/*********************************************************************** * * 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.Xml; using System.IO; using Novell.CASA; using Novell.CASA.DataEngines.Common; using System.Collections.Specialized; using System.Runtime.InteropServices; using Novell.CASA.DataEngines.KWallet; namespace Novell.CASA.DataEngines { /* * This class is implementation of Data engine for KWallet. */ class KWalletEngine : DataEngine { string[] EntryTypes = {"Binary","Passwords","Unknown", "Maps"}; enum KWalletResult : int { KWALLET_RESULT_OK, KWALLET_RESULT_CANNOT_OPEN_WALLET, KWALLET_RESULT_CANNOT_OPEN_FOLDER, KWALLET_RESULT_CANNOT_WRITE_ENTRY, KWALLET_RESULT_MALFORMED_XML, KWALLET_RESULT_CANNOT_CREATE_FOLDER, KWALLET_RESULT_CANNOT_CREATE_WALLET, KWALLET_RESULT_CANNOT_REMOVE_ENTRY, KWALLET_RESULT_UNKNOWN_ERROR }; public KWalletEngine() { // TBD: Read Policy information and have a list of wallet names; } public XmlNode Aggregate() { XmlDocument doc = new XmlDocument(); Hashtable lookup = new Hashtable(); XmlElement key1; XmlAttribute Atr; XmlElement value1; XmlAttribute idAttr; String secid, val; XmlElement currentWallet; XmlElement Folder; XmlElement Type; XmlElement Secret; String walletName, foldername, entryType, secretval; //Adding Kwallet Top Node XmlElement elem = doc.CreateElement(ConstStrings.CCF_KW); doc.AppendChild(elem); EnumSecretList enumList = new EnumSecretList(); //kwallet.Try(enumList); kwallet.AggregateKW(enumList); EnumSecretList tempEnumSecretList1 = enumList; //This can be Null only when nothing is aggregated. if (((String)Marshal.PtrToStringAnsi(tempEnumSecretList1.walletName)) == null ) { //TBD: Log that there are no secrets to aggregate } else // Something to Aggregate { while (tempEnumSecretList1 != null) { walletName = (String)Marshal.PtrToStringAnsi(tempEnumSecretList1.walletName); // Console.WriteLine("\n\nWallet name is***# : "+walletName); foldername = (String)Marshal.PtrToStringAnsi(tempEnumSecretList1.folderName); //Console.WriteLine("\tFolder***# : "+foldername); int entrytype = tempEnumSecretList1.entryType; //Console.WriteLine("\t\tEntryType ***#: "+entrytype); entryType = EntryTypes[entrytype]; //Console.WriteLine("\t\tEntryType in string ***#: "+entryType); secretval = (String)Marshal.PtrToStringAnsi(tempEnumSecretList1.secretVal); //Console.WriteLine("\t\tSecret***# : "+secretval); //Adding Wallet if (lookup.ContainsKey(walletName)) { //Console.WriteLine("Wallet Node found"); currentWallet = (XmlElement)lookup[walletName]; } else { currentWallet = doc.CreateElement(ConstStrings.CCF_WALLET); idAttr = doc.CreateAttribute(ConstStrings.CCF_ID); idAttr.Value = walletName; currentWallet.SetAttributeNode(idAttr); elem.AppendChild(currentWallet); lookup.Add(walletName,currentWallet); } //Adding Folder String xpath = "descendant::Folder[@Name='"+foldername+"']"; XmlNodeList folList = currentWallet.SelectNodes(xpath); if (folList.Count == 0) { Folder = doc.CreateElement(ConstStrings.CCF_FOLDER); XmlAttribute name_attr = doc.CreateAttribute(ConstStrings.CCF_NAME); name_attr.Value = foldername; Folder.SetAttributeNode(name_attr); currentWallet.AppendChild(Folder); } //Adding Type xpath = "descendant::Folder"; XmlNodeList folderlist = currentWallet.SelectNodes(xpath); foreach(XmlNode folder in folderlist) { XmlAttributeCollection atcol = folder.Attributes; XmlAttribute attr = atcol[ConstStrings.CCF_NAME]; if (attr.InnerXml.Equals(foldername)) { xpath = "descendant::Type[@ID='"+entryType+"']"; XmlNodeList keylist = folder.SelectNodes(xpath); if (keylist.Count == 0) { Type = doc.CreateElement(ConstStrings.CCF_TYPE); XmlAttribute name_attr = doc.CreateAttribute(ConstStrings.CCF_ID); name_attr.Value = entryType; Type.SetAttributeNode(name_attr); folder.AppendChild(Type); } else { //Console.WriteLine("Type Already Added"); } } } //Adding the Secret xpath = "descendant::Folder"; folderlist = currentWallet.SelectNodes(xpath); foreach(XmlNode folder in folderlist) { XmlAttributeCollection atcol = folder.Attributes; XmlAttribute attr = atcol[ConstStrings.CCF_NAME]; if (attr.InnerXml.Equals(foldername)) { xpath = "descendant::Type[@ID='"+entryType+"']"; XmlNodeList keylist = folder.SelectNodes(xpath); if (keylist.Count == 0) { //Console.WriteLine("Construction of CCF Failed"); } else { XmlNode TargetType = keylist[0]; //Type Node string[] split = null; int index = secretval.IndexOf('='); secid = secretval.Substring(0,index); Secret = doc.CreateElement(ConstStrings.CCF_SECRET); XmlAttribute idattr = doc.CreateAttribute(ConstStrings.CCF_ID); idattr.Value = secid; Secret.SetAttributeNode(idattr); /*XmlAttribute typeAttr = doc.CreateAttribute(ConstStrings.CCF_TYPE); typeAttr.Value = entryType; Secret.SetAttributeNode(typeAttr); */ if (entryType.Equals("Maps")) { string delim = ";"; char[] delimiter = delim.ToCharArray(); string realval = secretval.Substring(index+1); for(int x = 1; x < 10 ; x++) { split = realval.Split(delimiter, x); } foreach(string s in split) { int ix; string key; string value; //Console.WriteLine("The val is :" + s); if (s.Equals("")) { //Console.WriteLine("No Secret Content for a Secret ID"); key = " "; value = " "; } else { ix = s.IndexOf(':'); key = s.Substring(0,ix); value = s.Substring(ix+1); } key1 = doc.CreateElement(ConstStrings.CCF_KEY); Atr = doc.CreateAttribute(ConstStrings.CCF_ID); Atr.Value = key; key1.SetAttributeNode(Atr); //Value value1 = doc.CreateElement(ConstStrings.CCF_VALUE); value1.InnerText = value; key1.AppendChild(value1); Secret.AppendChild(key1); TargetType.AppendChild(Secret); } }//entrytype=Maps else if (entryType.Equals("Passwords")) { //Console.WriteLine("Passwords"); val = secretval.Substring(index+1); //Key key1 = doc.CreateElement(ConstStrings.CCF_KEY); Atr = doc.CreateAttribute(ConstStrings.CCF_ID); Atr.Value = "Credential"; key1.SetAttributeNode(Atr); //Value value1 = doc.CreateElement(ConstStrings.CCF_VALUE); value1.InnerText = val; key1.AppendChild(value1); Secret.AppendChild(key1); TargetType.AppendChild(Secret); }//entryType=Password } } } if (tempEnumSecretList1.next == IntPtr.Zero) { // Console.WriteLine("Reached End ##"); break; } tempEnumSecretList1 = (EnumSecretList)Marshal.PtrToStructure(tempEnumSecretList1.next, typeof(EnumSecretList)); } } kwallet.FreeResources(); #if TEST XmlTextWriter writer = new XmlTextWriter("/root/kwtest.xml",null); writer.Formatting = Formatting.Indented; doc.Save(writer); writer.Close(); #endif return doc.ChildNodes[0]; } public int SetSecret(XmlNode secret) { try { string walletName = ExtractWalletName(secret); string folderName = ExtractFolderName(secret); string keyName = ExtractKeyName(secret); int secretType = ExtractSecretType(secret); if (secretType != 3) //Type not Map { string value = secret.ChildNodes[0].ChildNodes[0].InnerText; //Secret.Key.Value return(kwallet.SetSecret(walletName, folderName, secretType, keyName, value, value.Length)); } else //If type is Map { NameValueCollection nvc = new NameValueCollection(); for (int i =0; i< secret.ChildNodes.Count; i++) { XmlNode key = secret.ChildNodes[i]; XmlAttributeCollection atcol; atcol = key.Attributes; String keyMapName = atcol["ID"].InnerXml; string value = key.ChildNodes[0].InnerText; //Secret.Key.Value nvc.Add(keyMapName,value); } return(kwallet.SetSecret(walletName, folderName,keyName,nvc)); } } catch(NullReferenceException n) { //Console.WriteLine("Exception in Set Secret Cause :" + n.ToString()); return (int)KWalletResult.KWALLET_RESULT_MALFORMED_XML; } catch(Exception e) { //Console.WriteLine("Exception in Set Secret Cause :" + e.ToString()); return (int)KWalletResult.KWALLET_RESULT_UNKNOWN_ERROR; } } public int SetSecret(XmlNode secret, int opnType) { return SetSecret(secret); } public int GetSecret(XmlNode secret) { return ConstStrings.CASA_SUCCESS; } public int Remove(XmlNode secret) { try { string walletName = ExtractWalletName(secret); string folderName = ExtractFolderName(secret); string keyName = ExtractKeyName(secret); int res = kwallet.DeleteSecret(walletName, folderName, keyName); if (res == 0) { XmlNode root = secret.ParentNode; root.RemoveChild(secret); } return res; } catch(NullReferenceException n) { //Console.WriteLine("Exception in Set Secret Cause :" + n.ToString()); return (int)KWalletResult.KWALLET_RESULT_MALFORMED_XML; } catch(Exception e) { //Console.WriteLine("Exception in Set Secret Cause :" + e.ToString()); return (int)KWalletResult.KWALLET_RESULT_UNKNOWN_ERROR; } } string ExtractWalletName(XmlNode secret) { XmlAttributeCollection atcol; XmlNode parentNode = secret.ParentNode.ParentNode.ParentNode; atcol = parentNode.Attributes; String walletname = atcol["ID"].InnerXml; return walletname; } string ExtractFolderName(XmlNode secret) { XmlAttributeCollection atcol; XmlNode parentNode = secret.ParentNode.ParentNode; //Folder.Type.Secret atcol = parentNode.Attributes; String foldername = atcol["Name"].InnerXml; return foldername; } string ExtractKeyName(XmlNode secret) { XmlAttributeCollection atcol; atcol = secret.Attributes; String keyname = atcol["ID"].InnerXml; return keyname; } int ExtractSecretType(XmlNode secret) { XmlAttributeCollection atcol; XmlNode parentNode = secret.ParentNode; //Type.Secret atcol = parentNode.Attributes; String entryType = atcol["ID"].InnerXml; if (entryType.CompareTo("Passwords")== 0) { return 1; } if (entryType.CompareTo("Binary") == 0) { return 2; } if (entryType.CompareTo("Maps") == 0) { return 3; } return 0; } public static Boolean IsStoreAvailable() { return true; } #if TEST public static void Main() { KWalletEngine kw = new KWalletEngine(); Console.WriteLine(); Console.WriteLine("********** Menu ***********"); Console.WriteLine("* 1. Add secret *"); Console.WriteLine("* 2. Modify secret *"); Console.WriteLine("* 3. Set secret *"); Console.WriteLine("* 4. Remove secret *"); Console.WriteLine("* 5. Refresh *"); Console.WriteLine("* 6. Quit *"); Console.WriteLine("***************************"); Console.WriteLine("For all options the input is the file /root/kwtest.xml"); Console.WriteLine("Select option and Press enter"); String line = Console.ReadLine(); int res = 0; if (line.Length > 0) { char[] c = line.Substring(0, 1).ToCharArray(); if (c.Length > 0) { if (c[0].Equals('6')) return; if (c[0].Equals('5')) kw.Aggregate (); else { XmlDocument xmlDoc = new XmlDocument(); XmlTextReader tr = new XmlTextReader("/root/kwtest.xml"); tr.Read(); xmlDoc.Load(tr); XmlNode root = xmlDoc.FirstChild; if (root == null) { Console.WriteLine("Root is null"); } XmlNode secret = root.ChildNodes[0].ChildNodes[0].ChildNodes[0].ChildNodes[0]; if (c[0].Equals('4')) res =kw.Remove(secret); else if (c[0].Equals('1')) res = kw.SetSecret(secret,ConstStrings.OPERATION_ADD_SECRET); else if (c[0].Equals('2')) res = kw.SetSecret(secret,ConstStrings.OPERATION_MODIFY_SECRET); else if (c[0].Equals('3')) res = kw.SetSecret(secret); } } } Console.WriteLine("Result of Operation = " + res); } #endif } }