using System; using System.Text; using System.Runtime.InteropServices; namespace Novell.SecretStore.NSSSWrapper { /// <summary> /// Summary description for Class1. /// </summary> public class NativeCalls { //private uint NSSS_GET_CONTEXT_F = 0x00000100; private string m_host = null; private string m_userId = null; private string m_password = null; private string m_certFile = null; private SSS_CONTEXT_T m_context = null; private SS_OBJECT_DN_T m_objectDN = null; public NativeCalls(string host, string userId, string password, string certFile) { // // TODO: Add constructor logic here // m_host = host; m_userId = userId; m_password = password; m_certFile = certFile; } //* Get service info extended data [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public class SSS_GSINFOEXT_T { public uint statFlags; public uint secretCount; public uint lockCount; public uint enumBufLen; public uint hidSecCount; public uint clientVersion; public uint serverVersion; public uint serverCryptoStrength; public uint clientCryptoStrength; public uint unlockTStamp; public uint admnDNLen; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 516)] public string admnDN; //[NSSS_MAX_DN_LEN]; public uint hintLen; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string hint; //[NSSS_MAX_MP_PWORD_HINT_LEN]]; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public class SS_SERVER_INFO_T { //char treeName[NSSS_MAX_TREE_NAME_LEN]; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] // in bytes? public string treeName; //char ssServerDN[NSSS_MAX_DN_LEN]; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 516)] public string ssServerDN; //char ssServerIPAddr[NSSS_MAX_IP_ADDR_LEN]; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] public string ssServerIPAddr; //char sssConfigDN[NSSS_MAX_DN_LEN]; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 516)] public string sssConfigDN; } ; [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public class SS_OBJECT_DN_T { public int len; //char id[NSSS_MAX_DN_LEN]; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 516)] public string id; }; [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public class SSS_CONTEXT_T { public uint flags; //* IN- context type indicator and public uint dsCtx; //* IN/OUT- ldap/ncp context public uint version; //* IN- context version indicator public SS_SERVER_INFO_T ssServerInfo; //* IN/OUT- preferred SecretStore server info public SS_OBJECT_DN_T callerDN; //* IN/OUT- DN of the caller. OUT-For NCP. public IntPtr handles; public IntPtr bindInfo; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public class SSCS_EXT_T { public int extID; // defined to identify the extension public int version; // defined as the version of the specified extension //void *ext; // points to the actual extension public IntPtr ext; } ; [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public class SS_LDAPBIND_INFO_T { public uint portNum; //* default: 636 //char lHostName[ NSSS_MAX_DN_LEN ]; //* Ex: "nsd10.novell.com" or ip addr [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 516)] public string lHostHame; //char trustedRootCert[ NSSS_MAX_DN_LEN ]; //* default: "c:\TrustedRootCertificate.der" [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 516)] public string trustedRootCert; //char loginPword[ NSSS_MAX_LDAP_PWORD_LEN ]; //* LDAP login password (utf8) [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string loginPword; } ; [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public class SS_SECRET_T { public int len; public IntPtr data; }; //* password structure [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public class SS_PWORD_T { public uint pwordLen; //* enhanced protection len & pword to set //char pword[NSSS_MAX_EP_PWORD_LEN]; //* should be passed in # of chars [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string pword; }; [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public class SSS_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 }; //* Secret ID type [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public class SS_SECRET_ID_T { public int len; //* max id len in bytes //char id[NSSS_MAX_SECRET_ID_LEN]; //* should be passed in # of chars [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 512)] public string id; }; [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public class SS_SH_SECRET_ID_T { public int type; // The shared secret type i.e. SS_App or SS_CredSet //char pName[NSSS_MAX_SECRET_ID_LEN]; // The shared secret name. This is the same as the identifier [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 512)] public string id; public int len; // except that it excludes the header and is not escaped. } ; #if DEBUG private const string NDK_LIBRARY = "nsss"; //private const string NDK_LIBRARY = "/opt/novell/sss/libnsss.so"; #else private const string NDK_LIBRARY = "nsss"; #endif [DllImport(NDK_LIBRARY, CharSet=CharSet.Ansi)] public static extern int NSSSGetServiceInformation ( [In, Out] SSS_CONTEXT_T context, [In] SS_OBJECT_DN_T targetObjDN, [In] uint ssFlags, [In, Out] SSS_GSINFOEXT_T gsData, [In, Out] SSCS_EXT_T ext ); [DllImport(NDK_LIBRARY, CharSet=CharSet.Ansi)] public static extern int NSSSEnumerateSecretIDs ( [In, Out] SSS_CONTEXT_T context, [In] SS_OBJECT_DN_T targetObjDN, [In] uint ssFlags, [In, Out] IntPtr srchStr, [In, Out] ref uint count, [In, Out] SS_SECRET_T secretIDList, [In, Out] SSCS_EXT_T ext ); [DllImport(NDK_LIBRARY, CharSet=CharSet.Ansi)] public static extern int NSSSReadSecret ( [In, Out] SSS_CONTEXT_T context, [In] SS_OBJECT_DN_T targetObjDN, [In] uint ssFlags, [In] SS_PWORD_T epPassword, [In, Out] SSS_READEXT_T readData, [In] SS_SECRET_ID_T secretID, [In, Out] SS_SECRET_T secretValue, [In, Out] SSCS_EXT_T ext ); //************************************************************** //* Support Functions for processing (populating or extracting) //* data components from a Shared Secret //************************************************************** [DllImport(NDK_LIBRARY)] public static extern IntPtr NSSSCreateSHSHandle(); [DllImport(NDK_LIBRARY)] public static extern int NSSSDestroySHSHandle( [In] IntPtr handle); // in [DllImport(NDK_LIBRARY, CharSet=CharSet.Ansi) ] public static extern int NSSSGetNextSHSEntry ( [In] int restart, //* in (set to 1 to begin from head of list) [In] IntPtr secretHandle, //* in [In, Out] ref uint keyLen, //* out //[MarshalAs(UnmanagedType.LPTStr)] // StringBuilder key, //* out uchar [In, Out] IntPtr pKey, [In, Out] ref uint valLen, //* out //[MarshalAs(UnmanagedType.LPTStr)] // StringBuilder val, //* out uchar [In, Out] IntPtr pVal, [In] uint ssCtxFlags ); [DllImport(NDK_LIBRARY, CharSet=CharSet.Ansi)] public static extern int NSSSAddSHSEntry ( [In] IntPtr secretHandle, //* in] //[MarshalAs(UnmanagedType.B)] string key, //* in /wchar //[MarshalAs(UnmanagedType.LPTStr)] string val, //* in /uchar [In] uint ssCtxFlags ); [DllImport(NDK_LIBRARY)] public static extern int NSSSRemoveSHSEntry ( [In] IntPtr secretHandle, //* in [MarshalAs(UnmanagedType.LPWStr)] string key, //* out /uchar [MarshalAs(UnmanagedType.LPTStr)] string val, //* out /uchar [In] uint ssCtxFlags ); //************************************************************** //* These function calls will utilize the Support Functions for //* populating or extracting data from a Shared Secret. //************************************************************** [DllImport(NDK_LIBRARY)] public static extern int NSSSWriteSharedSecret ( [In] IntPtr secretHandle, //* in [In] SS_SH_SECRET_ID_T pSharedSecret, [In, Out] SSS_CONTEXT_T context, [In] SS_OBJECT_DN_T targetObjDN, [In] uint ssFlags, [In] SS_PWORD_T epPassword, [In, Out] SSCS_EXT_T ext ); [DllImport(NDK_LIBRARY)] public static extern int NSSSReadSharedSecret ( [In] IntPtr secretHandle, //* in [In] SS_SH_SECRET_ID_T pSharedSecret, [In, Out] SSS_CONTEXT_T context, [In] SS_OBJECT_DN_T targetObjDN, [In] uint ssFlags, [In] SS_PWORD_T epPassword, [In, Out] SSS_READEXT_T readData, [In, Out] SSCS_EXT_T ext ); [DllImport(NDK_LIBRARY)] public static extern int NSSSRemoveSharedSecret ( [In] SS_SH_SECRET_ID_T pSharedSecret, [In, Out] SSS_CONTEXT_T context, [In] SS_OBJECT_DN_T targetObjDN, [In] uint ssFlags, [In, Out] SSCS_EXT_T ext ); // code starts here public void setContextInfo(string sHost, string sUsername, string sPassword, string sCertFile) { m_host = sHost; m_userId = sUsername; m_password = sPassword; m_certFile = sCertFile; } public void getStoreInfo() { // set up locals SSS_CONTEXT_T context = new SSS_CONTEXT_T(); SS_OBJECT_DN_T objectDN = new SS_OBJECT_DN_T(); SS_LDAPBIND_INFO_T ldapBindInfo = new SS_LDAPBIND_INFO_T(); SSS_GSINFOEXT_T gsData = new SSS_GSINFOEXT_T(); SSCS_EXT_T ext = new SSCS_EXT_T(); // init params objectDN.id = m_userId; objectDN.len = objectDN.id.Length + 1; //ldapBindInfo.lHostHame = "151.155.152.209"; //ldapBindInfo.lHostHame = "jim1.provo.novell.com"; ldapBindInfo.lHostHame = m_host; //ldapBindInfo.loginPword = "test"; ldapBindInfo.loginPword = m_password; ldapBindInfo.portNum = 636; ldapBindInfo.trustedRootCert = m_certFile; context.bindInfo = Marshal.AllocHGlobal(Marshal.SizeOf(ldapBindInfo)); Marshal.StructureToPtr(ldapBindInfo, context.bindInfo, false); //context.callerDN = objectDN; context.callerDN = objectDN; context.flags = 2050; context.handles = IntPtr.Zero; context.version = 0; //context.bindInfo = ldapBindInfo; //context.bindInfo = new IntPtr(4); context.ssServerInfo = new SS_SERVER_INFO_T(); Console.WriteLine("ServerInfoSize: "+Marshal.SizeOf(context.ssServerInfo)); int rcode = NSSSGetServiceInformation(context, objectDN, 0x00000100, //0x00000110, // 0x00000010, ALL STRINGS UNICODE.... gsData, ext); if (rcode != 0) { Console.Write("NSSSGetServiceInformation return error: " + rcode); throw new Exception("Login Failed"); } else { m_context = context; m_objectDN = objectDN; } //enumerateSecretIDs(context, objectDN, 0x00000110); } public string[] enumerateSecretIDs() { return enumerateSecretIDs(m_context, m_objectDN, 0x00000000); } private string[] enumerateSecretIDs(SSS_CONTEXT_T context, SS_OBJECT_DN_T targetObjDN, uint ssFlags) { int rcode = 0; uint count = 0; SS_SECRET_T secretIDList = new SS_SECRET_T(); secretIDList.data = Marshal.AllocHGlobal(16384+1); secretIDList.len = 16384+1; SSCS_EXT_T ext = new SSCS_EXT_T(); rcode = NSSSEnumerateSecretIDs(context, targetObjDN, ssFlags, IntPtr.Zero, // [In, Out] IntPtr srchStr, ref count, secretIDList, ext); if (rcode != 0) { Console.Write("NSSSGetServiceInformation return error: " + rcode); return null; } string ids = Marshal.PtrToStringAnsi(secretIDList.data); if (ids.EndsWith("*")) ids = ids.Substring(0, ids.Length-1); // parse the buffer string [] split = null; string delimStr = "*"; char [] delimiter = delimStr.ToCharArray(); for (int i = 1; i <= count; i++) { split = ids.Split(delimiter, i); } /* if (false) { // dump em out. for (int i=0; i<split.Length; i++) { Console.WriteLine("-------------------"); string sTemp = split[i].ToString().TrimEnd(delimiter); Console.WriteLine("ID: "+sTemp); if (sTemp.StartsWith("SS_CredSet")) getSharedSecret(context, targetObjDN, ssFlags, sTemp); else getSecret(context, targetObjDN, ssFlags, sTemp); Console.WriteLine(); } } */ return split; } public RemoteSecret getSecret(uint ssFlags, string sSecretID) { return getSecret(m_context, m_objectDN, ssFlags, sSecretID); } public RemoteSecret getSecret(SSS_CONTEXT_T context, SS_OBJECT_DN_T targetObjDN, uint ssFlags, string sSecretID) { if (sSecretID.StartsWith("SS_CredSet") || sSecretID.StartsWith("SS_App")) { return getSharedSecret(context, targetObjDN, ssFlags, sSecretID); } int rcode = 0; SS_PWORD_T epPassword = new SS_PWORD_T(); SSS_READEXT_T readData = new SSS_READEXT_T(); SS_SECRET_ID_T secretId = new SS_SECRET_ID_T(); secretId.id = sSecretID; secretId.len = sSecretID.Length+1; SS_SECRET_T secretValue = new SS_SECRET_T(); secretValue.data = Marshal.AllocHGlobal(1024*64); secretValue.len = (1024*64); SSCS_EXT_T ext = new SSCS_EXT_T(); rcode = NSSSReadSecret(context, targetObjDN, ssFlags, epPassword, readData, secretId, secretValue, ext); if (rcode == 0) { RemoteSecret rs = new RemoteSecret(sSecretID, readData.crtStamp, readData.lmtStamp, readData.latStamp); String sValue = Marshal.PtrToStringAnsi(secretValue.data, secretValue.len); //String sValue = Marshal.PtrToStringAnsi(secretValue.data, secretValue.len); rs.setValue(sValue); Marshal.FreeHGlobal(secretValue.data); return rs; } else Console.WriteLine("value: not found "+ rcode); // release unmanaged memory. Marshal.FreeHGlobal(secretValue.data); return null; } public static RemoteSecret getSharedSecret(SSS_CONTEXT_T context, SS_OBJECT_DN_T targetObjDN, uint ssFlags, string sSecretID) { int rcode = 0; SS_PWORD_T epPassword = new SS_PWORD_T(); SSS_READEXT_T readData = new SSS_READEXT_T(); SS_SH_SECRET_ID_T pSharedSecretID = new SS_SH_SECRET_ID_T(); if (sSecretID.StartsWith("SS_CredSet")) { pSharedSecretID.id = sSecretID.Substring(11); pSharedSecretID.len = pSharedSecretID.id.Length; pSharedSecretID.type = 2; } else //SS_App { pSharedSecretID.id = sSecretID.Substring(7); pSharedSecretID.len = pSharedSecretID.id.Length; pSharedSecretID.type = 1; } SSCS_EXT_T ext = new SSCS_EXT_T(); // get secretHandle IntPtr secretHandle = NSSSCreateSHSHandle(); rcode = NSSSReadSharedSecret(secretHandle, pSharedSecretID, context, targetObjDN, ssFlags, epPassword, readData, ext); if (rcode == 0) { RemoteSecret rs = new RemoteSecret(pSharedSecretID.id, readData.crtStamp, readData.lmtStamp, readData.latStamp); // enumerate key/value pairs loadKeyValuePairs(context, secretHandle, rs); return rs; } else return null; } internal static void loadKeyValuePairs(SSS_CONTEXT_T context, IntPtr secretHandle, RemoteSecret rs) { int rcode=0; int iStart = 1; uint iKeyLen = 60416; //StringBuilder sKey = new StringBuilder((int)iKeyLen); IntPtr pKey; // = new IntPtr(4); pKey = Marshal.AllocHGlobal(60416); uint iValueLen = 60416; //StringBuilder sValue = new StringBuilder((int)iValueLen); IntPtr pValue; // = new IntPtr(4); pValue = Marshal.AllocHGlobal(60416); while (true) { rcode = NSSSGetNextSHSEntry( iStart, secretHandle, ref iKeyLen, //sKey, pKey, ref iValueLen, //sValue, pValue, context.flags ); if (rcode != 0) break; else { /* UTF8Encoding encoder = new UTF8Encoding(); System.Text.Decoder decoder = encoder.GetDecoder(); byte[] baKey= new byte[(int)iKeyLen]; Marshal.Copy(pKey, baKey, 0, (int)iKeyLen-1); char[] caKey = new char[256]; rcode = decoder.GetChars(baKey, 0, baKey.Length, caKey, 0); string sKey = new String(caKey); Console.WriteLine("baKeyBytes"); for (int j=0; j<baKey.Length; j++) Console.Write(baKey[j] + " "); Console.WriteLine(); byte[] baValue = new byte[(int)iValueLen]; Marshal.Copy(pValue, baValue, 0, (int)iValueLen-1); char[] caValue = new char[256]; rcode = decoder.GetChars(baValue, 0, baValue.Length, caValue, 0); string sValue = new string(caValue); Console.WriteLine("Adding key-value " + sKey.Trim() + "=" +sValue.Trim()); rs.setKeyValuePair(sKey.Trim(), sValue.Trim()); */ string sKey = Marshal.PtrToStringAnsi(pKey, (int)iKeyLen-1); string sValue = Marshal.PtrToStringAnsi(pValue, (int)iValueLen-1); //Marshal.PtrToStringAnsi( //Console.WriteLine(sKey + "=" + sValue); rs.setKeyValuePair(sKey, sValue); iKeyLen = 60416; iValueLen = 60416; iStart = 0; } } Marshal.FreeHGlobal(pKey); Marshal.FreeHGlobal(pValue); } public void setSecret(RemoteSecret secret) { setSecret(m_context, m_objectDN, 0, secret); } internal void setSecret(SSS_CONTEXT_T context, SS_OBJECT_DN_T targetObjDN, uint ssFlags, RemoteSecret secret) { int rcode = 0; // create a secretHandle // get secretHandle IntPtr secretHandle = NSSSCreateSHSHandle(); // write out the keyValue Pairs System.Collections.Specialized.NameValueCollection nvc = secret.getKeyValueCollection(); //int NSSS_LDAP_CTX_F 0x00000002; //* Context is for LDAP //int NSSS_CONTEXT_INITIALIZED_F 0x00000004; for (int i=0; i<nvc.Count; i++) { string sKey = nvc.GetKey(i); string sValue = nvc.Get(i); rcode = NSSSAddSHSEntry(secretHandle, sKey, sValue, 6); } SS_PWORD_T epPassword = new SS_PWORD_T(); SS_SH_SECRET_ID_T pSharedSecretID = new SS_SH_SECRET_ID_T(); pSharedSecretID.id = secret.getID(); pSharedSecretID.len = pSharedSecretID.id.Length; pSharedSecretID.type = 2; SSCS_EXT_T ext = new SSCS_EXT_T(); // Write the SharedSecret rcode = NSSSWriteSharedSecret(secretHandle, pSharedSecretID, context, targetObjDN, ssFlags, epPassword, ext); } } }