diff --git a/CASA/micasad/micasad.csproj b/CASA/micasad/micasad.csproj
index acdcc823..bb031e92 100644
--- a/CASA/micasad/micasad.csproj
+++ b/CASA/micasad/micasad.csproj
@@ -245,6 +245,7 @@
Code
+
Code
diff --git a/CASA/micasad/verbs/MergeCache.cs b/CASA/micasad/verbs/MergeCache.cs
new file mode 100644
index 00000000..2d15a68e
--- /dev/null
+++ b/CASA/micasad/verbs/MergeCache.cs
@@ -0,0 +1,141 @@
+using System;
+using sscs.verbs;
+using sscs.cache;
+using sscs.common;
+using sscs.constants;
+using sscs.lss;
+
+namespace sscs.verbs
+{
+ ///
+ /// Summary description for MergeCache.
+ ///
+ internal class MergeCache : SSVerb
+ {
+ private ushort msgId = 0;
+ private uint inMsgLen = 0;
+ private uint outMsgLen = 0;
+
+ private int retCode = 0;
+
+ private byte[] inBuf;
+ private byte[] outBuf;
+
+ public void SetMessageContent(byte[] ipcBytes)
+ {
+ CSSSLogger.ExecutionTrace(this);
+ inBuf = ipcBytes;
+ }
+
+ /*
+ * This method does the actual implementation of MergeSecret
+ *
+ */
+
+ public byte[] ProcessRequest(UserIdentifier userId)
+ {
+
+ CSSSLogger.ExecutionTrace(this);
+ UserIdentifier tempUserId = userId;
+
+ /* 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);
+
+ if (inMsgLen != inBuf.Length)
+ throw new FormatException(" MsgLen sent does not match the length of the message received.");
+
+
+ // get the src LUID
+ int luidLow = BitConverter.ToInt32(inBuf, 14);
+ int luidHigh = BitConverter.ToInt32(inBuf, 18);
+
+ // get the target LUID
+ int targetLuidLow = BitConverter.ToInt32(inBuf, 30);
+ int targetLuidHigh = BitConverter.ToInt32(inBuf, 34);
+
+ // get destroy flag
+ int iDestroySrcCache = BitConverter.ToInt32(inBuf, 38);
+
+
+#if W32
+ // only allow the merge if the calling process is "System"
+ WinUserIdentifier callingUser = (WinUserIdentifier)userId;
+ if ((callingUser.GetUIDLow() == 999) && (callingUser.GetUIDHigh() == 0))
+ {
+
+ // get the store for the src
+ try
+ {
+ WinUserIdentifier srcUser = new WinUserIdentifier(luidLow, luidHigh);
+ SecretStore srcStore = SessionManager.GetUserSecretStore(srcUser);
+
+ WinUserIdentifier targetUser = new WinUserIdentifier(targetLuidLow, targetLuidHigh);
+ SecretStore targetStore = SessionManager.CreateUserSession(targetUser);
+
+ byte[] baSecrets = LocalStorage.GetSecretsAsXMLStream(srcStore, ConstStrings.SSCS_SESSION_KEY_CHAIN_ID).ToArray();
+
+ if (baSecrets != null)
+ {
+ targetStore.MergeXMLSecrets(baSecrets);
+ }
+
+ if (iDestroySrcCache > 0)
+ {
+ SessionManager.RemoveUserSession(srcUser, true);
+ }
+ }
+ catch (Exception e)
+ {
+ CSSSLogger.DbgLog(e.ToString());
+ retCode = IPCRetCodes.SSCS_E_INVALID_INPUT;
+ }
+ }
+ else
+ {
+ retCode = IPCRetCodes.SSCS_E_INVALID_INPUT;
+ }
+#else
+ retCode = IPCRetCodes.SSCS_E_SYSTEM_ERROR;
+#endif
+
+ try
+ {
+ msgId = 19;
+ outMsgLen = 10;
+ outBuf = new byte[10];
+ byte[] t = new byte[10];
+
+ t = BitConverter.GetBytes((ushort)msgId);
+ Array.Copy(t, 0, outBuf, 0, 2);
+
+ t = BitConverter.GetBytes((uint)outMsgLen);
+ Array.Copy(t, 0, outBuf, 2, 4);
+
+ t = BitConverter.GetBytes(retCode);
+ Array.Copy(t, 0, outBuf, 6, 4);
+ }
+ catch (Exception e)
+ {
+ CSSSLogger.ExpLog(e.ToString());
+ throw new FormatException("Unable to form the response " + e.ToString());
+ }
+
+ return outBuf;
+ }
+
+ /*
+ * Gives the name of operation performed. Will be used in case
+ * of error.
+ */
+ public string GetVerbName()
+ {
+ CSSSLogger.ExecutionTrace(this);
+ return this.ToString();
+ }
+ }
+}
diff --git a/CASA/sharp/Novell.Casa.MiCasa/MiCasa.cs b/CASA/sharp/Novell.Casa.MiCasa/MiCasa.cs
index 83f376e6..7fd9e433 100644
--- a/CASA/sharp/Novell.Casa.MiCasa/MiCasa.cs
+++ b/CASA/sharp/Novell.Casa.MiCasa/MiCasa.cs
@@ -103,17 +103,38 @@ namespace Novell.Casa
string sUsername,
string sPassword)
{
- NativeCalls.SetCredential(ssFlags, sAppSecretID, sSharedSecretID, unFlag, NativeCalls.SSCS_CRED_TYPE_BASIC_F, sUsername, sPassword);
+ SetCredential(ssFlags, sAppSecretID, sSharedSecretID, unFlag, sUsername, sPassword, null);
+ }
+
+ public static void SetCredential(
+ uint ssFlags,
+ string sAppSecretID,
+ string sSharedSecretID,
+ uint unFlag,
+ string sUsername,
+ string sPassword,
+ WinLuid luid)
+ {
+ NativeCalls.SetCredential(ssFlags, sAppSecretID, sSharedSecretID, unFlag, NativeCalls.SSCS_CRED_TYPE_BASIC_F, sUsername, sPassword, luid);
+ }
+
+ public static BasicCredential GetCredential(
+ uint ssFlags,
+ string sAppSecretID,
+ string sSharedSecretID,
+ uint unFlag)
+ {
+ return GetCredential(ssFlags, sAppSecretID, sSharedSecretID, unFlag, null);
}
public static BasicCredential GetCredential(
uint ssFlags,
string sAppSecretID,
string sSharedSecretID,
- uint unFlag)
-
+ uint unFlag,
+ WinLuid luid)
{
- return NativeCalls.GetCredential(ssFlags, sAppSecretID, sSharedSecretID, unFlag, NativeCalls.SSCS_CRED_TYPE_BASIC_F);
+ return NativeCalls.GetCredential(ssFlags, sAppSecretID, sSharedSecretID, unFlag, NativeCalls.SSCS_CRED_TYPE_BASIC_F, luid);
}
public static void RemoveCredential(
@@ -136,6 +157,11 @@ namespace Novell.Casa
string secretID)
{
return NativeCalls.IsSecretPersistent(ssFlags,secretID);
- }
+ }
+
+ public static void miCASAMergeCache(WinLuid srcLuid, WinLuid destLuid, bool bDestroySrcCache)
+ {
+ NativeCalls.miCASAMergeCache(srcLuid, destLuid, bDestroySrcCache);
+ }
}
}
diff --git a/CASA/sharp/Novell.Casa.MiCasa/NativeCalls.cs b/CASA/sharp/Novell.Casa.MiCasa/NativeCalls.cs
index 17888e3b..7106615e 100644
--- a/CASA/sharp/Novell.Casa.MiCasa/NativeCalls.cs
+++ b/CASA/sharp/Novell.Casa.MiCasa/NativeCalls.cs
@@ -122,6 +122,13 @@ namespace Novell.Casa
public byte[] password;
}
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ private struct LUID
+ {
+ public int luidLow;
+ public int luidHigh;
+ }
+
// * The following functions will be exposed as exported API:
// **************************************************************
// * These function calls will utilize the Support Functions for
@@ -204,6 +211,82 @@ namespace Novell.Casa
[In, Out] SSCS_EXT_T ext
);
+ [DllImport(NDK_LIBRARY)]
+ internal static extern int miCASAMergeCache
+ (
+ [In] SSCS_EXT_T extSrc,
+ [In] SSCS_EXT_T extDest,
+ [In] uint bDestroySrcCache
+ );
+
+
+ internal static void miCASAMergeCache(WinLuid srcLUID, WinLuid destLUID, bool bDestroySrc)
+ {
+ // marshall the luids
+ SSCS_EXT_T extSrc = new SSCS_EXT_T();
+ LUID sluid;
+ if (srcLUID != null)
+ {
+ // allocate a structure to marshal
+ sluid = new LUID();
+ sluid.luidHigh = srcLUID.GetHighPart();
+ sluid.luidLow = srcLUID.GetLowPart();
+
+ extSrc.extID = 1;
+ extSrc.version = 1;
+ extSrc.ext = Marshal.AllocHGlobal(Marshal.SizeOf(sluid));
+
+ Marshal.StructureToPtr(sluid, extSrc.ext, false);
+ }
+ else
+ {
+ throw new MiCasaException(MiCasaException.NSSCS_E_INVALID_PARAM);
+ }
+
+ SSCS_EXT_T extDest = new SSCS_EXT_T();
+ LUID dluid;
+ if (destLUID != null)
+ {
+ // allocate a structure to marshal
+ dluid = new LUID();
+ dluid.luidHigh = destLUID.GetHighPart();
+ dluid.luidLow = destLUID.GetLowPart();
+
+ extDest.extID = 1;
+ extDest.version = 1;
+ extDest.ext = Marshal.AllocHGlobal(Marshal.SizeOf(dluid));
+
+ Marshal.StructureToPtr(dluid, extDest.ext, false);
+ }
+ else
+ {
+ throw new MiCasaException(MiCasaException.NSSCS_E_INVALID_PARAM);
+ }
+
+
+ uint iDestroySrcCache = 0;
+ if (bDestroySrc)
+ {
+ iDestroySrcCache = 1;
+ }
+
+ // make the call
+ int rcode = miCASAMergeCache(extSrc, extDest, iDestroySrcCache);
+
+ if (extSrc.ext != IntPtr.Zero)
+ Marshal.FreeHGlobal(extSrc.ext);
+
+ if (extDest.ext != IntPtr.Zero)
+ Marshal.FreeHGlobal(extDest.ext);
+
+ if (rcode != 0)
+ {
+ throw new MiCasaException(rcode);
+ }
+
+ }
+
+
///
///
@@ -216,7 +299,8 @@ namespace Novell.Casa
string sAppSecretID,
string sSharedSecretID,
uint unFlag,
- uint credType)
+ uint credType,
+ WinLuid luid)
{
if (sAppSecretID == null || sAppSecretID.Length == 0)
throw new MiCasaException(MiCasaException.NSSCS_E_INVALID_PARAM);
@@ -243,6 +327,24 @@ namespace Novell.Casa
IntPtr pCredential = Marshal.AllocHGlobal(Marshal.SizeOf(credential));
Marshal.StructureToPtr(credential, pCredential, false);
+ // marshall luid if there is one
+ SSCS_EXT_T ext = new SSCS_EXT_T();
+ LUID sluid;
+ if ((luid != null) &&
+ ((luid.GetHighPart() != 0) || (luid.GetLowPart() != 0)))
+ {
+ // allocate a structure to marshal
+ sluid = new LUID();
+ sluid.luidHigh = luid.GetHighPart();
+ sluid.luidLow = luid.GetLowPart();
+
+ ext.extID = 1;
+ ext.version = 1;
+ ext.ext = Marshal.AllocHGlobal(Marshal.SizeOf(sluid));
+
+ Marshal.StructureToPtr(sluid, ext.ext, false);
+ }
+
try
{
rcode = miCASAGetCredential(
@@ -251,7 +353,7 @@ namespace Novell.Casa
sharedID,
ref credType,
pCredential,
- new SSCS_EXT_T()
+ ext
);
}
catch (Exception)
@@ -287,7 +389,8 @@ namespace Novell.Casa
uint unFlag,
uint uCredType,
string sUsername,
- string sPassword)
+ string sPassword,
+ WinLuid luid)
{
if (sAppSecretID == null || sUsername == null || sPassword == null
@@ -320,13 +423,31 @@ namespace Novell.Casa
Marshal.StructureToPtr(credential, pCredential, true);
+ SSCS_EXT_T ext = new SSCS_EXT_T();
+ LUID sluid;
+ if ((luid != null) &&
+ ((luid.GetHighPart() != 0) || (luid.GetLowPart() != 0)))
+ {
+ // allocate a structure to marshal
+ sluid = new LUID();
+ sluid.luidHigh = luid.GetHighPart();
+ sluid.luidLow = luid.GetLowPart();
+
+ ext.extID = 1;
+ ext.version = 1;
+ ext.ext = Marshal.AllocHGlobal(Marshal.SizeOf(sluid));
+
+ Marshal.StructureToPtr(sluid, ext.ext, false);
+ }
+
+
rcode = miCASASetCredential
(ssFlags,
appSecretID,
sharedID,
uCredType,
pCredential,
- new SSCS_EXT_T()
+ ext
);
if (rcode != 0)
diff --git a/CASA/sharp/Novell.Casa.MiCasa/WinLuid.cs b/CASA/sharp/Novell.Casa.MiCasa/WinLuid.cs
new file mode 100644
index 00000000..dd00fef0
--- /dev/null
+++ b/CASA/sharp/Novell.Casa.MiCasa/WinLuid.cs
@@ -0,0 +1,29 @@
+using System;
+
+namespace Novell.Casa
+{
+ ///
+ /// Summary description for WinLuid.
+ ///
+ public class WinLuid
+ {
+ private int m_low = 0;
+ private int m_high = 0;
+
+ public WinLuid(int lowPart, int highPart )
+ {
+ m_low = lowPart;
+ m_high = highPart;
+ }
+
+ public int GetLowPart()
+ {
+ return m_low;
+ }
+
+ public int GetHighPart()
+ {
+ return m_high;
+ }
+ }
+}