Add code to Novell.Casa.MiCall.dll to allow access to SERVER_KEY_CHAIN.

Windows only change.
This commit is contained in:
Jim Norman 2008-05-12 17:42:41 +00:00
parent 83e1a14664
commit 7cfc9a8114
5 changed files with 2051 additions and 1440 deletions

File diff suppressed because it is too large Load Diff

View File

@ -21,7 +21,8 @@
***********************************************************************/ ***********************************************************************/
using System; using System;
using System.Collections.Specialized;
using Novell.Casa; using Novell.Casa;
namespace Novell.Casa namespace Novell.Casa
@ -42,6 +43,9 @@ namespace Novell.Casa
private static uint SSCS_CRED_TYPE_BINARY_F = 0x00000002; private static uint SSCS_CRED_TYPE_BINARY_F = 0x00000002;
private static uint SSCS_CRED_TYPE_SERVER_F = 0x00000004; private static uint SSCS_CRED_TYPE_SERVER_F = 0x00000004;
public static string SESSION_KEY_CHAIN = "SSCS_SESSION_KEY_CHAIN_ID";
public static string SERVER_KEY_CHAIN = "SSCS_SERVER_KEY_CHAIN_ID";
public MiCasa() public MiCasa()
{ {
// //
@ -185,6 +189,26 @@ namespace Novell.Casa
public static void miCASAMergeCache(WinLuid srcLuid, WinLuid destLuid, bool bDestroySrcCache) public static void miCASAMergeCache(WinLuid srcLuid, WinLuid destLuid, bool bDestroySrcCache)
{ {
NativeCalls.miCASAMergeCache(srcLuid, destLuid, bDestroySrcCache); NativeCalls.miCASAMergeCache(srcLuid, destLuid, bDestroySrcCache);
}
public static StringCollection GetSecretIDs()
{
return GetSecretIDs(SESSION_KEY_CHAIN);
}
public static StringCollection GetSecretIDs(String sKeyChainID)
{
return NativeCalls.EnumerateSecretIDs(0, sKeyChainID, "");
}
public static Secret GetSecret(String sSecretID)
{
return GetSecret(SESSION_KEY_CHAIN, sSecretID);
}
public static Secret GetSecret(String sKeyChainID, String sSecretID)
{
return NativeCalls.GetSecret(sKeyChainID, 0, sSecretID, Secret.SS_CREDSET, null);
} }
} }
} }

View File

