CASA/c_micasad/verbs/ObjectSerialization.cs
2006-01-28 18:47:48 +00:00

878 lines
22 KiB
C#

/***********************************************************************
*
* Copyright (C) 2005-2006 Novell, Inc.
*
* 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
* Library 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
***********************************************************************/
using System;
using System.Collections;
using System.Text;
using System.Threading;
using sscs.verbs;
using sscs.cache;
using sscs.common;
using sscs.constants;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using Novell.CASA.MiCasa.Common;
using Novell.CASA.MiCasa.Communication;
namespace sscs.verbs
{
/*
* There will be one instance existing for every call made by the client.
*/
internal class ObjectSerialization : SSVerb
{
private ushort msgId = 0;
private uint inMsgLen = 0;
private byte[] inBuf;
private byte[] outBuf;
/*
* This method sets the class member with the byte array received.
*/
public void SetMessageContent(byte[] ipcBytes)
{
CSSSLogger.ExecutionTrace(this);
inBuf = ipcBytes;
}
/*
* This method does the actual implementation of ReadSecret
*
*/
public byte[] ProcessRequest(UserIdentifier userId)
{
CSSSLogger.ExecutionTrace(this);
/* If an exception occurs in message format decoding,
* it is handled by AppHandler
*/
// Message Format decipher - Start
msgId = BitConverter.ToUInt16(inBuf,0);
inMsgLen = BitConverter.ToUInt32(inBuf,2);
//Console.WriteLine("Serialization verb: msgId is " + msgId + " inMsgLen = " + inMsgLen + "inBuf.Length is " + inBuf.Length);
// if( inMsgLen != inBuf.Length )
// Console.WriteLine("inMsgLen != inBuf.Length");
// throw new FormatException(" MsgLen sent does not match the length of the message received.");
// deserialize the data
BinaryFormatter formatter = new BinaryFormatter();
MemoryStream ms = new MemoryStream(inBuf, 6, (int)inMsgLen - 6);
// MemoryStream ms = new MemoryStream(inBuf, 6, (int)inMsgLen);
WrappedObject request;
WrappedObject reply;
try
{
request = (WrappedObject)formatter.Deserialize(ms);
reply = ProcessMessage(request, userId);
}
catch (Exception e)
{
reply = new WrappedObject(-1, null);
}
// Serialize the WrappedObject and send the reply
ms = new MemoryStream();
formatter.Serialize(ms, reply);
int msLen = (int)ms.Length;
outBuf = new byte[4+msLen];
byte[] t = new byte[10];
t = BitConverter.GetBytes(ms.Length);
Array.Copy(t,0,outBuf,0,4);
Array.Copy(ms.GetBuffer(), 0, outBuf, 4, msLen);
SessionManager.RemoveUserSession(userId, false);
return outBuf;
}
internal WrappedObject ProcessMessage(WrappedObject wo, UserIdentifier userId)
{
//Console.WriteLine("ObjectSerialization Called");
SecretStore ssStore = SessionManager.CreateUserSession(userId);
try
{
int action = wo.GetAction();
switch (action)
{
case MiCasaRequestReply.VERB_PING_MICASAD:
{
return DoPing(wo);
}
case MiCasaRequestReply.VERB_SET_LINKED_KEY:
{
return DoSetLinkedKey(ssStore, wo);
}
case MiCasaRequestReply.VERB_REMOVE_LINKED_KEY:
{
return DoRemoveLinkedKey(ssStore, wo);
}
case MiCasaRequestReply.VERB_GET_LINKED_KEYS:
{
return DoGetLinkedKeys(ssStore, wo);
}
case MiCasaRequestReply.VERB_CREATE_TEST_SECRETS:
{
return DoCreateTestSecrets(ssStore, wo);
}
case MiCasaRequestReply.VERB_REMOVE_TEST_SECRETS:
{
return DoRemoveTestSecrets(ssStore, wo);
}
case MiCasaRequestReply.VERB_DUMP_LINKED_KEYS:
{
return DoDumpLinkedKeys(ssStore, wo);
}
case MiCasaRequestReply.VERB_WRITE_KEY:
{
return DoWriteKey(ssStore, wo);
}
case MiCasaRequestReply.VERB_LOCK_STORE:
{
ssStore.LockStore();
return wo;
}
case MiCasaRequestReply.VERB_UNLOCK_STORE:
{
return DoUnlockStore(ssStore, wo);
}
case MiCasaRequestReply.VERB_REMOVE_ALL_SECRETS:
{
// stop persistence
//ssStore.StopPersistence();
// remove secrets
return DoRemoveAllSecrets(ssStore, wo);
}
case MiCasaRequestReply.VERB_GET_STORE_STATUS:
{
wo.SetObject(ssStore.GetSecretStoreState());
return wo;
}
case MiCasaRequestReply.VERB_REMOVE_KEY:
{
return DoRemoveKey(ssStore, wo);
}
case MiCasaRequestReply.VERB_READ_KEY:
{
return DoReadKey(ssStore, wo);
}
case MiCasaRequestReply.VERB_GET_KEY_LIST:
{
return DoGetKeyList(ssStore, wo);
}
case MiCasaRequestReply.VERB_RESET_MASTER_PASSWORD:
{
return DoResetMasterPassword(ssStore, wo);
}
default:
{
wo.SetError(constants.RetCodes.FAILURE, "Verb Not Supported");
return wo;
}
}
}
catch (Exception e)
{
wo.SetError(constants.RetCodes.FAILURE, e.ToString());
}
return wo;
}
private WrappedObject DoRemoveAllSecrets(SecretStore ssStore, WrappedObject wo)
{
if (!ssStore.IsStoreLocked())
{
string sKeyChainID = wo.GetKeychainID();
if (sKeyChainID != null)
{
KeyChain kc = ssStore.GetKeyChain(sKeyChainID);
kc.RemoveAllSecrets();
ssStore.UpdatePersistentStore();
}
}
else
{
wo.SetError(constants.RetCodes.FAILURE, "Store locked");
}
return wo;
}
private WrappedObject DoUnlockStore(SecretStore ssStore, WrappedObject wo)
{
try
{
string sMasterPassword = (string)wo.GetObject();
ssStore.UnlockStore(null, sMasterPassword);
}
catch (Exception e)
{
wo.SetError(constants.RetCodes.FAILURE, e.ToString());
}
return wo;
}
private WrappedObject DoRemoveKey(SecretStore ssStore, WrappedObject wo)
{
try
{
string keychainID = wo.GetKeychainID();
string secretID = wo.GetSecretID();
string keyID = wo.GetKeyID();
KeyChain keyChain = ssStore.GetKeyChain(keychainID);
Secret secret = null;
if( keyChain.CheckIfSecretExists(secretID) == false)
{
wo.SetError(constants.RetCodes.FAILURE,"Secret does not exist");
}
else
{
secret = keyChain.GetSecret(secretID);
secret.RemoveKeyValue(keyChain, keyID);
wo.SetError(constants.RetCodes.SUCCESS, null);
ssStore.UpdatePersistentStore();
}
}
catch (Exception e)
{
wo.SetError(constants.RetCodes.FAILURE, e.ToString());
}
return wo;
}
private WrappedObject DoReadKey(SecretStore ssStore, WrappedObject wo)
{
if (!ssStore.IsStoreLocked())
{
try
{
string keychainID = wo.GetKeychainID();
string secretID = wo.GetSecretID();
string keyID = wo.GetKeyID();
// string sValue = (String)wo.GetObject();
KeyChain keyChain = ssStore.GetKeyChain(keychainID);
Secret secret = null;
if( keyChain.CheckIfSecretExists(secretID) == false)
{
wo.SetError(constants.RetCodes.FAILURE,"Secret does not exist");
}
else
{
secret = keyChain.GetSecret(secretID);
KeyValue kv = secret.GetKeyValue(keyID);
string value = kv.GetValue();
wo.SetObject(value);
wo.SetError(constants.RetCodes.SUCCESS, null);
}
}
catch (Exception e)
{
wo.SetError(constants.RetCodes.FAILURE, e.ToString());
}
}
else
wo.SetError(constants.RetCodes.FAILURE, "Store locked");
return wo;
}
private WrappedObject DoGetKeyList(SecretStore ssStore, WrappedObject wo)
{
try
{
string keychainID = wo.GetKeychainID();
string secretID = wo.GetSecretID();
KeyChain keyChain = ssStore.GetKeyChain(keychainID);
Secret secret = null;
if( keyChain.CheckIfSecretExists(secretID) == false)
{
wo.SetError(constants.RetCodes.FAILURE,"Secret does not exist");
}
else
{
secret = keyChain.GetSecret(secretID);
if( null != secret )
{
ArrayList keyList = secret.GetKeyList();
wo.SetObject(keyList);
wo.SetError(constants.RetCodes.SUCCESS, null);
}
}
}
catch (Exception e)
{
wo.SetError(constants.RetCodes.FAILURE, e.ToString());
}
return wo;
}
private WrappedObject DoWriteKey(SecretStore ssStore, WrappedObject wo)
{
if (!ssStore.IsStoreLocked())
{
try
{
string keychainID = wo.GetKeychainID();
string secretID = wo.GetSecretID();
string keyID = wo.GetKeyID();
string sValue = (String)wo.GetObject();
if (secretID.IndexOf("*") < 0)
{
KeyChain keyChain = ssStore.GetKeyChain(keychainID);
Secret secret;
if( keyChain.CheckIfSecretExists(secretID) == false)
{
secret = new Secret(secretID);
keyChain.AddSecret(secret);
}
else
{
secret = keyChain.GetSecret(secretID);
}
secret.SetKeyValue(keyID, sValue);
ChangeLinkedKeys(keyChain, secret, keyID, sValue);
wo.SetError(constants.RetCodes.SUCCESS, null);
ssStore.UpdatePersistentStore();
}
else
wo.SetError(constants.RetCodes.FAILURE, null);
}
catch (Exception e)
{
wo.SetError(constants.RetCodes.FAILURE, e.ToString());
}
}
else
wo.SetError(constants.RetCodes.FAILURE, "Store locked");
return wo;
}
private void ChangeLinkedKeys(KeyChain keyChain, Secret secret, string key, string valStr)
{
Hashtable htLinkedkeys = secret.GetLinkedKeys(key);
if (htLinkedkeys != null)
{
// enumerate the hashtable, getting each secret/key and change it's value
ICollection coll = htLinkedkeys.Values;
IDictionaryEnumerator ienum = (IDictionaryEnumerator)coll.GetEnumerator();
LinkedKeyInfo linkedInfo; // = (LinkedKeyInfo)ienum.Current;
while (ienum.MoveNext())
{
linkedInfo = (LinkedKeyInfo)ienum.Value;
// Get the target Secret
Secret targetSecret = keyChain.GetSecret(linkedInfo.GetLinkedSecretID());
if (targetSecret != null)
{
// get target key value
string targetKey = linkedInfo.GetLinkedKeyID();
string targetkv = targetSecret.GetKeyValue(targetKey).GetValue();
// if a change is required in the target, then call this method recursively using the TargetSecret
if (!targetkv.Equals(valStr))
{
// NOTE: ORDER IS IMPORTANT
// first change this one
targetSecret.SetKeyValue(linkedInfo.GetLinkedKeyID(), valStr);
// now call the traget to change it's linked ones
ChangeLinkedKeys(keyChain, targetSecret, targetKey, valStr);
}
}
}
}
}
private WrappedObject DoDumpLinkedKeys(SecretStore ssStore, WrappedObject wo)
{
// create 2 secrets
string keychainID = wo.GetKeychainID();
KeyChain keyChain;
Console.WriteLine("\r\n*********Dumping Linked Keys");
try
{
keyChain = ssStore.GetKeyChain(keychainID);
}
catch (Exception)
{
keyChain = new KeyChain(keychainID);
ssStore.AddKeyChain(keyChain);
}
// enumerate all secrets
IDictionaryEnumerator ienum = (IDictionaryEnumerator)keyChain.GetAllSecrets();
ienum.Reset();
while (ienum.MoveNext())
{
string secretID = (string)ienum.Key;
Secret secret = keyChain.GetSecret(secretID);
IDictionaryEnumerator idenum = secret.GetKeyValueEnumerator();
idenum.Reset();
while (idenum.MoveNext())
{
KeyValue kv = (KeyValue)idenum.Value;
Hashtable htLKI = kv.GetLinkedKeys();
if (htLKI != null)
{
Console.WriteLine(secret.GetKey() + ":" + kv.Key + " is Linked to");
IDictionaryEnumerator htienum = (IDictionaryEnumerator)htLKI.GetEnumerator();
htienum.Reset();
while (htienum.MoveNext())
{
LinkedKeyInfo lki = (LinkedKeyInfo) htienum.Value;
Console.WriteLine(" " + lki.GetLinkID());
}
}
}
}
return wo;
}
string GW = "SS_CredSet:TestGroupwise\0";
string IFOLDER = "SS_CredSet:TestiFolder\0";
string GWIM = "SS_CredSet:TestGWIM\0";
private WrappedObject DoRemoveTestSecrets(SecretStore ssStore, WrappedObject wo)
{
string keychainID = wo.GetKeychainID();
KeyChain keyChain;
try
{
keyChain = ssStore.GetKeyChain(keychainID);
}
catch (Exception)
{
return wo;
}
try
{
keyChain.RemoveSecret(GW);
}
catch (Exception)
{}
try
{
keyChain.RemoveSecret(GWIM);
}
catch (Exception)
{}
try
{
keyChain.RemoveSecret(IFOLDER);
}
catch (Exception)
{}
return wo;
}
private WrappedObject DoCreateTestSecrets(SecretStore ssStore, WrappedObject wo)
{
// create 2 secrets
string keychainID = wo.GetKeychainID();
KeyChain keyChain;
try
{
keyChain = ssStore.GetKeyChain(keychainID);
}
catch (Exception)
{
keyChain = new KeyChain(keychainID);
ssStore.AddKeyChain(keyChain);
}
Secret secret1 = GetOrCreateSecret(keyChain, GW);
secret1.SetKeyValue("CN", "User1");
secret1.SetKeyValue("Password", "GWPass");
try
{
keyChain.AddSecret(secret1);
}
catch (Exception)
{}
Secret secret2 = GetOrCreateSecret(keyChain, IFOLDER);
secret2.SetKeyValue("CN", "User2");
secret2.SetKeyValue("Password", "IfolderPass");
secret2.SetKeyValue("EmployeeID", "123456");
try
{
keyChain.AddSecret(secret2);
}
catch (Exception)
{}
Secret secret3 = GetOrCreateSecret(keyChain,GWIM);
secret3.SetKeyValue("CN", "User3");
secret3.SetKeyValue("Password", "GwimPass");
try
{
keyChain.AddSecret(secret3);
}
catch (Exception)
{}
try
{
// link password fields
KeyValue kv = secret1.GetKeyValue("Password");
KeyValue kv2 = secret2.GetKeyValue("Password");
KeyValue kv3 = secret3.GetKeyValue("Password");
kv.AddLink(new LinkedKeyInfo(IFOLDER, "Password"));
kv2.AddLink(new LinkedKeyInfo(GW, "Password"));
kv2.AddLink(new LinkedKeyInfo(GWIM, "Password"));
kv3.AddLink(new LinkedKeyInfo(IFOLDER, "Password"));
kv3.AddLink(new LinkedKeyInfo(GW, "Password"));
kv.AddLink(new LinkedKeyInfo(GWIM, "Password"));
}
catch (Exception e)
{
//Console.WriteLine(e.ToString());
}
#if DEBUG
DoDumpLinkedKeys(ssStore, wo);
#endif
return wo;
}
private Secret GetOrCreateSecret(KeyChain kc, string sID)
{
try
{
return kc.GetSecret(sID);
}
catch (Exception)
{
return new Secret(sID);
}
}
private WrappedObject DoGetLinkedKeys(SecretStore ssStore, WrappedObject wo)
{
string keychainID = wo.GetKeychainID();
string secretID = wo.GetSecretID();
string keyID = wo.GetKeyID();
KeyChain keyChain = ssStore.GetKeyChain(keychainID);
Secret secret = keyChain.GetSecret(secretID);
KeyValue kv = secret.GetKeyValue(keyID);
wo.SetObject(kv.GetLinkedKeys());
wo.SetError(constants.RetCodes.SUCCESS, null);
return wo;
}
private WrappedObject DoRemoveLinkedKey(SecretStore ssStore, WrappedObject wo)
{
string keychainID = wo.GetKeychainID();
string secretID = wo.GetSecretID();
string keyID = wo.GetKeyID();
KeyChain keyChain = ssStore.GetKeyChain(keychainID);
Secret secret = keyChain.GetSecret(secretID);
KeyValue kv = secret.GetKeyValue(keyID);
LinkedKeyInfo lki = (LinkedKeyInfo)wo.GetObject();
kv.RemoveLink(lki.GetLinkID());
// remove reverse link as well
Secret targetSecret = keyChain.GetSecret(lki.GetLinkedSecretID());
KeyValue targetkv = targetSecret.GetKeyValue(lki.GetLinkedKeyID());
targetkv.RemoveLink(secretID+":"+keyID);
ssStore.UpdatePersistentStore();
return wo;
}
private WrappedObject DoSetLinkedKey(SecretStore ssStore, WrappedObject wo)
{
string keychainID = wo.GetKeychainID();
string secretID = wo.GetSecretID();
string keyID = wo.GetKeyID();
KeyChain keyChain = ssStore.GetKeyChain(keychainID);
Secret secret = keyChain.GetSecret(secretID);
KeyValue kv = secret.GetKeyValue(keyID);
LinkedKeyInfo lki = (LinkedKeyInfo)wo.GetObject();
kv.AddLink(lki);
// add reverse link
try
{
Secret target = keyChain.GetSecret(lki.GetLinkedSecretID());
KeyValue targetkv = target.GetKeyValue(lki.GetLinkedKeyID());
targetkv.AddLink(new LinkedKeyInfo(secretID, keyID));
ssStore.UpdatePersistentStore();
}
catch (Exception e)
{
Console.WriteLine("Reverse Link error: " + e.ToString());
wo.SetError(constants.RetCodes.FAILURE, "Reverse Link: " + e.ToString());
}
return wo;
}
private WrappedObject DoResetMasterPassword(SecretStore ssStore, WrappedObject wo)
{
ResetMasterPassword rmp = (ResetMasterPassword)wo.GetObject();
// verify current master password
try
{
string sMasterPassword = rmp.m_currentPassword;
ssStore.UnlockStore(null, sMasterPassword);
}
catch (Exception e)
{
wo.SetError(constants.RetCodes.FAILURE, e.ToString());
return wo;
}
// change master master password
string sNewPassword = rmp.m_newPassword;
if (sNewPassword == null || sNewPassword.Length < 8)
{
wo.SetError(constants.RetCodes.FAILURE, null);
return wo;
}
if (!ssStore.ChangeMasterPassword(rmp.m_currentPassword, rmp.m_newPassword))
wo.SetError(constants.RetCodes.FAILURE, null);
else
wo.SetError(constants.RetCodes.SUCCESS, null);
return wo;
}
private WrappedObject DoPing(WrappedObject wo)
{
//Console.WriteLine("MICASAD received Ping from Client");
wo.SetError(IPCRetCodes.SSCS_REPLY_SUCCESS, null);
Ping ping = (Ping)wo.GetObject();
ping.servermessage = "MICASAD echos client message: <" + ping.clientmessage + ">";
return wo;
}
/*
internal WrappedObject ProcessMessage(WrappedObject wo, UserIdentifier userId)
{
Console.WriteLine("ObjectSerialization Called");
SecretStore ssStore = SessionManager.CreateUserSession(userId);
Secret secret;
try
{
keyChainId = wo.GetKeychainID();
secretId = wo.GetSecretID();
keyId = wo.GetKeyID();
int action = wo.GetAction();
if (action == WrappedObject.VERB_PING_MICASAD)
{
Console.WriteLine("MICASAD received Ping from Client");
wo.SetError(IPCRetCodes.SSCS_REPLY_SUCCESS, null);
Ping ping = (Ping)wo.GetObject();
ping.servermessage = "MICASAD echos client message: <" + ping.clientmessage + ">";
return wo;
}
else if (action <= WrappedObject.VERB_REMOVE_LINKED_KEY)
{
wo.SetError(IPCRetCodes.SSCS_REPLY_SUCCESS, null);
if (action == WrappedObject.VERB_GET_STORE)
{
wo.SetObject(ssStore);
return wo;
}
// look up Keychain
KeyChain keyChain = new KeyChain(keyChainId);
// temporary
try
{
if (true)
ssStore.AddKeyChain(keyChain);
}
catch (Exception e)
{
}
if( ssStore.CheckIfKeyChainExists(keyChainId) )
{
keyChain = ssStore.GetKeyChain(keyChainId);
if (action == WrappedObject.VERB_GET_KEYCHAIN)
{
wo.SetObject(keyChain);
return wo;
}
if((action == WrappedObject.VERB_GET_SECRET) && (keyChain.CheckIfSecretExists(secretId) == false))
{
wo.SetError(IPCRetCodes.SSCS_E_SECRETID_DOES_NOT_EXIST, null);
return wo;
}
else
{
secret = keyChain.GetSecret(secretId);
if (action == WrappedObject.VERB_GET_SECRET)
{
wo.SetObject(secret);
return wo;
}
else if ((action == WrappedObject.VERB_SET_SECRET) && (null != wo.GetObject()))
{
keyChain.AddSecret((Secret)wo.GetObject());
}
else if (action == WrappedObject.VERB_SET_LINKED_KEY)
{
KeyValue kv = secret.GetKeyValue(keyId);
LinkedKeyInfo lki = (LinkedKeyInfo)wo.GetObject();
kv.AddLink(lki);
// add reverse link
try
{
Secret target = keyChain.GetSecret(lki.GetLinkedSecretID());
KeyValue targetkv = target.GetKeyValue(lki.GetLinkedKeyID());
targetkv.AddLink(new LinkedKeyInfo(secretId, keyId));
}
catch (Exception e)
{
Console.WriteLine("Reverse Link error: " + e.ToString());
}
}
}
}
else
{
wo.SetError(IPCRetCodes.SSCS_E_KEYCHAIN_DOES_NOT_EXIST, null);
}
}
else
{
wo.SetError(IPCRetCodes.SSCS_E_SYSTEM_ERROR, "Action not supported");
}
}
catch (Exception e)
{
String error = e.ToString();
Console.WriteLine(error);
wo = new WrappedObject(constants.RetCodes.FAILURE, error);
}
return wo;
}
*/
public string GetVerbName()
{
CSSSLogger.ExecutionTrace(this);
return this.ToString();
}
}
}