summaryrefslogtreecommitdiffstats
path: root/pki/base/tps/src/engine/RA.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'pki/base/tps/src/engine/RA.cpp')
-rw-r--r--pki/base/tps/src/engine/RA.cpp2306
1 files changed, 2306 insertions, 0 deletions
diff --git a/pki/base/tps/src/engine/RA.cpp b/pki/base/tps/src/engine/RA.cpp
new file mode 100644
index 000000000..be17177f0
--- /dev/null
+++ b/pki/base/tps/src/engine/RA.cpp
@@ -0,0 +1,2306 @@
+// --- 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 <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "prmem.h"
+#include "prsystem.h"
+#include "plstr.h"
+#include "prio.h"
+#include "prprf.h"
+#include "plhash.h"
+#include "pk11func.h"
+#include "cert.h"
+#include "tus/tus_db.h"
+#include "secder.h"
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#include "main/Memory.h"
+#include "main/ConfigStore.h"
+#include "main/RA_Context.h"
+#include "channel/Secure_Channel.h"
+#include "engine/RA.h"
+#include "main/Util.h"
+#include "cms/HttpConnection.h"
+#include "main/RA_pblock.h"
+
+
+static ConfigStore *m_cfg = NULL;
+static PRFileDesc *m_fd_debug = (PRFileDesc *)NULL;
+static PRFileDesc *m_fd_audit = (PRFileDesc *)NULL;
+static PRFileDesc *m_fd_error = (PRFileDesc *)NULL;
+
+static int tokendbInitialized = 0;
+
+bool RA::m_pod_enable=false;
+int RA::m_pod_curr = 0;
+PRLock *RA::m_pod_lock = NULL;
+int RA::m_auth_curr;
+PRLock *RA::m_verify_lock = NULL;
+PRLock *RA::m_auth_lock = NULL;
+PRLock *RA::m_debug_log_lock = NULL;
+PRLock *RA::m_error_log_lock = NULL;
+PRLock *RA::m_audit_log_lock = NULL;
+SecurityLevel RA::m_global_security_level;
+
+int RA::m_audit_log_level = (int) LL_PER_SERVER;
+int RA::m_debug_log_level = (int) LL_PER_SERVER;
+int RA::m_error_log_level = (int) LL_PER_SERVER;
+int RA::m_caConns_len = 0;
+int RA::m_tksConns_len = 0;
+int RA::m_drmConns_len = 0;
+int RA::m_auth_len = 0;
+
+#define MAX_BODY_LEN 4096
+
+#define MAX_CA_CONNECTIONS 20
+#define MAX_TKS_CONNECTIONS 20
+#define MAX_DRM_CONNECTIONS 20
+#define MAX_AUTH_LIST_MEMBERS 20
+HttpConnection* RA::m_caConnection[MAX_CA_CONNECTIONS];
+HttpConnection* RA::m_tksConnection[MAX_TKS_CONNECTIONS];
+AuthenticationEntry* RA::m_auth_list[MAX_AUTH_LIST_MEMBERS];
+HttpConnection* RA::m_drmConnection[MAX_DRM_CONNECTIONS];
+int RA::m_num_publishers = 0;
+PublisherEntry *RA::publisher_list = NULL;
+
+/* TKS response parameters */
+const char *RA::TKS_RESPONSE_STATUS = "status";
+const char *RA::TKS_RESPONSE_SessionKey = "sessionKey";
+const char *RA::TKS_RESPONSE_EncSessionKey = "encSessionKey";
+const char *RA::TKS_RESPONSE_KEK_DesKey = "kek_wrapped_desKey";
+const char *RA::TKS_RESPONSE_DRM_Trans_DesKey = "drm_trans_wrapped_desKey";
+const char *RA::TKS_RESPONSE_HostCryptogram = "hostCryptogram";
+
+const char *RA::CFG_DEBUG_ENABLE = "logging.debug.enable";
+const char *RA::CFG_DEBUG_FILENAME = "logging.debug.filename";
+const char *RA::CFG_DEBUG_LEVEL = "logging.debug.level";
+const char *RA::CFG_AUDIT_ENABLE = "logging.audit.enable";
+const char *RA::CFG_AUDIT_FILENAME = "logging.audit.filename";
+const char *RA::CFG_AUDIT_LEVEL = "logging.audit.level";
+const char *RA::CFG_ERROR_ENABLE = "logging.error.enable";
+const char *RA::CFG_ERROR_FILENAME = "logging.error.filename";
+const char *RA::CFG_ERROR_LEVEL = "logging.error.level";
+const char *RA::CFG_CHANNEL_SEC_LEVEL = "channel.securityLevel";
+const char *RA::CFG_CHANNEL_ENCRYPTION = "channel.encryption";
+const char *RA::CFG_APPLET_CARDMGR_INSTANCE_AID = "applet.aid.cardmgr_instance";
+const char *RA::CFG_APPLET_NETKEY_INSTANCE_AID = "applet.aid.netkey_instance";
+const char *RA::CFG_APPLET_NETKEY_FILE_AID = "applet.aid.netkey_file";
+const char *RA::CFG_APPLET_NETKEY_OLD_INSTANCE_AID = "applet.aid.netkey_old_instance";
+const char *RA::CFG_APPLET_NETKEY_OLD_FILE_AID = "applet.aid.netkey_old_file";
+const char *RA::CFG_APPLET_SO_PIN = "applet.so_pin";
+const char *RA::CFG_APPLET_DELETE_NETKEY_OLD = "applet.delete_old";
+
+const char *RA::CFG_AUTHS_ENABLE="auth.enable";
+
+/* default values */
+const char *RA::CFG_DEF_CARDMGR_INSTANCE_AID = "A0000000030000";
+const char *RA::CFG_DEF_NETKEY_INSTANCE_AID = "627601FF000000";
+const char *RA::CFG_DEF_NETKEY_FILE_AID = "627601FF0000";
+const char *RA::CFG_DEF_NETKEY_OLD_INSTANCE_AID = "A00000000101";
+const char *RA::CFG_DEF_NETKEY_OLD_FILE_AID = "A000000001";
+const char *RA::CFG_DEF_APPLET_SO_PIN = "000000000000";
+
+typedef IPublisher* (*makepublisher)();
+typedef Authentication* (*makeauthentication)();
+
+extern void BuildHostPortLists(char *host, char *port, char **hostList,
+ char **portList, int len);
+
+#ifdef XP_WIN32
+#define TPS_PUBLIC __declspec(dllexport)
+#else /* !XP_WIN32 */
+#define TPS_PUBLIC
+#endif /* !XP_WIN32 */
+
+/**
+ * Constructs a Registration Authority object.
+ */
+RA::RA ()
+{
+}
+
+/**
+ * Destructs a Registration Authority object.
+ */
+RA::~RA ()
+{
+}
+
+TPS_PUBLIC ConfigStore *RA::GetConfigStore()
+{
+ return m_cfg;
+}
+
+PRLock *RA::GetVerifyLock()
+{
+ return m_verify_lock;
+}
+
+/**
+ * Initializes RA with the given configuration file.
+ */
+TPS_PUBLIC int RA::Initialize(char *cfg_path, RA_Context *ctx)
+{
+ int ca_status = 0;
+ int tks_status = 0;
+ int drm_status = 0;
+
+ int rc = -1;
+ int i = 0;
+
+ // Authentication *auth;
+ // int secLevel = 0; // for getting config param
+ bool global_enc = false;
+ SecurityLevel security_level = SECURE_MSG_MAC_ENC;
+
+ m_verify_lock = PR_NewLock();
+ m_debug_log_lock = PR_NewLock();
+ m_audit_log_lock = PR_NewLock();
+ m_error_log_lock = PR_NewLock();
+ m_cfg = ConfigStore::CreateFromConfigFile(cfg_path);
+ if( m_cfg == NULL ) {
+ rc = -2;
+ goto loser;
+ }
+
+ if (m_cfg->GetConfigAsBool(CFG_DEBUG_ENABLE, 0)) {
+ m_fd_debug = PR_Open(
+ m_cfg->GetConfigAsString(CFG_DEBUG_FILENAME,
+ "/tmp/debug.log"),
+ PR_RDWR | PR_CREATE_FILE | PR_APPEND,
+ 440 | 220);
+ if (m_fd_debug == NULL)
+ goto loser;
+ }
+
+ if (m_cfg->GetConfigAsBool(CFG_AUDIT_ENABLE, 0)) {
+ m_fd_audit = PR_Open(
+ m_cfg->GetConfigAsString(CFG_AUDIT_FILENAME,
+ "/tmp/audit.log"),
+ PR_RDWR | PR_CREATE_FILE | PR_APPEND,
+ 440 | 220);
+ if (m_fd_audit == NULL)
+ goto loser;
+ }
+
+ if (m_cfg->GetConfigAsBool(CFG_ERROR_ENABLE, 0)) {
+ m_fd_error = PR_Open(
+ m_cfg->GetConfigAsString(CFG_ERROR_FILENAME,
+ "/tmp/error.log"),
+ PR_RDWR | PR_CREATE_FILE | PR_APPEND,
+ 440 | 220);
+ if (m_fd_error == NULL)
+ goto loser;
+ }
+
+ m_audit_log_level = m_cfg->GetConfigAsInt(CFG_AUDIT_LEVEL, (int) LL_PER_SERVER);
+ m_debug_log_level = m_cfg->GetConfigAsInt(CFG_DEBUG_LEVEL, (int) LL_PER_SERVER);
+ m_error_log_level = m_cfg->GetConfigAsInt(CFG_ERROR_LEVEL, (int) LL_PER_SERVER);
+
+ RA::Debug("RA:: Initialize", "CS TPS starting...");
+
+ rc = InitializeTokendb(cfg_path);
+ if( rc != LDAP_SUCCESS ) {
+ RA::Debug("RA:: Initialize", "Token DB initialization failed, server continues");
+ ctx->LogError( "RA::Initialize",
+ __LINE__,
+ "The TPS plugin could NOT load the "
+ "Tokendb library! See specific details in the "
+ "TPS plugin log files." );
+ // Since the server hasn't started yet, there is
+ // no need to perform a call to RA::Shutdown()!
+ //goto loser;
+ } else
+ RA::Debug("RA:: Initialize", "Token DB initialization succeeded");
+
+ //testTokendb();
+
+ m_pod_enable = m_cfg->GetConfigAsBool("failover.pod.enable", false);
+ m_pod_curr = 0;
+ m_auth_curr = 0;
+ m_pod_lock = PR_NewLock();
+ m_auth_lock = PR_NewLock();
+
+
+ // make encryption not default for operations globally
+ // individual security levels can override
+ // secLevel = RA::GetConfigAsInt(RA::CFG_CHANNEL_SEC_LEVEL,
+ // SECURE_MSG_MAC);
+
+ global_enc = m_cfg->GetConfigAsBool(RA::CFG_CHANNEL_ENCRYPTION, true);
+ if (global_enc == true)
+ security_level = SECURE_MSG_MAC_ENC;
+ else
+ security_level = SECURE_MSG_MAC;
+
+ RA::SetGlobalSecurityLevel(security_level);
+
+ // Initialize the CA connection pool to be empty
+ for (i=0; i<MAX_CA_CONNECTIONS; i++) {
+ m_caConnection[i] = NULL;
+ }
+
+ // Initialize the TKS connection pool to be empty
+ for (i=0; i<MAX_TKS_CONNECTIONS; i++) {
+ m_tksConnection[i] = NULL;
+ }
+
+ // Initialize the DRM connection pool to be empty
+ for (i=0; i<MAX_DRM_CONNECTIONS; i++) {
+ m_drmConnection[i] = NULL;
+ }
+
+ // Initialize the authentication list to be empty
+ for (i=0; i<MAX_AUTH_LIST_MEMBERS; i++) {
+ m_auth_list[i] = NULL;
+ }
+
+ // even rc != 0, we still go ahead starting up the server.
+ rc = InitializeAuthentication();
+
+ // initialize CA connections
+ ca_status = InitializeHttpConnections("ca", &m_caConns_len,
+ m_caConnection, ctx);
+
+ if( ca_status != 0 ) {
+#if 0
+ RA::Shutdown();
+ goto loser;
+#endif
+ }
+
+ // initialize TKS connections
+ tks_status = InitializeHttpConnections("tks", &m_tksConns_len,
+ m_tksConnection, ctx);
+
+ if( tks_status != 0 ) {
+#if 0
+ RA::Shutdown();
+ goto loser;
+#endif
+ }
+
+ // initialize DRM connections
+ drm_status = InitializeHttpConnections("drm", &m_drmConns_len,
+ m_drmConnection, ctx);
+
+ if( drm_status != 0 ) {
+#if 0
+ RA::Shutdown();
+ goto loser;
+#endif
+ }
+
+ //Initialize Publisher Library
+ InitializePublishers();
+
+ rc = 1;
+loser:
+
+ // Log the status of this TPS plugin into the web server's log:
+ if( rc != 1 ) {
+ ctx->LogError( "RA::Initialize",
+ __LINE__,
+ "The TPS plugin could NOT be "
+ "loaded (rc = %d)! See specific details in the "
+ "TPS plugin log files.", rc );
+ } else {
+ ctx->LogInfo( "RA::Initialize",
+ __LINE__,
+ "The TPS plugin was "
+ "successfully loaded!" );
+ }
+
+ return rc;
+}
+
+
+int RA::testTokendb() {
+ // try to see if we can talk to the database
+ int st = 0;
+ LDAPMessage *ldapResult = NULL;
+ const char * filter = "(cn=0000000000080000*)";
+
+ if ((st = find_tus_db_entries(filter, 0, &ldapResult)) != LDAP_SUCCESS) {
+ RA::Debug("RA::testing", "response from token DB failed");
+ } else {
+ RA::Debug("RA::testing", "response from token DB succeeded");
+ }
+
+ return st;
+}
+
+int RA::IsTokendbInitialized()
+{
+ return tokendbInitialized;
+}
+
+
+/**
+ * Shutdown RA.
+ */
+TPS_PUBLIC int RA::Shutdown()
+{
+
+ tus_db_end();
+
+ if( m_pod_lock != NULL ) {
+ PR_DestroyLock( m_pod_lock );
+ m_pod_lock = NULL;
+ }
+
+ if( m_auth_lock != NULL ) {
+ PR_DestroyLock( m_auth_lock );
+ m_auth_lock = NULL;
+ }
+
+ if (m_caConnection != NULL) {
+ for (int i=0; i<m_caConns_len; i++) {
+ if( m_caConnection[i] != NULL ) {
+ delete m_caConnection[i];
+ m_caConnection[i] = NULL;
+ }
+ }
+ }
+
+ if (m_tksConnection != NULL) {
+ for (int i=0; i<m_tksConns_len; i++) {
+ if( m_tksConnection[i] != NULL ) {
+ delete m_tksConnection[i];
+ m_tksConnection[i] = NULL;
+ }
+ }
+ }
+ if (m_drmConnection != NULL) {
+ for (int i=0; i<m_drmConns_len; i++) {
+ if( m_drmConnection[i] != NULL ) {
+ delete m_drmConnection[i];
+ m_drmConnection[i] = NULL;
+ }
+ }
+ }
+
+ /* close debug file if opened */
+ if( m_fd_debug != NULL ) {
+ PR_Close( m_fd_debug );
+ m_fd_debug = NULL;
+ }
+
+ /* close audit file if opened */
+ if( m_fd_audit != NULL ) {
+ PR_Close( m_fd_audit );
+ m_fd_audit = NULL;
+ }
+
+ /* close error file if opened */
+ if( m_fd_error != NULL ) {
+ PR_Close( m_fd_error );
+ m_fd_error = NULL;
+ }
+
+ if( m_verify_lock != NULL ) {
+ PR_DestroyLock( m_verify_lock );
+ m_verify_lock = NULL;
+ }
+
+ if( m_debug_log_lock != NULL ) {
+ PR_DestroyLock( m_debug_log_lock );
+ m_debug_log_lock = NULL;
+ }
+
+ if( m_audit_log_lock != NULL ) {
+ PR_DestroyLock( m_audit_log_lock );
+ m_audit_log_lock = NULL;
+ }
+
+ if( m_error_log_lock != NULL ) {
+ PR_DestroyLock( m_error_log_lock );
+ m_error_log_lock = NULL;
+ }
+
+ if (m_auth_list != NULL) {
+ for (int i=0; i<m_auth_len; i++) {
+ if( m_auth_list[i] != NULL ) {
+ delete m_auth_list[i];
+ m_auth_list[i] = NULL;
+ }
+ }
+ }
+
+ /* destroy configuration hashtable */
+ if( m_cfg != NULL ) {
+ delete m_cfg;
+ m_cfg = NULL;
+ }
+
+ CleanupPublishers();
+
+ return 1;
+}
+
+HttpConnection *RA::GetTKSConn(const char *id) {
+ HttpConnection *tksconn = NULL;
+ for (int i=0; i<m_tksConns_len; i++) {
+ if (strcmp(m_tksConnection[i]->GetId(), id) == 0) {
+ tksconn = m_tksConnection[i];
+ break;
+ }
+ }
+ return tksconn;
+}
+
+HttpConnection *RA::GetDRMConn(const char *id) {
+ HttpConnection *drmconn = NULL;
+ for (int i=0; i<m_drmConns_len; i++) {
+ if (strcmp(m_drmConnection[i]->GetId(), id) == 0) {
+ drmconn = m_drmConnection[i];
+ break;
+ }
+ }
+ return drmconn;
+}
+
+void RA::ReturnTKSConn(HttpConnection *conn) {
+ // do nothing for now
+}
+
+void RA::ReturnDRMConn(HttpConnection *conn) {
+ // do nothing for now
+}
+
+HttpConnection *RA::GetCAConn(const char *id) {
+ HttpConnection *caconn = NULL;
+ if (id == NULL)
+ return NULL;
+ for (int i=0; i<m_caConns_len; i++) {
+ if (strcmp(m_caConnection[i]->GetId(), id) == 0) {
+ caconn = m_caConnection[i];
+ break;
+ }
+ }
+ return caconn;
+}
+
+AuthenticationEntry *RA::GetAuth(const char *id) {
+ AuthenticationEntry *authEntry = NULL;
+ for (int i=0; i<m_auth_len; i++) {
+ authEntry = m_auth_list[i];
+ if (strcmp(authEntry->GetId(), id) == 0)
+ return authEntry;
+ }
+ return NULL;
+}
+
+void RA::ReturnCAConn(HttpConnection *conn) {
+ // do nothing for now
+}
+
+TPS_PUBLIC PRLock *RA::GetAuthLock() {
+ return m_auth_lock;
+}
+
+int RA::GetPodIndex() {
+ PR_Lock(m_pod_lock);
+ int index = m_pod_curr;
+ PR_Unlock(m_pod_lock);
+ return index;
+}
+
+void RA::SetPodIndex(int index) {
+ PR_Lock(m_pod_lock);
+ m_pod_curr = index;
+ PR_Unlock(m_pod_lock);
+}
+
+void RA::SetCurrentIndex(HttpConnection *&conn, int index) {
+ PRLock *lock = conn->GetLock();
+ PR_Lock(lock);
+ conn->SetCurrentIndex(index);
+ PR_Unlock(lock);
+}
+
+int RA::GetCurrentIndex(HttpConnection *conn) {
+ PRLock *lock = conn->GetLock();
+ PR_Lock(lock);
+ int index = conn->GetCurrentIndex();
+ PR_Unlock(lock);
+ return index;
+}
+
+TPS_PUBLIC int RA::GetAuthCurrentIndex() {
+ PR_Lock(m_auth_lock);
+ int index = m_auth_curr;
+ PR_Unlock(m_auth_lock);
+ return index;
+}
+
+void RA::SetAuthCurrentIndex(int index) {
+ PR_Lock(m_auth_lock);
+ m_auth_curr = index;
+ PR_Unlock(m_auth_lock);
+}
+
+TPS_PUBLIC void RA::IncrementAuthCurrentIndex(int len) {
+ PR_Lock(m_auth_lock);
+ if ((++m_auth_curr) >= len)
+ m_auth_curr = 0;
+ PR_Unlock(m_auth_lock);
+}
+
+void RA::SetGlobalSecurityLevel(SecurityLevel sl) {
+ m_global_security_level = sl;
+ RA::Debug(" RA::SetGlobalSecurityLevel", "global security level set to %d", (int) sl);
+
+}
+
+SecurityLevel RA::GetGlobalSecurityLevel() {
+ return m_global_security_level;
+}
+
+
+/*
+ * recovers user encryption key that was previously archived.
+ * It expects DRM to search its archival db by cert.
+ *
+ * input:
+ * @param cuid (cuid of the recovering key's token)
+ * @param userid (uid of the recovering key owner
+ * @param desKey_s (came from TKS - session key wrapped with DRM transport
+ * @param cert (base64 encoded cert of the recovering key)
+ * @param connId (drm connectoin id)
+ *
+ * output:
+ * @param publickey_s public key provided by DRM
+ * @param wrappedPrivateKey_s encrypted private key provided by DRM
+ */
+void RA::RecoverKey(RA_Session *session, const char* cuid,
+ const char *userid, char* desKey_s,
+ char *b64cert, char **publicKey_s,
+ char **wrappedPrivateKey_s, const char *connId)
+{
+ int status;
+ PSHttpResponse *response = NULL;
+ HttpConnection *drmConn = NULL;
+ char body[MAX_BODY_LEN];
+ char configname[256];
+ char * cert_s;
+ int drm_curr = 0;
+ long s;
+ char * content = NULL;
+ char ** hostport= NULL;
+ const char* servletID = NULL;
+ char *wrappedDESKey_s= NULL;
+ Buffer *decodeKey = NULL;
+ ConnectionInfo *connInfo = NULL;
+ RA_pblock *ra_pb = NULL;
+ int currRetries = 0;
+ char *p = NULL;
+
+ RA::Debug(" RA:: RecoverKey", "in RecoverKey");
+ if (cuid == NULL) {
+ RA::Debug(" RA:: RecoverKey", "in RecoverKey, cuid NULL");
+ goto loser;
+ }
+ if (userid == NULL) {
+ RA::Debug(" RA:: RecoverKey", "in RecoverKey, userid NULL");
+ goto loser;
+ }
+ if (b64cert == NULL) {
+ RA::Debug(" RA:: RecoverKey", "in RecoverKey, b64cert NULL");
+ goto loser;
+ }
+ if (desKey_s == NULL) {
+ RA::Debug(" RA:: RecoverKey", "in RecoverKey, desKey_s NULL");
+ goto loser;
+ }
+ if (connId == NULL) {
+ RA::Debug(" RA:: RecoverKey", "in RecoverKey, connId NULL");
+ goto loser;
+ }
+ RA::Debug(" RA:: RecoverKey", "in RecoverKey, desKey_s=%s, connId=%s",desKey_s, connId);
+
+ cert_s = Util::URLEncode(b64cert);
+ drmConn = RA::GetDRMConn(connId);
+ if (drmConn == NULL) {
+ RA::Debug(" RA:: RecoverKey", "in RecoverKey, failed getting drmconn");
+ goto loser;
+ }
+ RA::Debug(" RA:: RecoverKey", "in RecoverKey, got drmconn");
+ connInfo = drmConn->GetFailoverList();
+ RA::Debug(" RA:: RecoverKey", "in RecoverKey, got drm failover");
+ decodeKey = Util::URLDecode(desKey_s);
+ RA::Debug(" RA:: RecoverKey", "in RecoverKey,url decoded des");
+ wrappedDESKey_s = Util::SpecialURLEncode(*decodeKey);
+
+ RA::Debug(" RA:: RecoverKey", "in RecoverKey, wrappedDESKey_s=%s", wrappedDESKey_s);
+
+ PR_snprintf((char *)body, MAX_BODY_LEN,
+ "CUID=%s&userid=%s&drm_trans_desKey=%s&cert=%s",cuid, userid, wrappedDESKey_s, cert_s);
+ RA::Debug(" RA:: RecoverKey", "in RecoverKey, body=%s", body);
+ PR_snprintf((char *)configname, 256, "conn.%s.servlet.TokenKeyRecovery", connId);
+ servletID = GetConfigStore()->GetConfigAsString(configname);
+ RA::Debug(" RA:: RecoverKey", "in RecoverKey, configname=%s", configname);
+
+ drm_curr = RA::GetCurrentIndex(drmConn);
+ response = drmConn->getResponse(drm_curr, servletID, body);
+ hostport = connInfo->GetHostPortList();
+ if (response == NULL) {
+ RA::Debug(LL_PER_PDU, "The recoverKey response from DRM ",
+ "at %s is NULL.", hostport[drm_curr]);
+
+ //goto loser;
+ } else {
+ RA::Debug(LL_PER_PDU, "The recoverKey response from DRM ",
+ "at %s is not NULL.", hostport[drm_curr]);
+ }
+
+ while (response == NULL) {
+ RA::Failover(drmConn, connInfo->GetHostPortListLen());
+
+ drm_curr = RA::GetCurrentIndex(drmConn);
+ RA::Debug(LL_PER_PDU, "RA is reconnecting to DRM ",
+ "at %s for recoverKey.", hostport[drm_curr]);
+
+ if (++currRetries >= drmConn->GetNumOfRetries()) {
+ RA::Debug("Used up all the retries in recoverKey. Response is NULL","");
+ RA::Error("RA::RecoverKey","Failed connecting to DRM after %d retries", currRetries);
+
+ goto loser;
+ }
+ response = drmConn->getResponse(drm_curr, servletID, body);
+ }
+
+ RA::Debug(" RA:: RecoverKey", "in RecoverKey - got response");
+ // XXXskip handling fallback host for prototype
+
+ content = response->getContent();
+ p = strstr(content, "status=");
+ content = p; //skip the HTTP header
+
+ s = response->getStatus();
+
+ if ((content != NULL) && (s == 200)) {
+ RA::Debug("RA::RecoverKey", "response from DRM status ok");
+
+ Buffer* status_b;
+ char* status_s;
+
+ ra_pb = ( RA_pblock * ) session->create_pblock(content);
+ if (ra_pb == NULL)
+ goto loser;
+
+ status_b = ra_pb->find_val("status");
+ if (status_b == NULL) {
+ status = 4;
+ goto loser;
+ }
+ else {
+ status_s = status_b->string();
+ status = atoi(status_s);
+ }
+
+
+ char * tmp = NULL;
+ tmp = ra_pb->find_val_s("public_key");
+ if ((tmp == NULL) || (tmp == "")) {
+ RA::Error(LL_PER_PDU, "RecoverKey"," got no public key");
+ goto loser;
+ } else {
+ RA::Debug(LL_PER_PDU, "RecoverKey", "got public key =%s", tmp);
+ *publicKey_s = PL_strdup(tmp);
+ }
+
+ tmp = NULL;
+ tmp = ra_pb->find_val_s("wrapped_priv_key");
+ if ((tmp == NULL) || (tmp == "")) {
+ RA::Error(LL_PER_PDU, "RecoverKey"," got no wrapped private key");
+ //XXX goto loser;
+ } else {
+ RA::Debug(LL_PER_PDU, "RecoverKey", "got wrappedprivate key =%s", tmp);
+ *wrappedPrivateKey_s = PL_strdup(tmp);
+ }
+
+ } else {// if content is NULL or status not 200
+ if (content != NULL)
+ RA::Debug("RA::RecoverKey", "response from DRM error status %ld", s);
+ else
+ RA::Debug("RA::RecoverKey", "response from DRM no content");
+ }
+ loser:
+ if (desKey_s != NULL)
+ PR_Free(desKey_s);
+
+ if (decodeKey != NULL)
+ PR_Free(decodeKey);
+
+ if (wrappedDESKey_s != NULL)
+ PR_Free(wrappedDESKey_s);
+
+ if (drmConn != NULL)
+ RA::ReturnDRMConn(drmConn);
+
+ if (response != NULL) {
+ if (content != NULL)
+ response->freeContent();
+ delete response;
+ }
+
+ if (ra_pb != NULL) {
+ delete ra_pb;
+ }
+
+}
+
+
+
+/*
+ * input:
+ * @param desKey_s provided for drm to wrap user private
+ * @param publicKey_s returned for key injection back to token
+ *
+ * Output:
+ * @param publicKey_s public key provided by DRM
+ * @param wrappedPrivateKey_s encrypted private key provided by DRM
+ */
+void RA::ServerSideKeyGen(RA_Session *session, const char* cuid,
+ const char *userid, char* desKey_s,
+ char **publicKey_s,
+ char **wrappedPrivateKey_s,
+ char **ivParam_s, const char *connId,
+ bool archive, int keysize)
+{
+
+ const char *FN="RA::ServerSideKeyGen";
+ int status;
+ PSHttpResponse *response = NULL;
+ HttpConnection *drmConn = NULL;
+ char body[MAX_BODY_LEN];
+ char configname[256];
+
+ long s;
+ char * content = NULL;
+ char ** hostport = NULL;
+ const char* servletID = NULL;
+ char *wrappedDESKey_s = NULL;
+ Buffer *decodeKey = NULL;
+ ConnectionInfo *connInfo = NULL;
+ RA_pblock *ra_pb = NULL;
+ int drm_curr = 0;
+ int currRetries = 0;
+ char *p = NULL;
+
+ if ((cuid == NULL) || (cuid == "")) {
+ RA::Debug( LL_PER_CONNECTION, FN,
+ "error: passed invalid cuid");
+ goto loser;
+ }
+ if ((userid == NULL) || (userid =="")) {
+ RA::Debug(LL_PER_CONNECTION, FN,
+ "error: passed invalid userid");
+ goto loser;
+ }
+ if ((desKey_s == NULL) || (desKey_s =="")) {
+ RA::Debug(LL_PER_CONNECTION, FN,
+ "error: passed invalid desKey_s");
+ goto loser;
+ }
+ if ((connId == NULL) ||(connId == "")) {
+ RA::Debug(LL_PER_CONNECTION, FN,
+ "error: passed invalid connId");
+ goto loser;
+ }
+ RA::Debug(LL_PER_CONNECTION, FN,
+ "desKey_s=%s, connId=%s",desKey_s, connId);
+ drmConn = RA::GetDRMConn(connId);
+
+ if (drmConn == NULL) {
+ RA::Debug(LL_PER_CONNECTION, FN,
+ "drmconn is null");
+ goto loser;
+ }
+ RA::Debug(LL_PER_CONNECTION, FN,
+ "found DRM connection info");
+ connInfo = drmConn->GetFailoverList();
+ RA::Debug(LL_PER_CONNECTION, FN,
+ "got DRM failover list");
+
+ decodeKey = Util::URLDecode(desKey_s);
+ if (decodeKey == NULL) {
+ RA::Debug(LL_PER_CONNECTION, FN,
+ "url-decoding of des key-transport-key failed");
+ goto loser;
+ }
+ RA::Debug(LL_PER_CONNECTION, FN,
+ "successfully url-decoded key-transport-key");
+ wrappedDESKey_s = Util::SpecialURLEncode(*decodeKey);
+
+ RA::Debug(LL_PER_CONNECTION, FN,
+ "wrappedDESKey_s=%s", wrappedDESKey_s);
+
+ PR_snprintf((char *)body, MAX_BODY_LEN,
+ "archive=%s&CUID=%s&userid=%s&keysize=%d&drm_trans_desKey=%s",archive?"true":"false",cuid, userid, keysize, wrappedDESKey_s);
+ RA::Debug(LL_PER_CONNECTION, FN,
+ "sending to DRM: query=%s", body);
+
+ PR_snprintf((char *)configname, 256, "conn.%s.servlet.GenerateKeyPair", connId);
+ servletID = GetConfigStore()->GetConfigAsString(configname);
+ RA::Debug(LL_PER_CONNECTION, FN,
+ "finding DRM servlet info, configname=%s", configname);
+
+ drm_curr = RA::GetCurrentIndex(drmConn);
+ response = drmConn->getResponse(drm_curr, servletID, body);
+ hostport = connInfo->GetHostPortList();
+ if (response == NULL) {
+ RA::Error(LL_PER_CONNECTION, FN,
+ "failed to get response from DRM at %s",
+ hostport[drm_curr]);
+ RA::Debug(LL_PER_CONNECTION, FN,
+ "failed to get response from DRM at %s",
+ hostport[drm_curr]);
+ } else {
+ RA::Debug(LL_PER_CONNECTION, FN,
+ "response from DRM (%s) is not NULL.",
+ hostport[drm_curr]);
+ }
+
+ while (response == NULL) {
+ RA::Failover(drmConn, connInfo->GetHostPortListLen());
+
+ drm_curr = RA::GetCurrentIndex(drmConn);
+ RA::Debug(LL_PER_CONNECTION, FN,
+ "RA is failing over to DRM at %s", hostport[drm_curr]);
+
+ if (++currRetries >= drmConn->GetNumOfRetries()) {
+ RA::Debug(LL_PER_CONNECTION, FN,
+ "Failed to get response from all DRMs in conn group '%s'"
+ " after %d retries", connId, currRetries);
+ RA::Error(LL_PER_CONNECTION, FN,
+ "Failed to get response from all DRMs in conn group '%s'"
+ " after %d retries", connId, currRetries);
+
+
+ goto loser;
+ }
+ response = drmConn->getResponse(drm_curr, servletID, body);
+ }
+
+ RA::Debug(" RA:: ServerSideKeyGen", "in ServerSideKeyGen - got response");
+ // XXX skip handling fallback host for prototype
+
+ content = response->getContent();
+ p = strstr(content, "status=");
+ content = p; //skip the HTTP header
+ s = response->getStatus();
+
+ if ((content != NULL) && (s == 200)) {
+ RA::Debug("RA::ServerSideKeyGen", "response from DRM status ok");
+
+ Buffer* status_b;
+ char* status_s;
+
+ ra_pb = ( RA_pblock * ) session->create_pblock(content);
+ if (ra_pb == NULL)
+ goto loser;
+
+ status_b = ra_pb->find_val("status");
+ if (status_b == NULL) {
+ status = 4;
+ goto loser;
+ } else {
+ status_s = status_b->string();
+ status = atoi(status_s);
+ }
+
+ char * tmp = NULL;
+ tmp = ra_pb->find_val_s("public_key");
+ if (tmp == NULL) {
+ RA::Error(LL_PER_CONNECTION, FN,
+ "Did not get public key in DRM response");
+ } else {
+ RA::Debug(LL_PER_PDU, "ServerSideKeyGen", "got public key =%s", tmp);
+ *publicKey_s = PL_strdup(tmp);
+ }
+
+ tmp = NULL;
+ tmp = ra_pb->find_val_s("wrapped_priv_key");
+ if ((tmp == NULL) || (tmp == "")) {
+ RA::Error(LL_PER_CONNECTION, FN,
+ "did not get wrapped private key in DRM response");
+ } else {
+ RA::Debug(LL_PER_CONNECTION, FN,
+ "got wrappedprivate key =%s", tmp);
+ *wrappedPrivateKey_s = PL_strdup(tmp);
+ }
+
+ tmp = ra_pb->find_val_s("iv_param");
+ if ((tmp == NULL) || (tmp == "")) {
+ RA::Error(LL_PER_CONNECTION, FN,
+ "did not get iv_param for private key in DRM response");
+ } else {
+ RA::Debug(LL_PER_PDU, "ServerSideKeyGen", "got iv_param for private key =%s", tmp);
+ *ivParam_s = PL_strdup(tmp);
+ }
+
+ } else {// if content is NULL or status not 200
+ if (content != NULL)
+ RA::Debug("RA::ServerSideKeyGen", "response from DRM error status %ld", s);
+ else
+ RA::Debug("RA::ServerSideKeyGen", "response from DRM no content");
+ }
+
+ loser:
+ if (desKey_s != NULL)
+ PR_Free(desKey_s);
+
+ if (decodeKey != NULL) {
+ delete decodeKey;
+ }
+
+ if (wrappedDESKey_s != NULL)
+ PR_Free(wrappedDESKey_s);
+
+ if (drmConn != NULL)
+ RA::ReturnDRMConn(drmConn);
+
+ if (response != NULL) {
+ if (content != NULL)
+ response->freeContent();
+ delete response;
+ }
+
+ if (ra_pb != NULL) {
+ delete ra_pb;
+ }
+
+}
+
+
+#define DES2_WORKAROUND
+#define MAX_BODY_LEN 4096
+
+PK11SymKey *RA::ComputeSessionKey(RA_Session *session,
+ Buffer &CUID,
+ Buffer &keyInfo,
+ Buffer &card_challenge,
+ Buffer &host_challenge,
+ Buffer **host_cryptogram,
+ Buffer &card_cryptogram,
+ PK11SymKey **encSymKey,
+ char** drm_desKey_s,
+ char** kek_desKey_s,
+ char** keycheck_s,
+ const char *connId)
+{
+ PK11SymKey *symKey = NULL;
+ char body[MAX_BODY_LEN];
+ char configname[256];
+ char * cardc = NULL;
+ char * hostc = NULL;
+ char * cardCrypto = NULL;
+ char * cuid = NULL;
+ char * keyinfo = NULL;
+ PSHttpResponse *response = NULL;
+ HttpConnection *tksConn = NULL;
+ RA_pblock *ra_pb = NULL;
+
+ RA::Debug(LL_PER_PDU, "Start ComputeSessionKey", "");
+ tksConn = RA::GetTKSConn(connId);
+ if (tksConn == NULL) {
+ RA::Error(LL_PER_PDU, "RA::ComputeSessionKey", "Failed to get TKSConnection %s", connId);
+ return NULL;
+ } else {
+ int currRetries = 0;
+ ConnectionInfo *connInfo = tksConn->GetFailoverList();
+
+ PR_snprintf((char *) configname, 256, "conn.%s.keySet", connId);
+ const char *keySet = RA::GetConfigStore()->GetConfigAsString(configname, "defKeySet");
+ // is serversideKeygen on?
+ PR_snprintf((char *) configname, 256, "conn.%s.serverKeygen", connId);
+ bool serverKeygen = RA::GetConfigStore()->GetConfigAsBool(configname, false);
+ if (serverKeygen)
+ RA::Debug(LL_PER_PDU, "RA::ComputeSessionKey", "serverKeygen for %s is on", connId);
+ else
+ RA::Debug(LL_PER_PDU, "RA::ComputeSessionKey", "serverKeygen for %s is off", connId);
+
+ cardc = Util::SpecialURLEncode(card_challenge);
+ hostc = Util::SpecialURLEncode(host_challenge);
+ cardCrypto = Util::SpecialURLEncode(card_cryptogram);
+ cuid = Util::SpecialURLEncode(CUID);
+ keyinfo = Util::SpecialURLEncode(keyInfo);
+
+ if ((cardc == NULL) || (hostc == NULL) || (cardCrypto == NULL) ||
+ (cuid == NULL) || (keyinfo == NULL))
+ goto loser;
+
+ PR_snprintf((char *)body, MAX_BODY_LEN,
+ "serversideKeygen=%s&CUID=%s&card_challenge=%s&host_challenge=%s&KeyInfo=%s&card_cryptogram=%s&keySet=%s", serverKeygen? "true":"false", cuid,
+ cardc, hostc, keyinfo, cardCrypto, keySet);
+
+ PR_snprintf((char *)configname, 256, "conn.%s.servlet.computeSessionKey", connId);
+ const char *servletID = GetConfigStore()->GetConfigAsString(configname);
+ int tks_curr = RA::GetCurrentIndex(tksConn);
+ response = tksConn->getResponse(tks_curr, servletID, body);
+ char **hostport = connInfo->GetHostPortList();
+ if (response == NULL)
+ RA::Debug(LL_PER_PDU, "The computeSessionKey response from TKS ",
+ "at %s is NULL.", hostport[tks_curr]);
+ else
+ RA::Debug(LL_PER_PDU, "The computeSessionKey response from TKS ",
+ "at %s is not NULL.", hostport[tks_curr]);
+
+ while (response == NULL) {
+ RA::Failover(tksConn, connInfo->GetHostPortListLen());
+
+ tks_curr = RA::GetCurrentIndex(tksConn);
+ RA::Debug(LL_PER_PDU, "RA is reconnecting to TKS ",
+ "at %s for computeSessionKey.", hostport[tks_curr]);
+
+ if (++currRetries >= tksConn->GetNumOfRetries()) {
+ RA::Debug("Used up all the retries in ComputeSessionKey. Response is NULL","");
+ RA::Error("RA::ComputeSessionKey","Failed connecting to TKS after %d retries", currRetries);
+
+ goto loser;
+ }
+ response = tksConn->getResponse(tks_curr, servletID, body);
+ }
+
+ RA::Debug(LL_PER_PDU, "ComputeSessionKey Response is not ","NULL");
+ char * content = response->getContent();
+
+ PK11SlotInfo *slot = PK11_GetInternalKeySlot();
+
+ if (content != NULL) {
+ Buffer *status_b;
+
+ char *status_s, *sessionKey_s, *encSessionKey_s, *hostCryptogram_s;
+ int status;
+
+ /* strip the http header */
+ /* raidzilla 57722: strip the HTTP header and just pass
+ name value pairs into the pblock parsing code.
+ */
+ RA::Debug("RA::Engine", "Pre-processing content '%s", content);
+ char *cx = content;
+ while (cx[0] != '\0' && (!(cx[0] == '\r' && cx[1] == '\n' &&
+ cx[2] == '\r' && cx[3] == '\n')))
+ {
+ cx++;
+ }
+ if (cx[0] != '\0') {
+ cx+=4;
+ }
+ RA::Debug("RA::Engine", "Post-processing content '%s", cx);
+ ra_pb = ( RA_pblock * ) session->create_pblock(cx);
+ if (ra_pb == NULL) {
+ RA::Debug(LL_PER_PDU, "RA:ComputeSessionKey", "fail no ra_pb");
+ goto loser;
+ }
+
+ status_b = ra_pb->find_val(TKS_RESPONSE_STATUS);
+ if (status_b == NULL) {
+ status = 4;
+ RA::Error(LL_PER_SERVER, "RA:ComputeSessionKey", "Bad TKS Connection. Please make sure TKS is accessible by TPS.");
+ RA::Debug(LL_PER_PDU, "RA:ComputeSessionKey", "fail no status");
+ goto loser;
+ // return NULL;
+ }
+ else {
+ status_s = status_b->string();
+ status = atoi(status_s);
+ }
+
+ sessionKey_s = ra_pb->find_val_s(TKS_RESPONSE_SessionKey);
+ if (sessionKey_s == NULL) {
+ RA::Debug(LL_PER_PDU, "RA:ComputeSessionKey", "fail no sessionKey_b");
+ goto loser;
+ }
+
+ RA::Debug(LL_PER_PDU, "RA:ComputeSessionKey", "mac session key=%s", sessionKey_s);
+ Buffer *decodeKey = Util::URLDecode(sessionKey_s);
+
+ RA::Debug(LL_PER_PDU, "RA:ComputeSessionKey", "decodekey len=%d",decodeKey->size());
+
+ BYTE masterKeyData[24];
+ SECItem masterKeyItem = {siBuffer, masterKeyData, sizeof(masterKeyData)};
+ BYTE *keyData = (BYTE *)*decodeKey;
+ memcpy(masterKeyData, (char*)keyData, 16);
+ memcpy(masterKeyData+16, (char*)keyData, 8);
+
+ symKey = PK11_ImportSymKeyWithFlags(slot, CKM_DES3_ECB,
+ PK11_OriginGenerated, CKA_ENCRYPT, &masterKeyItem,
+ CKF_ENCRYPT, PR_FALSE, 0);
+
+ if( decodeKey != NULL ) {
+ delete decodeKey;
+ decodeKey = NULL;
+ }
+ if (symKey == NULL)
+ RA::Debug(LL_PER_PDU, "RA:ComputeSessionKey", "MAC Session key is NULL");
+
+
+ encSessionKey_s = ra_pb->find_val_s(TKS_RESPONSE_EncSessionKey);
+ if (encSessionKey_s == NULL) {
+ RA::Debug(LL_PER_PDU, "RA:ComputeSessionKey", "fail no encSessionKey_b");
+ goto loser;
+ }
+
+ RA::Debug(LL_PER_PDU, "RA:ComputeSessionKey", "encSessionKey=%s", encSessionKey_s);
+ Buffer *decodeEncKey = Util::URLDecode(encSessionKey_s);
+
+ RA::Debug(LL_PER_PDU, "RA:ComputeSessionKey",
+ "decodeEnckey len=%d",decodeEncKey->size());
+
+ BYTE masterEncKeyData[24];
+ SECItem masterEncKeyItem =
+ {siBuffer, masterEncKeyData, sizeof(masterEncKeyData)};
+ BYTE *EnckeyData = (BYTE *)*decodeEncKey;
+ memcpy(masterEncKeyData, (char*)EnckeyData, 16);
+ memcpy(masterEncKeyData+16, (char*)EnckeyData, 8);
+
+ *encSymKey =
+ PK11_ImportSymKeyWithFlags(slot, CKM_DES3_ECB,
+ PK11_OriginGenerated, CKA_ENCRYPT, &masterEncKeyItem,
+ CKF_ENCRYPT, PR_FALSE, 0);
+
+ if( decodeEncKey != NULL ) {
+ delete decodeEncKey;
+ decodeEncKey = NULL;
+ }
+
+ if (encSymKey == NULL)
+ RA::Debug(LL_PER_PDU, "RA:ComputeSessionKey", "encSessionKey is NULL");
+
+
+ if (serverKeygen) {
+ char * tmp= NULL;
+ tmp = ra_pb->find_val_s(TKS_RESPONSE_DRM_Trans_DesKey);
+ if (tmp == NULL) {
+ RA::Debug(LL_PER_PDU, "RA:ComputeSessionKey", "drm_desKey not retrieved");
+ RA::Error(LL_PER_PDU, "RA:ComputeSessionKey", "drm_desKey not retrieved");
+ goto loser;
+ } else {
+ *drm_desKey_s = PL_strdup(tmp);
+ }
+ // wrapped des key is to be sent to DRM "as is"
+ // thus should not be touched
+ RA::Debug(LL_PER_PDU, "RA:ComputeSessionKey", "drm_desKey=%s", *drm_desKey_s );
+
+ tmp = ra_pb->find_val_s(TKS_RESPONSE_KEK_DesKey);
+ if (tmp == NULL) {
+ RA::Debug(LL_PER_PDU, "RA:ComputeSessionKey", "kek-wrapped desKey not retrieved");
+ RA::Error(LL_PER_PDU, "RA:ComputeSessionKey", "kek-wrapped desKey not retrieved");
+ goto loser;
+ } else {
+ *kek_desKey_s = PL_strdup(tmp);
+ }
+ RA::Debug(LL_PER_PDU, "RA:ComputeSessionKey", "kek_desKey=%s", *kek_desKey_s );
+
+
+ tmp = ra_pb->find_val_s("keycheck");
+ if (tmp == NULL) {
+ RA::Debug(LL_PER_PDU, "RA:ComputeSessionKey", "keycheck not retrieved");
+ RA::Error(LL_PER_PDU, "RA:ComputeSessionKey", "keycheck not retrieved");
+ goto loser;
+ } else {
+ *keycheck_s = PL_strdup(tmp);
+ }
+ }// serversideKeygen
+
+ hostCryptogram_s = ra_pb->find_val_s(TKS_RESPONSE_HostCryptogram);
+ if (hostCryptogram_s == NULL)
+ goto loser;
+
+ RA::Debug(LL_PER_PDU, "RA:ComputeSessionKey", "hostC=%s", hostCryptogram_s);
+ *host_cryptogram = Util::URLDecode(hostCryptogram_s);
+ } // if content != NULL
+
+ } // else tksConn != NULL
+ RA::Debug(LL_PER_PDU, "finish ComputeSessionKey", "");
+
+
+ loser:
+ if (tksConn != NULL) {
+ RA::ReturnTKSConn(tksConn);
+ }
+ if( cardc != NULL ) {
+ PR_Free( cardc );
+ cardc = NULL;
+ }
+ if( hostc != NULL ) {
+ PR_Free( hostc );
+ hostc = NULL;
+ }
+ if( cuid != NULL ) {
+ PR_Free( cuid );
+ cuid = NULL;
+ }
+ if( keyinfo != NULL ) {
+ PR_Free( keyinfo );
+ keyinfo = NULL;
+ }
+ if (cardCrypto != NULL) {
+ PR_Free( cardCrypto );
+ cardCrypto = NULL;
+ }
+
+ if( response != NULL ) {
+ response->freeContent();
+ delete response;
+ response = NULL;
+ }
+
+ if (ra_pb != NULL) {
+ delete ra_pb;
+ }
+ // in production, if TKS is unreachable, symKey will be NULL,
+ // and this will signal error to the caller.
+ return symKey;
+
+}
+
+Buffer *RA::ComputeHostCryptogram(Buffer &card_challenge,
+ Buffer &host_challenge)
+{
+ /* hardcoded enc auth key */
+ BYTE enc_auth_key[16] = {
+ 0x40, 0x41, 0x42, 0x43,
+ 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b,
+ 0x4c, 0x4d, 0x4e, 0x4f
+ };
+ Buffer input = Buffer(16, (BYTE)0);
+ int i;
+ Buffer icv = Buffer(8, (BYTE)0);
+ Buffer *output = new Buffer(8, (BYTE)0);
+ BYTE *cc = (BYTE*)card_challenge;
+ int cc_len = card_challenge.size();
+ BYTE *hc = (BYTE*)host_challenge;
+ int hc_len = host_challenge.size();
+
+ /* copy card and host challenge into input buffer */
+ for (i = 0; i < 8; i++) {
+ ((BYTE*)input)[i] = cc[i];
+ }
+ for (i = 0; i < 8; i++) {
+ ((BYTE*)input)[8+i] = hc[i];
+ }
+
+ PK11SymKey *key = Util::DeriveKey(
+ Buffer(enc_auth_key, 16), Buffer(hc, hc_len),
+ Buffer(cc, cc_len));
+ Util::ComputeMAC(key, input, icv, *output);
+
+ return output;
+}
+
+TPS_PUBLIC void RA::DebugBuffer(const char *func_name, const char *prefix, Buffer *buf)
+{
+ RA::DebugBuffer(LL_PER_CONNECTION, func_name, prefix, buf);
+}
+
+void RA::DebugBuffer(RA_Log_Level level, const char *func_name, const char *prefix, Buffer *buf)
+{
+ int i;
+ PRTime now;
+ const char* time_fmt = "%Y-%m-%d %H:%M:%S";
+ char datetime[1024];
+ PRExplodedTime time;
+ BYTE *data = *buf;
+ int sum = 0;
+ PRThread *ct;
+
+ if (m_fd_debug == NULL)
+ return;
+ if ((int) level >= m_debug_log_level)
+ return;
+ PR_Lock(m_debug_log_lock);
+ now = PR_Now();
+ PR_ExplodeTime(now, PR_LocalTimeParameters, &time);
+ PR_FormatTimeUSEnglish(datetime, 1024, time_fmt, &time);
+ ct = PR_GetCurrentThread();
+ PR_fprintf(m_fd_debug, "[%s] %x %s - ", datetime, ct, func_name);
+ PR_fprintf(m_fd_debug, "%s (length='%d')", prefix, buf->size());
+ PR_fprintf(m_fd_debug, "\n");
+ PR_fprintf(m_fd_debug, "[%s] %x %s - ", datetime, ct, func_name);
+ for (i=0; i<(int)buf->size(); i++) {
+ PR_fprintf(m_fd_debug, "%02x ", (unsigned char)data[i]);
+ sum++;
+ if (sum == 10) {
+ PR_fprintf(m_fd_debug, "\n");
+ PR_fprintf(m_fd_debug, "[%s] %x %s - ", datetime, ct, func_name);
+ sum = 0;
+ }
+ }
+ PR_Write(m_fd_debug, "\n", 1);
+ PR_Unlock(m_debug_log_lock);
+}
+
+TPS_PUBLIC void RA::Debug (const char *func_name, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ RA::DebugThis(LL_PER_SERVER, func_name, fmt, ap);
+ va_end(ap);
+}
+
+TPS_PUBLIC void RA::Debug (RA_Log_Level level, const char *func_name, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ RA::DebugThis(level, func_name, fmt, ap);
+ va_end(ap);
+}
+
+void RA::DebugThis (RA_Log_Level level, const char *func_name, const char *fmt, va_list ap)
+{
+ PRTime now;
+ const char* time_fmt = "%Y-%m-%d %H:%M:%S";
+ char datetime[1024];
+ PRExplodedTime time;
+ PRThread *ct;
+
+ if (m_fd_debug == NULL)
+ return;
+ if ((int) level >= m_debug_log_level)
+ return;
+ PR_Lock(m_debug_log_lock);
+ now = PR_Now();
+ ct = PR_GetCurrentThread();
+ PR_ExplodeTime(now, PR_LocalTimeParameters, &time);
+ PR_FormatTimeUSEnglish(datetime, 1024, time_fmt, &time);
+ PR_fprintf(m_fd_debug, "[%s] %x %s - ", datetime, ct, func_name);
+ PR_vfprintf(m_fd_debug, fmt, ap);
+ PR_Write(m_fd_debug, "\n", 1);
+ PR_Unlock(m_debug_log_lock);
+}
+
+TPS_PUBLIC void RA::Audit (const char *func_name, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ RA::AuditThis (LL_PER_SERVER, func_name, fmt, ap);
+ va_end(ap);
+ va_start(ap, fmt);
+ RA::DebugThis (LL_PER_SERVER, func_name, fmt, ap);
+ va_end(ap);
+}
+
+TPS_PUBLIC void RA::Audit (RA_Log_Level level, const char *func_name, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ RA::AuditThis (level, func_name, fmt, ap);
+ va_end(ap);
+ va_start(ap, fmt);
+ RA::DebugThis (level, func_name, fmt, ap);
+ va_end(ap);
+}
+
+void RA::AuditThis (RA_Log_Level level, const char *func_name, const char *fmt, va_list ap)
+{
+ PRTime now;
+ const char* time_fmt = "%Y-%m-%d %H:%M:%S";
+ char datetime[1024];
+ PRExplodedTime time;
+ PRThread *ct;
+
+ if (m_fd_audit == NULL)
+ return;
+ if ((int) level >= m_audit_log_level)
+ return;
+ PR_Lock(m_audit_log_lock);
+ now = PR_Now();
+ PR_ExplodeTime(now, PR_LocalTimeParameters, &time);
+ PR_FormatTimeUSEnglish(datetime, 1024, time_fmt, &time);
+ ct = PR_GetCurrentThread();
+ PR_fprintf(m_fd_audit, "[%s] %x %s - ", datetime, ct, func_name);
+ PR_vfprintf(m_fd_audit, fmt, ap);
+ PR_Write(m_fd_audit, "\n", 1);
+ PR_Unlock(m_audit_log_lock);
+}
+
+TPS_PUBLIC void RA::Error (const char *func_name, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ RA::ErrorThis(LL_PER_SERVER, func_name, fmt, ap);
+ va_end(ap);
+ va_start(ap, fmt);
+ RA::DebugThis(LL_PER_SERVER, func_name, fmt, ap);
+ va_end(ap);
+}
+
+TPS_PUBLIC void RA::Error (RA_Log_Level level, const char *func_name, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ RA::ErrorThis(level, func_name, fmt, ap);
+ va_end(ap);
+ va_start(ap, fmt);
+ RA::DebugThis(level, func_name, fmt, ap);
+ va_end(ap);
+}
+
+void RA::ErrorThis (RA_Log_Level level, const char *func_name, const char *fmt, va_list ap)
+{
+ PRTime now;
+ const char* time_fmt = "%Y-%m-%d %H:%M:%S";
+ char datetime[1024];
+ PRExplodedTime time;
+ PRThread *ct;
+
+ if (m_fd_error == NULL)
+ return;
+ if ((int) level >= m_error_log_level)
+ return;
+ PR_Lock(m_error_log_lock);
+ now = PR_Now();
+ ct = PR_GetCurrentThread();
+ PR_ExplodeTime(now, PR_LocalTimeParameters, &time);
+ PR_FormatTimeUSEnglish(datetime, 1024, time_fmt, &time);
+ PR_fprintf(m_fd_error, "[%s] %x %s - ", datetime, ct, func_name);
+ PR_vfprintf(m_fd_error, fmt, ap);
+ PR_Write(m_fd_error, "\n", 1);
+ PR_Unlock(m_error_log_lock);
+}
+
+PublisherEntry *RA::getPublisherById(const char *publisher_id)
+{
+
+ PublisherEntry *cur = RA::publisher_list;
+
+ if(cur == NULL)
+ {
+ return NULL;
+ }
+
+ while(cur != NULL)
+ {
+ if(!strcmp(publisher_id,cur->id))
+ {
+ break;
+ }
+
+ cur = cur->next;
+ }
+
+ return cur;
+
+}
+
+int RA::InitializePublishers()
+
+{
+ RA::m_num_publishers = 0;
+
+ RA::Debug(LL_PER_PDU, "RA::InitializePublishers: Attempting to load the configurable list of Publishers.", "");
+
+ const char *pub_prefix = "publisher.instance";
+ const char *pub_suffix = "publisherId";
+
+ const char *publisher_id = NULL;
+ const char *publisher_lib_name = NULL;
+ const char *publisher_lib_factory_name = NULL;
+
+ char config_str[500];
+
+ int i = -1;
+ int res = 0;
+
+ PublisherEntry *new_entry;
+
+ while(1)
+ {
+ i++;
+
+ PR_snprintf((char *)config_str, 256,"%s.%d.%s", pub_prefix,i,pub_suffix);
+ publisher_id = m_cfg->GetConfigAsString(config_str,NULL);
+
+ if(publisher_id != NULL)
+ {
+ RA::Debug(LL_PER_PDU, "RA::InitializePublishers:"," Found publisher id %s ", publisher_id);
+ PR_snprintf((char *)config_str, 256, "%s.%d.%s",pub_prefix,i,"libraryName");
+
+ publisher_lib_name = m_cfg->GetConfigAsString(config_str,NULL);
+
+ if(publisher_lib_name != NULL)
+ {
+ RA::Debug(LL_PER_PDU, "RA::InitializePublishers:"," Found publisher lib name %s ", publisher_lib_name);
+ PR_snprintf((char *)config_str, 256, "%s.%d.%s",pub_prefix,i,"libraryFactory");
+
+ publisher_lib_factory_name = m_cfg->GetConfigAsString(config_str,NULL);
+
+ if(publisher_lib_factory_name)
+ {
+
+ RA::Debug(LL_PER_PDU, "RA::InitializePublishers:"," Found publisher lib factory name %s ", publisher_lib_factory_name);
+
+ PRLibrary *pb = PR_LoadLibrary(publisher_lib_name);
+
+ if(pb)
+ {
+ void *sym = PR_FindSymbol(pb,publisher_lib_factory_name);
+
+ if(sym == NULL)
+ {
+
+ RA::Error(LL_PER_PDU, "RA:InitializePublishers",
+ "Failed to find symbol '%s' publisher %s error code: %d",publisher_lib_factory_name,publisher_lib_name,PR_GetError());
+
+ RA::Debug(LL_PER_PDU, "RA::InitializePublishers: Failed to load publish library.", "");
+
+
+ continue;
+ }
+ makepublisher make_pub = (makepublisher ) sym;
+
+ IPublisher *publisher = (* make_pub )();
+
+ if(publisher == NULL)
+ {
+ RA::Error(LL_PER_PDU, "RA:InitializePublishers",
+ "Failed to initialize publisher %s error code: %d",publisher_lib_name,PR_GetError());
+ RA::Debug(LL_PER_PDU, "RA::InitializePublishers: Failed to allocate Netkey publisher.", "");
+ continue;
+ }
+ if(publisher)
+ {
+ res = publisher->init();
+ }
+
+ if(!res)
+ {
+ RA::Debug(LL_PER_PDU, "RA::InitializePublishers: Failed to initialize publisher %s.", publisher_lib_name);
+ continue;
+ }
+
+ new_entry = (PublisherEntry *) malloc(sizeof(PublisherEntry));
+
+ if(new_entry == NULL)
+ {
+
+ RA::Debug(LL_PER_PDU, "RA::InitializePublishers: Failed to allocate PublisherEntry structure", "");
+
+ break;
+
+ }
+ new_entry->id = strdup(publisher_id);
+ new_entry->publisher = publisher;
+ new_entry->publisher_lib = pb;
+
+ if(RA::publisher_list == NULL)
+ {
+ RA::publisher_list = new_entry;
+ new_entry->next = NULL;
+
+ }
+
+ else
+ {
+ PublisherEntry *cur = RA::publisher_list;
+
+ while(cur->next != NULL)
+ {
+ cur= cur->next;
+ }
+
+ cur->next = new_entry;
+ new_entry->next = NULL;
+
+ }
+
+ RA::m_num_publishers++;
+ RA::Debug(LL_PER_PDU, "RA::InitializePublishers:"," Successfully initialized publisher %s.", publisher_lib_name);
+ }
+ else
+ {
+ RA::Error(LL_PER_PDU, "RA:InitializePublishers",
+ "Failed to open library %s error code: %d",publisher_lib_name,PR_GetError());
+
+ RA::Debug(LL_PER_PDU, "RA::InitializePublishers"," Failed to load publish library.", "");
+
+ continue;
+
+ }
+ }
+ else
+ {
+ continue;
+ }
+ }
+ else
+ {
+ continue;
+
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if(RA::m_num_publishers == 0)
+ {
+ RA::Debug(LL_PER_PDU, "RA::InitializePublishers:"," Did not load any publisher libraries, possibly not configured for publishing. Server continues normally... ");
+ return 0;
+ }
+ else
+ {
+ RA::Debug(LL_PER_PDU, "RA::InitializePublishers:"," Loaded %d Publisher(s).", RA::m_num_publishers);
+
+ return 1;
+ }
+
+}
+
+void RA::CleanupPublishers()
+{
+
+ if(RA::m_num_publishers == 0)
+ return;
+
+ RA::Debug(LL_PER_PDU, "RA::CleanupPublishers:"," Loaded %d publishers.", RA::m_num_publishers);
+
+ PublisherEntry *cur = RA::publisher_list;
+
+ if(cur == NULL)
+ {
+ return ;
+ }
+
+ while(cur != NULL)
+ {
+
+ PublisherEntry *next =cur->next;
+
+ if(cur)
+ {
+
+ RA::Debug(LL_PER_PDU, "RA::CleanupPublishers:"," Cleanup up publisher %s", cur->id);
+ if( cur->id != NULL)
+ {
+ free( cur->id );
+ cur->id = NULL;
+ }
+
+ if( cur->publisher != NULL ) {
+ delete cur->publisher;
+ cur->publisher = NULL;
+ }
+
+ if( cur->publisher_lib != NULL ) {
+ PR_UnloadLibrary( cur->publisher_lib );
+ cur->publisher_lib = NULL;
+ }
+
+ if( cur != NULL ) {
+ free( cur );
+ cur = NULL;
+ }
+
+ cur = next;
+
+ }
+ }
+
+
+}
+
+int RA::InitializeHttpConnections(const char *id, int *len, HttpConnection **conn, RA_Context *ctx) {
+ char configname[256];
+ char connID[100];
+ CERTCertDBHandle *handle = 0;
+ CERTCertificate *cert = NULL;
+ int rc = 0;
+ int i=0;
+
+ *len = 0;
+
+ // Initialize each connection
+ while (1) {
+ i++;
+ PR_snprintf((char *)configname, 256, "conn.%s%d.hostport", id, i);
+ const char *host_port = m_cfg->GetConfigAsString(configname);
+ if (host_port == NULL) {
+ break;
+ }
+ ConnectionInfo *cinfo = new ConnectionInfo();
+ cinfo->BuildFailoverList(host_port);
+ PR_snprintf((char *)configname, 256, "conn.%s%d.retryConnect", id, i);
+ int retries = m_cfg->GetConfigAsInt(configname, 3);
+ PR_snprintf((char *)configname, 256, "conn.%s%d.timeout", id, i);
+ int timeout = m_cfg->GetConfigAsInt(configname, 10);
+ PR_snprintf((char *)connID, 100, "%s%d", id, i);
+ PR_snprintf((char *)configname, 256, "conn.%s%d.clientNickname", id, i);
+ const char *clientnickname = m_cfg->GetConfigAsString(configname);
+
+ // Bugscape Bug #56583: insure that specified certificate is present
+ //
+ // (1) To prevent a coredump, we need to determine if NSS has been
+ // initialized prior to loading this TPS plugin. However,
+ // since NSS does not provide a callable initialization check
+ // to inform the caller whether or not NSS has been initialized,
+ // we need to supply the following workaround solution:
+ handle = CERT_GetDefaultCertDB();
+ if( handle == 0 ) {
+ ctx->InitializationError( "RA::InitializeHttpConnections",
+ __LINE__ );
+ rc = -1;
+ goto loser;
+ }
+
+ // (2) Since NSS has been initialized, verify the presence of the
+ // specified certificate:
+ if( ( clientnickname != NULL ) &&
+ ( PL_strcmp( clientnickname, "" ) != 0 ) ) {
+ cert = CERT_FindCertByNickname( handle,
+ (char *) clientnickname );
+ if( cert == NULL ) {
+ RA::Error( LL_PER_SERVER,
+ "RA::InitializeHttpConnections",
+ "A %s certificate nicknamed \"%s\" "
+ "could NOT be found in the certificate "
+ "database for connection %d!",
+ id,
+ clientnickname,
+ i );
+ rc = -2;
+ goto loser;
+ } else {
+ RA::Debug( LL_PER_CONNECTION,
+ "RA::InitializeHttpConnections",
+ "A %s certificate nicknamed \"%s\" "
+ "was found in the certificate "
+ "database for connection %d.",
+ id,
+ clientnickname,
+ i );
+ CERT_DestroyCertificate( cert );
+ cert = NULL;
+ }
+ } else {
+ RA::Error( LL_PER_SERVER,
+ "RA::InitializeHttpConnections",
+ "An empty or missing %s certificate nickname "
+ "was specified for connection %d!",
+ id,
+ i );
+ rc = -3;
+ goto loser;
+ }
+
+ PR_snprintf((char *)configname, 256, "conn.%s%d.SSLOn", id, i);
+ bool isSSL = m_cfg->GetConfigAsBool(configname, true);
+ PR_snprintf((char *)configname, 256, "conn.%s%d.keepAlive", id, i);
+ bool keepAlive = m_cfg->GetConfigAsBool(configname, true);
+ conn[*len] = new HttpConnection(connID, cinfo, retries, timeout, isSSL, clientnickname, keepAlive, NULL);
+ (*len)++;
+ }
+
+loser:
+
+ return rc;
+}
+
+int RA::InitializeTokendb(char *cfg_path)
+{
+ char *error = NULL;
+ int status;
+
+ if (tokendbInitialized)
+ return 0;
+
+ RA::Debug("RA::InitializeTokendb", "config path = %s", cfg_path);
+
+ if (get_tus_db_config(cfg_path) != 1) {
+ RA::Debug("RA::InitializeTokendb", "get_tus_db_config failed");
+ return -1;
+ }
+
+ tokendbInitialized = 1;
+
+ RA::Debug("RA::InitializeTokendb", "Initializing TUS database");
+ if( ( status = tus_db_init( &error ) ) != LDAP_SUCCESS ) {
+ if( error != NULL ) {
+ RA::Debug( "RA::InitializeTokendb",
+ "Token DB initialization failed: '%s'",
+ error );
+ PR_smprintf_free( error );
+ error = NULL;
+ } else {
+ RA::Debug( "RA::InitializeTokendb",
+ "Token DB initialization failed" );
+ }
+ }
+
+ return status;
+}
+
+TPS_PUBLIC int RA::ra_find_tus_certificate_entries_by_order_no_vlv (char *filter,
+ LDAPMessage **result, int order)
+{
+ return find_tus_certificate_entries_by_order_no_vlv(filter, result, order);
+}
+
+TPS_PUBLIC int RA::ra_find_tus_certificate_entries_by_order (char *filter,
+ int max, LDAPMessage **result, int order)
+{
+ return find_tus_certificate_entries_by_order(filter, max, result, order);
+}
+
+TPS_PUBLIC CERTCertificate **RA::ra_get_certificates(LDAPMessage *e) {
+ return get_certificates(e);
+}
+
+TPS_PUBLIC LDAPMessage *RA::ra_get_first_entry(LDAPMessage *e) {
+ return get_first_entry(e);
+}
+
+TPS_PUBLIC LDAPMessage *RA::ra_get_next_entry(LDAPMessage *e) {
+ return get_next_entry(e);
+}
+
+TPS_PUBLIC char **RA::ra_get_attribute_values(LDAPMessage *e, const char *p) {
+ return get_attribute_values(e, p);
+}
+
+TPS_PUBLIC char *RA::ra_get_token_id(LDAPMessage *e) {
+ return get_token_id(e);
+}
+
+TPS_PUBLIC char *RA::ra_get_cert_tokenType(LDAPMessage *entry) {
+ return get_cert_tokenType(entry);
+}
+
+TPS_PUBLIC char *RA::ra_get_token_status(LDAPMessage *entry) {
+ return get_token_status(entry);
+}
+
+TPS_PUBLIC char *RA::ra_get_cert_cn(LDAPMessage *entry) {
+ return get_cert_cn(entry);
+}
+
+TPS_PUBLIC char *RA::ra_get_cert_attr_byname(LDAPMessage *entry, char *name) {
+ return get_cert_attr_byname(entry, name);
+}
+
+TPS_PUBLIC char *RA::ra_get_cert_status(LDAPMessage *entry) {
+ return get_cert_status(entry);
+}
+
+TPS_PUBLIC char *RA::ra_get_cert_type(LDAPMessage *entry) {
+ return get_cert_type(entry);
+}
+
+TPS_PUBLIC char *RA::ra_get_cert_serial(LDAPMessage *entry) {
+ return get_cert_serial(entry);
+}
+
+TPS_PUBLIC char *RA::ra_get_cert_issuer(LDAPMessage *entry) {
+ return get_cert_issuer(entry);
+}
+
+TPS_PUBLIC int RA::ra_tus_has_active_tokens(char *userid) {
+ return tus_has_active_tokens(userid);
+}
+
+TPS_PUBLIC char *RA::ra_get_token_reason(LDAPMessage *msg) {
+ return get_token_reason(msg);
+}
+
+TPS_PUBLIC int RA::ra_get_number_of_entries(LDAPMessage *ldapResult) {
+ return get_number_of_entries(ldapResult);
+}
+
+TPS_PUBLIC int RA::ra_find_tus_token_entries_no_vlv(char *filter,
+ LDAPMessage **ldapResult, int num)
+{
+ return find_tus_token_entries_no_vlv(filter, ldapResult, num);
+}
+
+TPS_PUBLIC int RA::ra_find_tus_token_entries(char *filter, int maxReturns,
+ LDAPMessage **ldapResult, int num)
+{
+ return find_tus_token_entries(filter, maxReturns, ldapResult, num);
+}
+
+TPS_PUBLIC int RA::ra_is_tus_db_entry_disabled(char *cuid)
+{
+ return is_tus_db_entry_disabled(cuid);
+}
+
+TPS_PUBLIC int RA::ra_is_token_present(char *cuid)
+{
+ return is_token_present(cuid);
+}
+
+TPS_PUBLIC int RA::ra_is_token_pin_resetable(char *cuid)
+{
+ return is_token_pin_resetable(cuid);
+}
+
+TPS_PUBLIC int RA::ra_is_update_pin_resetable_policy(char *cuid)
+{
+ return is_update_pin_resetable_policy(cuid);
+}
+
+TPS_PUBLIC char *RA::ra_get_token_policy(char *cuid)
+{
+ return get_token_policy(cuid);
+}
+
+TPS_PUBLIC char *RA::ra_get_token_userid(char *cuid)
+{
+ return get_token_userid(cuid);
+}
+
+TPS_PUBLIC int RA::ra_update_token_policy(char *cuid, char *policy)
+{
+ return update_token_policy(cuid, policy);
+}
+
+TPS_PUBLIC int RA::ra_update_cert_status(char *cn, const char *status)
+{
+ return update_cert_status(cn, status);
+}
+
+TPS_PUBLIC int RA::ra_update_token_status_reason_userid(char *userid, char *cuid, const char *status, const char *reason, int modifyDateOfCreate)
+{
+ return update_token_status_reason_userid(userid, cuid, status, reason, modifyDateOfCreate);
+}
+
+TPS_PUBLIC int RA::ra_allow_token_reenroll(char *cuid)
+{
+ return allow_token_reenroll(cuid);
+}
+
+int RA::tdb_activity(char *ip, char *cuid, const char *op, const char *result, const char *msg, const char *userid)
+{
+ return add_activity(ip, cuid, op, result, msg, userid);
+}
+
+int RA::tdb_update_certificates(char* cuid, char **tokentypes, char *userid, CERTCertificate ** certificates, char **ktypes, char **origins, int numOfCerts)
+{
+ int rc = -1;
+ LDAPMessage *ldapResult = NULL;
+ int k = 0;
+ char filter[512];
+ LDAPMessage *result = NULL;
+ LDAPMessage *e = NULL;
+ int i = 0;
+
+ if ((rc = find_tus_db_entry(cuid, 0, &ldapResult)) != LDAP_SUCCESS) {
+ return rc;
+ }
+
+ /* update certificates */
+ for (i = 0; i < numOfCerts; i++) {
+ if (certificates[i] == NULL) {
+ RA::Debug(LL_PER_PDU, "RA::tdb_update_certificates",
+ "no certificate found at index %d for tokendb entry: %s", i, cuid);
+ } else {
+ RA::Debug(LL_PER_PDU, "RA::tdb_update_certificates",
+ "cert=%x", certificates[i]);
+
+ k++;
+ }
+ }
+
+ for (i = 0; i < numOfCerts; i++) {
+ if (certificates[i] != NULL) {
+ RA::Debug(LL_PER_PDU, "RA::tdb_update_certificates",
+ "adding cert=%x", certificates[i]);
+
+ PR_snprintf(filter, 512, "tokenSerial=%x", DER_GetInteger(&(certificates[i])->serialNumber));
+ int r = find_tus_certificate_entries_by_order_no_vlv(filter, &result, 1);
+ bool found = false;
+ if (r == LDAP_SUCCESS) {
+ for (e = get_first_entry(result); e != NULL; e = get_next_entry(e)) {
+ char **values = get_attribute_values(e, "tokenStatus");
+ found = true;
+ RA::Debug("RA::tdb_update_certificates", "Certificate status is %s", values[0]);
+ add_certificate(cuid, origins[i], tokentypes[i], userid, certificates[i],
+ ktypes[i], values[0]);
+ ldap_value_free(values);
+ break;
+ }
+
+ ldap_msgfree(result);
+ }
+ if (!found)
+ add_certificate(cuid, origins[i], tokentypes[i], userid, certificates[i],
+ ktypes[i], "active");
+ }
+ }
+
+ return rc;
+}
+
+/*
+ * This adds a brand new token entry to tus.
+ */
+int RA::tdb_add_token_entry(char *userid, char* cuid, const char *status) {
+ int rc = -1;
+ int r = -1;
+ LDAPMessage *ldapResult = NULL;
+
+ if (tokendbInitialized != 1) {
+ r = 0;
+ goto loser;
+ }
+
+ RA::Debug(LL_PER_PDU, "RA::tdb_add_token_entry",
+ "searching for tokendb entry: %s", cuid);
+
+ if ((rc = find_tus_db_entry(cuid, 0, &ldapResult)) != LDAP_SUCCESS) {
+ /* create a new entry */
+ rc = add_default_tus_db_entry(userid, "~tps", cuid, status, NULL, NULL);
+ if (rc != LDAP_SUCCESS) {
+ RA::Error(LL_PER_PDU, "RA:tdb_add_token_entry",
+ "failed to add tokendb entry");
+ r = -1;
+ goto loser;
+ } else
+ RA::Debug(LL_PER_PDU, "RA::tdb_add_token_entry",
+ "add tokendb entry successful");
+ r = 0;
+ goto loser;
+ } else {
+ RA::Debug(LL_PER_PDU, "RA::tdb_add_token_entry",
+ "entry in tokendb exists.");
+
+ // try to see if the userid is there
+ LDAPMessage *e = ra_get_first_entry(ldapResult);
+ char **uid = ra_get_attribute_values(e, "tokenUserID");
+
+ if (uid != NULL) {
+ if (uid[0] != NULL) {
+ if (strlen(uid[0]) > 0 && strcmp(uid[0], userid) != 0) {
+ ldap_value_free(uid);
+ RA::Debug(LL_PER_PDU, "RA::tdb_add_token_entry",
+ "This token does not belong to this user: %s", userid);
+ r = -1;
+ goto loser;
+ } else {
+ if (strlen(uid[0]) > 0 && strcmp(uid[0], userid) == 0) {
+ ldap_value_free(uid);
+ r = 0;
+ goto loser;
+ }
+ }
+ }
+ ldap_value_free(uid);
+ }
+
+ // this is the recycled token, update userid and dateOfCreate
+ rc = ra_update_token_status_reason_userid(userid, cuid, status, "", 1);
+ r = rc;
+ }
+loser:
+ if (ldapResult != NULL) {
+ ldap_msgfree(ldapResult);
+ }
+ return r;
+}
+
+/*
+ * This adds entry to tokendb if entry not found
+ * It is then supposed to modify entry (not yet implemented)
+ */
+int RA::tdb_update(const char *userid, char* cuid, char* applet_version, char *key_info, const char *state, const char *reason)
+{
+ int rc = -1;
+ LDAPMessage *ldapResult = NULL;
+ // char filter[255];
+
+ if (tokendbInitialized != 1) {
+ rc = 0;
+ goto loser;
+ }
+
+
+ // PR_snprintf(filter, 255, "(cn=%s)", cuid);
+ RA::Debug(LL_PER_PDU, "RA::tdb_update",
+ "searching for tokendb entry: %s", cuid);
+
+ if ((rc = find_tus_db_entry(cuid, 0, &ldapResult)) != LDAP_SUCCESS) {
+ /* create a new entry */
+ rc = add_default_tus_db_entry(userid, "~tps", cuid, state, applet_version,
+ key_info);
+ if (rc != LDAP_SUCCESS) {
+ RA::Error(LL_PER_PDU, "RA:tdb_update",
+ "failed to add tokendb entry");
+ rc = -1;
+ goto loser;
+ } else
+ RA::Debug(LL_PER_PDU, "RA::tdb_update",
+ "add tokendb entry successful");
+ rc = 0;
+ } else {
+ RA::Debug(LL_PER_PDU, "RA::tdb_update",
+ "entry in tokendb exists...should modify entry");
+
+ /* need code to modify things such as applet version ...*/
+ /* ldap modify code to follow...*/
+ rc = update_tus_db_entry ("~tps", cuid, userid, key_info, state,
+ applet_version, reason);
+ }
+loser:
+ if (ldapResult != NULL) {
+ ldap_msgfree(ldapResult);
+ }
+ return rc;
+}
+
+int RA::InitializeAuthentication() {
+ char configname[256];
+ const char *authid;
+ const char *type;
+ const char *authPrefix = "auth.instance";
+ const char *lib = NULL;
+ const char *libfactory = NULL;
+ int i=-1;
+ int rc=0;
+ // AuthenticationEntry *authEntry;
+
+ while (1) {
+ i++;
+ PR_snprintf((char *)configname, 256, "%s.%d.authId", authPrefix, i);
+ authid = m_cfg->GetConfigAsString(configname, NULL);
+ if (authid != NULL) {
+ RA::Debug(LL_PER_PDU, "RA::InitializeAuthentication",
+ "Found authentication id=%s", authid);
+ PR_snprintf((char *)configname, 256, "%s.%d.libraryName", authPrefix, i);
+ lib = m_cfg->GetConfigAsString(configname, NULL);
+ if (lib != NULL) {
+ RA::Debug(LL_PER_PDU, "RA::InitializeAuthentication",
+ "Found authentication library=%s", lib);
+ PR_snprintf((char *)configname, 256, "%s.%d.libraryFactory", authPrefix, i);
+ libfactory = m_cfg->GetConfigAsString(configname, NULL);
+ if (libfactory != NULL) {
+ RA::Debug(LL_PER_PDU, "RA::InitializeAuthentication",
+ "Found authentication library factory=%s", libfactory);
+ PRLibrary *pb = PR_LoadLibrary(lib);
+ if (pb) {
+ RA::Debug(LL_PER_PDU, "RA::InitializeAuthentication", "Successfully loaded the library %s", lib);
+ void *sym = PR_FindSymbol(pb, libfactory);
+ if (sym == NULL) {
+ RA::Error(LL_PER_PDU, "RA::InitializeAuthentication",
+ "Failed to find symbol '%s' in '%s' library, error code: %d",
+ libfactory, lib, PR_GetError());
+ RA::Debug(LL_PER_PDU, "RA::InitializeAuthentication",
+ "Failed to load the library symbol");
+ continue;
+ }
+ makeauthentication make_auth = (makeauthentication)sym;
+ Authentication *authentication = (*make_auth)();
+ if (authentication == NULL) {
+ RA::Error(LL_PER_PDU, "RA::InitializeAuthentication",
+ "Failed to create authentication instance with library %s, error code=%d.",
+ lib, PR_GetError());
+ RA::Debug(LL_PER_PDU, "RA::InitializeAuthentication",
+ "Failed to create authentication instance with library %s, error code=%d.",
+ lib, PR_GetError());
+ continue;
+ } else {
+ authentication->Initialize(i);
+ m_auth_list[m_auth_len] = new AuthenticationEntry();
+ m_auth_list[m_auth_len]->SetId(authid);
+ m_auth_list[m_auth_len]->SetLibrary(pb);
+ m_auth_list[m_auth_len]->SetAuthentication(authentication);
+ PR_snprintf((char *)configname, 256, "%s.%d.type", authPrefix, i);
+ type = m_cfg->GetConfigAsString(configname, NULL);
+ m_auth_list[m_auth_len]->SetType(type);
+ RA::Debug(LL_PER_PDU, "RA::InitializeAuthentication:",
+ "Successfully initialized authentication %s.", lib);
+ }
+ } else {
+ RA::Debug(LL_PER_PDU, "RA::InitializeAuthentication",
+ "Failed to load the library %s: error=%d", lib, PR_GetError());
+ continue;
+ }
+ } else {
+ RA::Debug(LL_PER_PDU, "RA::InitializeAuthentication",
+ "Failed to find the library factory %s", libfactory);
+ continue;
+ }
+ } else {
+ RA::Debug(LL_PER_PDU, "RA::InitializeAuthentication",
+ "Failed to find the library %s", lib);
+ continue;
+ }
+ m_auth_len++;
+ } else {
+ break;
+ }
+ }
+
+ if (m_auth_len == 0) {
+ RA::Debug(LL_PER_PDU, "RA::InitializeAuthentication",
+ "No authentication module gets loaded, but server continues starting up...");
+ rc = -1;
+ } else {
+ RA::Debug(LL_PER_PDU, "RA::InitializeAuthentication",
+ "Total number of authentication modules get loaded: %d", m_auth_len);
+ }
+
+ return rc;
+}
+
+int RA::Failover(HttpConnection *&conn, int len) {
+ int rc = 0;
+ if (m_pod_enable) {
+ PR_Lock(m_pod_lock);
+ if (++m_pod_curr >= len)
+ m_pod_curr = 0;
+ HttpConnection *conn = NULL;
+ for (int i=0; i<m_caConns_len; i++) {
+ conn = m_caConnection[i];
+ RA::SetCurrentIndex(conn, m_pod_curr);
+ conn = m_drmConnection[i];
+ RA::SetCurrentIndex(conn, m_pod_curr);
+ conn = m_tksConnection[i];
+ RA::SetCurrentIndex(conn, m_pod_curr);
+ }
+ PR_Unlock(m_pod_lock);
+ } else {
+ if (conn != NULL) {
+ int curr = RA::GetCurrentIndex(conn);
+ if (++curr >= len)
+ curr = 0;
+ RA::SetCurrentIndex(conn, curr);
+ } else
+ rc = -1;
+ }
+ return rc;
+}