@ -37,7 +37,7 @@ namespace Novell.Casa
internal static uint SSCS_CRED_TYPE_BASIC_F = 1; internal static uint SSCS_CRED_TYPE_BASIC_F = 1;
internal static uint SSCS_CRED_TYPE_SERVER_F = 4; internal static uint SSCS_CRED_TYPE_SERVER_F = 4;
private static int USERNAME_LEN = 256; private static int USERNAME_LEN = 256;
private static int PASSWORD_LEN = 128; private static int PASSWORD_LEN = 128;
public NativeCalls() public NativeCalls()
{ {
@ -129,6 +129,39 @@ namespace Novell.Casa
public int luidHigh; public int luidHigh;
} }
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class SSCS_SRCH_KEY_T
{
public uint srchKeyLen;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 128)]
public string srchKey; //[NSSCS_MAX_SRCH_KEY_LEN]; //* should be passed in # of chars
} ;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class SSCS_SECRET_ID_LIST_T
{
public uint enumHandle;
public uint returnedIDs;
public IntPtr secretIDList; //* an array of secretID structures
};
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class SSCS_SH_SECRET_ID_LIST_T
{
public uint enumHandle;
public uint returnedIDs;
public IntPtr secretIDList; //* an array of secretID structures
};
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class SSCS_READEXT_T
{
public uint statFlags; //* OUT - return flags on the secret
public uint crtStamp; //* OUT - secret creation time stamp
public uint latStamp; //* OUT - last accessed time stamp (optional)
public uint lmtStamp; //* OUT - last modified time stamp
};
// * The following functions will be exposed as exported API: // * The following functions will be exposed as exported API:
// ************************************************************** // **************************************************************
// * These function calls will utilize the Support Functions for // * These function calls will utilize the Support Functions for
@ -137,6 +170,18 @@ namespace Novell.Casa
private const string NDK_LIBRARY = "micasa"; private const string NDK_LIBRARY = "micasa";
[DllImport(NDK_LIBRARY)]
internal static extern int miCASAEnumerateSecretIDs
(
[In] IntPtr context,
[In] SSCS_KEYCHAIN_ID_T keyChainID,
[In] uint ssFlags,
[In] SSCS_SRCH_KEY_T searchKey,
[In, Out] SSCS_SH_SECRET_ID_LIST_T secretIDList,
[In, Out] SSCS_EXT_T ext
);
[DllImport(NDK_LIBRARY)] [DllImport(NDK_LIBRARY)]
internal static extern int miCASAGetCredential internal static extern int miCASAGetCredential
( (
@ -204,26 +249,73 @@ namespace Novell.Casa
[In, Out] SSCS_EXT_T ext [In, Out] SSCS_EXT_T ext
); );
[DllImport(NDK_LIBRARY)]
internal static extern int miCASAReadSecret
(
[In] IntPtr context,
[In] SSCS_KEYCHAIN_ID_T keyChainID,
[In] uint ssFlags,
[In] IntPtr secretHandle,
[In] SSCS_SH_SECRET_ID_T sharedSecretID,
[In] SSCS_PASSWORD_T epPassword,
[In, Out] SSCS_READEXT_T readData,
[In, Out] SSCS_EXT_T ext
);
[DllImport(NDK_LIBRARY, CharSet = CharSet.None)] [DllImport(NDK_LIBRARY, CharSet = CharSet.None)]
internal static extern int miCASAWriteKey internal static extern int miCASAWriteKey
( (
[In] IntPtr context, [In] IntPtr context,
[In] uint ssFlags, [In] uint ssFlags,
[In] SSCS_KEYCHAIN_ID_T keyChainID, [In] SSCS_KEYCHAIN_ID_T keyChainID,
[In] SSCS_SH_SECRET_ID_T sharedSecretID, [In] SSCS_SECRET_ID_T sharedSecretID,
[MarshalAs(UnmanagedType.LPStr)] [MarshalAs(UnmanagedType.LPStr)]
string key, string key,
[In] uint keyLenBytes, // in bytes [In] uint keyLenBytes, // in bytes
[MarshalAs(UnmanagedType.LPStr)] [MarshalAs(UnmanagedType.LPStr)]
string val, string val,
[In] uint valueLenBytes, // in bytes [In] uint valueLenBytes, // in bytes
[In] SSCS_PASSWORD_T password, [In] SSCS_PASSWORD_T password,
[In, Out] SSCS_EXT_T ext [In, Out] SSCS_EXT_T ext
); );
[DllImport(NDK_LIBRARY, CharSet = CharSet.None)]
internal static extern int miCASARemoveKey
(
[In] IntPtr context,
[In] uint ssFlags,
[In] SSCS_KEYCHAIN_ID_T keyChainID,
[In] SSCS_SECRET_ID_T sharedSecretID,
[MarshalAs(UnmanagedType.LPStr)]
string key,
[In] uint keyLenBytes, // in bytes
[In] SSCS_PASSWORD_T password,
[In, Out] SSCS_EXT_T ext
);
[DllImport(NDK_LIBRARY)]
internal static extern IntPtr miCASA_CreateSHSHandle();
[DllImport(NDK_LIBRARY)]
internal static extern int miCASA_DestroySHSHandle(
[In] IntPtr secretHandle);
[DllImport(NDK_LIBRARY, CharSet = CharSet.None)]
internal static extern int miCASA_GetNextSHSEntry
(
[In] int restart, //* in (set to 1 to begin from head of list)
[In] IntPtr secretHandle, //* in
[In, Out] ref uint keyLen, //* out
IntPtr theKey,
[In, Out] ref uint valLen, //* out
IntPtr theValue
);
[DllImport(NDK_LIBRARY)] [DllImport(NDK_LIBRARY)]
internal static extern int miCASAMergeCache internal static extern int miCASAMergeCache
( (
[In] SSCS_EXT_T extSrc, [In] SSCS_EXT_T extSrc,
[In] SSCS_EXT_T extDest, [In] SSCS_EXT_T extDest,
[In] uint bDestroySrcCache [In] uint bDestroySrcCache
@ -273,7 +365,7 @@ namespace Novell.Casa
throw new MiCasaException(MiCasaException.NSSCS_E_INVALID_PARAM); throw new MiCasaException(MiCasaException.NSSCS_E_INVALID_PARAM);
} }
uint iDestroySrcCache = 0; uint iDestroySrcCache = 0;
if (bDestroySrc) if (bDestroySrc)
{ {
@ -282,7 +374,7 @@ namespace Novell.Casa
// make the call // make the call
int rcode = miCASAMergeCache(extSrc, extDest, iDestroySrcCache); int rcode = miCASAMergeCache(extSrc, extDest, iDestroySrcCache);
if (extSrc.ext != IntPtr.Zero) if (extSrc.ext != IntPtr.Zero)
Marshal.FreeHGlobal(extSrc.ext); Marshal.FreeHGlobal(extSrc.ext);
@ -305,17 +397,17 @@ namespace Novell.Casa
/// <returns></returns> /// <returns></returns>
internal static BasicCredential GetCredential( internal static BasicCredential GetCredential(
uint ssFlags, uint ssFlags,
string sAppSecretID, string sAppSecretID,
string sSharedSecretID, string sSharedSecretID,
uint unFlag, uint unFlag,
uint credType, uint credType,
WinLuid luid) WinLuid luid)
{ {
if (sAppSecretID == null || sAppSecretID.Length == 0) if (sAppSecretID == null || sAppSecretID.Length == 0)
throw new MiCasaException(MiCasaException.NSSCS_E_INVALID_PARAM); throw new MiCasaException(MiCasaException.NSSCS_E_INVALID_PARAM);
int rcode; int rcode;
BasicCredential bc = null; BasicCredential bc = null;
SSCS_SECRET_ID_T appSecretID = new SSCS_SECRET_ID_T(); SSCS_SECRET_ID_T appSecretID = new SSCS_SECRET_ID_T();
@ -447,7 +539,7 @@ namespace Novell.Casa
ext.version = 1; ext.version = 1;
ext.ext = Marshal.AllocHGlobal(Marshal.SizeOf(sluid)); ext.ext = Marshal.AllocHGlobal(Marshal.SizeOf(sluid));
Marshal.StructureToPtr(sluid, ext.ext, false); Marshal.StructureToPtr(sluid, ext.ext, false);
} }
@ -648,7 +740,362 @@ namespace Novell.Casa
} }
return sb.ToString(); return sb.ToString();
} }
internal static IntPtr OpenSecretStore(string sSecretStoreName)
{
//check params
if (sSecretStoreName == null || sSecretStoreName.Length == 0)
throw new MiCasaException(MiCasaException.NSSCS_E_INVALID_PARAM);
SSCS_SECRET_STORE_ID_T SSid = new SSCS_SECRET_STORE_ID_T();
SSid.id = sSecretStoreName;
SSid.version = 0;
SSCS_EXT_T ext = new SSCS_EXT_T();
try
{
IntPtr hSC = miCASAOpenSecretStoreCache(SSid, 0, ext);
return hSC;
}
catch (Exception)
{
return IntPtr.Zero;
}
}
internal static void CloseSecretStore(IntPtr hSC)
{
SSCS_EXT_T ext = new SSCS_EXT_T();
miCASACloseSecretStoreCache(hSC, 0, ext);
}
internal static StringCollection EnumerateSecretIDs(
uint ssFlags,
string sKeyChainID,
string sSearchKey)
{
IntPtr context;
if (sKeyChainID == null || sSearchKey == null
|| sKeyChainID.Length == 0)
{
throw new MiCasaException(MiCasaException.NSSCS_E_INVALID_PARAM);
}
context = OpenSecretStore("SecretStore");
if (context == IntPtr.Zero)
{
throw new MiCasaException(MiCasaException.NSSCS_E_SYSTEM_FAILURE);
}
// setup structures
SSCS_KEYCHAIN_ID_T keyChainID = new SSCS_KEYCHAIN_ID_T();
keyChainID.keychainID = sKeyChainID;
SSCS_SRCH_KEY_T searchKey = new SSCS_SRCH_KEY_T();
SSCS_SH_SECRET_ID_LIST_T idList = new SSCS_SH_SECRET_ID_LIST_T();
SSCS_EXT_T ext = new SSCS_EXT_T();
int numIDS = 1024;
StringCollection sc = new StringCollection(); //null;
// setup keychainid
keyChainID.len = sKeyChainID.Length + 1;
searchKey.srchKey = sSearchKey;
searchKey.srchKeyLen = (uint)sSearchKey.Length;
idList.returnedIDs = (uint)numIDS;
SSCS_SH_SECRET_ID_T secretId = new SSCS_SH_SECRET_ID_T();
// secretId.name = new char[512];
StringBuilder buffer3 = new StringBuilder("content", 512);
buffer3.Append((char)0);
buffer3.Append('*', buffer3.Capacity - 8);
String tempStr = buffer3.ToString();
idList.secretIDList = Marshal.AllocHGlobal(numIDS * Marshal.SizeOf(secretId));
// make the call
int rcode = miCASAEnumerateSecretIDs(
context,
keyChainID,
ssFlags,
searchKey,
idList,
ext);
if (idList.returnedIDs > 0)
{
sc = new StringCollection();
if (idList.returnedIDs != numIDS)
{
// enumerate returned list
for (int i = 0; i < idList.returnedIDs; i++)
{
IntPtr temp = new IntPtr(idList.secretIDList.ToInt32() + (i * Marshal.SizeOf(secretId)));
secretId = (SSCS_SH_SECRET_ID_T)Marshal.PtrToStructure(temp, typeof(SSCS_SH_SECRET_ID_T));
String st = secretId.name;
sc.Add(st);
}
}
}
Marshal.FreeHGlobal(idList.secretIDList);
CloseSecretStore(context);
return sc;
}
internal static Secret GetSecret(
string sKeyChainID,
uint iFlags,
string sSharedSecretID,
int iSecretType,
string sEPPassword)
{
IntPtr pHsc = OpenSecretStore("SecretStore");
if (pHsc == IntPtr.Zero)
{
throw new MiCasaException(MiCasaException.NSSCS_E_SYSTEM_FAILURE);
}
if (sKeyChainID == null || sSharedSecretID == null
|| sKeyChainID.Length == 0 || sSharedSecretID.Length == 0)
throw new MiCasaException(MiCasaException.NSSCS_E_INVALID_PARAM);
// setup structures
SSCS_KEYCHAIN_ID_T keyChainID = new SSCS_KEYCHAIN_ID_T();
keyChainID.keychainID = sKeyChainID;
SSCS_SH_SECRET_ID_T sharedSecretID = new SSCS_SH_SECRET_ID_T();
sharedSecretID.name = sSharedSecretID;
sharedSecretID.type = iSecretType;
SSCS_PASSWORD_T epPassword = new SSCS_PASSWORD_T();
SSCS_READEXT_T readData = new SSCS_READEXT_T();
SSCS_EXT_T ext = new SSCS_EXT_T();
// get SecretHandle
IntPtr pSecretHandle = miCASA_CreateSHSHandle();
// setup keychainid
keyChainID.len = sKeyChainID.Length + 1;
// setup sharedSecretID
sharedSecretID.len = sSharedSecretID.Length + 1;
sharedSecretID.type = iSecretType; // TODO: type APP(1), CRED(2), or Binary(4)
epPassword.pwordType = 1; // TODO: ep or master password based on flags
if (sEPPassword != null)
{
epPassword.pword = sEPPassword;
epPassword.pwordLen = (uint)sEPPassword.Length;
}
else
epPassword.pwordLen = 0;
int rcode = miCASAReadSecret(
pHsc,
keyChainID,
iFlags,
pSecretHandle,
sharedSecretID,
epPassword,
readData,
ext);
// create new secret
Secret temp = new Secret(sKeyChainID, iFlags, pSecretHandle, sSharedSecretID, sharedSecretID.type);
// if read was sucessfull, read key value pairs
if (rcode == 0)
{
LoadKeyValuePairs(temp);
}
// close store
CloseSecretStore(pHsc);
return temp;
}
internal static void LoadKeyValuePairs(Secret secret)
{
int rcode = 0;
int iStart = 1;
IntPtr theKey = Marshal.AllocHGlobal(60416);
IntPtr theValue = Marshal.AllocHGlobal(60416);
String sKey;
String sValue;
while (true)
{
uint iKeyLen = 60416;
uint iValueLen = 60416;
sKey = "";
sValue = "";
rcode = miCASA_GetNextSHSEntry(
iStart,
secret.m_secretHandle,
ref iKeyLen,
theKey, //sKey,
ref iValueLen,
theValue // sValue
);
if (rcode != 0)
break;
else
{
if (iKeyLen > 1)
{
//sKey = Marshal.PtrToStringAnsi(theKey, (int)iKeyLen - 1);
// convert from UTF8
byte[] baKey = new byte[iKeyLen - 1];
Marshal.Copy(theKey, baKey, 0, (int)iKeyLen - 1);
sKey = System.Text.Encoding.UTF8.GetString(baKey, 0, baKey.Length);
}
if (iValueLen > 1)
{
//sValue = Marshal.PtrToStringAnsi(theValue, (int)iValueLen -1);
// convert from UTF8
byte[] baValue = new byte[iValueLen - 1];
Marshal.Copy(theValue, baValue, 0, (int)iValueLen - 1);
sValue = System.Text.Encoding.UTF8.GetString(baValue, 0, baValue.Length);
}
if (sKey != null && sValue != null)
secret.SetKeyValue(sKey, sValue, false);
iStart = 0;
}
}
Marshal.FreeHGlobal(theKey);
Marshal.FreeHGlobal(theValue);
}
internal static void WriteKey(
uint iFlags,
string sKeyChainID,
string sSharedSecretID,
string sKey,
string sValue,
string sEPPassword)
{
IntPtr context;
if (sKeyChainID == null
|| sKeyChainID.Length == 0)
{
throw new MiCasaException(MiCasaException.NSSCS_E_INVALID_PARAM);
}
context = OpenSecretStore("SecretStore");
if (context == IntPtr.Zero)
{
throw new MiCasaException(MiCasaException.NSSCS_E_SYSTEM_FAILURE);
}
// setup structures
SSCS_KEYCHAIN_ID_T keyChainID = new SSCS_KEYCHAIN_ID_T();
keyChainID.keychainID = sKeyChainID;
keyChainID.len = sKeyChainID.Length + 1;
SSCS_SECRET_ID_T sharedSecretID = new SSCS_SECRET_ID_T();
sharedSecretID.id = sSharedSecretID;
sharedSecretID.len = sSharedSecretID.Length + 1;
SSCS_PASSWORD_T epPassword = new SSCS_PASSWORD_T();
SSCS_EXT_T ext = new SSCS_EXT_T();
StringCollection sc = new StringCollection(); //null;
int rcode = miCASAWriteKey(
context,
iFlags,
keyChainID,
sharedSecretID,
sKey,
(uint) (sKey.Length+1),
sValue,
(uint) (sValue.Length+1),
epPassword,
ext);
CloseSecretStore(context);
if (rcode != 0)
{
throw new MiCasaException(rcode);
}
}
internal static void RemoveKey(
string sKeyChainID,
uint iFlags,
string sSharedSecretID,
string sKey,
string sEPPassword)
{
IntPtr context;
if (sKeyChainID == null
|| sKeyChainID.Length == 0)
{
throw new MiCasaException(MiCasaException.NSSCS_E_INVALID_PARAM);
}
context = OpenSecretStore("SecretStore");
if (context == IntPtr.Zero)
{
throw new MiCasaException(MiCasaException.NSSCS_E_SYSTEM_FAILURE);
}
// setup structures
SSCS_KEYCHAIN_ID_T keyChainID = new SSCS_KEYCHAIN_ID_T();
keyChainID.keychainID = sKeyChainID;
keyChainID.len = sKeyChainID.Length + 1;
SSCS_SECRET_ID_T sharedSecretID = new SSCS_SECRET_ID_T();
sharedSecretID.id = sSharedSecretID;
sharedSecretID.len = sSharedSecretID.Length + 1;
SSCS_PASSWORD_T epPassword = new SSCS_PASSWORD_T();
SSCS_EXT_T ext = new SSCS_EXT_T();
int rcode = miCASARemoveKey(
context,
iFlags,
keyChainID,
sharedSecretID,
sKey,
(uint)(sKey.Length + 1),
epPassword,
ext);
CloseSecretStore(context);
if (rcode != 0)
{
throw new MiCasaException(rcode);
}
}
} }
} }

