CASA/c_adlib/KWalletEngine.cs
smanojna 7ea0c756ca
2006-02-14 12:46:09 +00:00

543 lines
22 KiB
C#

/***********************************************************************
*
* 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()
{
try
{
System.Runtime.InteropServices.Marshal.PrelinkAll(typeof(kwallet));
return true;
}
catch(DllNotFoundException d)
{
//Console.WriteLine("Store Not Available Exception =" + d.ToString());
return false;
}
catch(Exception e)
{
//Console.WriteLine("Store Not Available Exception =" + e.ToString());
return false;
}
}
#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
}
}