View File

@ -38,6 +38,7 @@
<Compile Include="MiCasaException.cs" /> <Compile Include="MiCasaException.cs" />
<Compile Include="NativeCalls.cs" /> <Compile Include="NativeCalls.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Secret.cs" />
<Compile Include="WinLuid.cs" /> <Compile Include="WinLuid.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -0,0 +1,133 @@
/***********************************************************************
*
* Copyright (C) 2005-2006 Novell, Inc. All Rights Reserved.
*
* 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 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, Novell, Inc.
*
* 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.Collections.Specialized;
namespace Novell.Casa
{
/// <summary>
/// Summary description for Secret.
/// </summary>
public class Secret : MarshalByRefObject
{
private String m_keyChainID;
private uint m_ssFlags;
internal IntPtr m_secretHandle;
private String m_secretID;
internal int m_type = 0;
// holds name value pairs for this secret
private System.Collections.Specialized.NameValueCollection m_nvc;
public static int SS_APP = 1;
public static int SS_CREDSET = 2;
public static int SS_BINARY = 4;
// constructor
internal Secret(
String sKeyChainID,
uint iSSFlags,
IntPtr ptrHandle,
string sSecretID,
int iSecretType)
{
m_keyChainID = sKeyChainID;
m_ssFlags = iSSFlags;
m_secretHandle = ptrHandle;
m_secretID = sSecretID;
m_type = iSecretType;
if (sSecretID.StartsWith("SS_CredSet"))
m_type = Secret.SS_CREDSET;
else if (sSecretID.StartsWith("SS_App"))
m_type = Secret.SS_APP;
else if (sSecretID.StartsWith("SS_Binary"))
m_type = Secret.SS_BINARY;
// create collection
m_nvc = new System.Collections.Specialized.NameValueCollection();
}
// TO clean up SecretHandle
public string GetID()
{
return m_secretID;
}
public void SetKeyValue(String sKey, String sKeyValue)
{
SetKeyValue(sKey, sKeyValue, true);
}
internal void SetKeyValue(String sKey, String sKeyValue, bool bCommit)
{
if (m_type == Secret.SS_APP)
m_nvc.Add(sKey, sKeyValue);
else
{
if (bCommit)
{
NativeCalls.WriteKey(0, m_keyChainID, this.GetID(),
sKey, sKeyValue, null);
}
m_nvc.Set(sKey, sKeyValue);
}
}
public string GetKeyValue(String sKey)
{
return m_nvc.Get(sKey);
}
private int GetSecretType()
{
return this.m_type;
}
public NameValueCollection GetKeyValueCollection()
{
return m_nvc;
}
public void MergeKeyValueCollection(NameValueCollection nvc)
{
m_nvc = nvc;
}
public void RemoveKey(String sKey)
{
//call the ndk to remove that one too.
NativeCalls.RemoveKey(this.m_keyChainID, 0, this.GetID(), sKey, null);
// remove from our collection
m_nvc.Remove(sKey);
}
}
}