/*********************************************************************** * * 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 System.Collections.Specialized; using Novell.CASA.DataEngines.Common; using Novell.CASA.CASAPolicy; #if LINUX using Novell.CASA.GUI; #endif namespace Novell.CASA.DataEngines { public class AD { private miCASAEngine micasaengine; #if LINUX private GKEngine gkEngine = null; private KWalletEngine kwEngine = null; private FFEngine ffEngine = null; #endif private AggregationPol aggPol; public AD() { // Always Aggregate miCASA. micasaengine = new miCASAEngine(); #if LINUX //FIXME: This should not be done always but should be based on policy as explained //for firefox below. kwEngine = new KWalletEngine(); gkEngine = new GKEngine(); //ffEngine = new FFEngine(); //Note: //The new instantiation of a wallet should not be done here since //if the policy has a specific wallet disabled, the constructor for the wallet //also should not be instantiated. //This is already being done within the Aggreagate\AggregateStore api. //Also all operations should check for an instance of a wallet and instanciate only //if not already instantiated as has been done for firefox. #endif } /******************************************************************************* Aggregates All Stores. public int Aggregate() Parameters : None StoreID : XmlNode All aggregated store's XML document. Returns : None *********************************************************************************/ public XmlDocument Aggregate() { #if LINUX gkEngine = null; kwEngine = null; //ffEngine = null; //Note: //Use the same instance of the wallet rather than re-initializing again #endif //Read the Policy Just before you aggregate // Reading Policy to see what else needs to be Aggregated. aggPol = (AggregationPol) ICASAPol.GetPolicy(CASAPolType.AGGREGATION_POL); if (aggPol != null ) { ArrayList stores = aggPol.StoreList; IEnumerator enumerator = stores.GetEnumerator(); while(enumerator.MoveNext()) { string storeID = (((Store)(enumerator.Current)).StoreName); #if LINUX if(storeID.Equals(ConstStrings.KW)) { Logger.DbgLog("A-D Lib: KWallet Set up for Aggregation"); kwEngine = new KWalletEngine(); } else if(storeID.Equals(ConstStrings.GK)) { Logger.DbgLog("A-D Lib:Gnome Keyring Set up for Aggregation"); gkEngine = new GKEngine(); } else if(storeID.Equals(ConstStrings.FF) && (ffEngine==null) ) {//Use the existing instance of firefox Logger.DbgLog("A-D Lib:FireFox Set up for Aggregation"); ffEngine = new FFEngine(); } #endif // Console.WriteLine("StoreName = " + ((Store)(enumerator.Current)).StoreName + "StoreId = " + ((Store)(enumerator.Current)).StoreId); } } XmlDocument ccf = new XmlDocument(); XmlElement elem = ccf.CreateElement("CCF"); ccf.AppendChild(elem); // TBD: Lookup Policy here and maybe send it via constructors XmlNode micasaEnum = micasaengine.Aggregate(); if (micasaEnum != null) //Atleast should come incase of no secrets { XmlNode gotit = ccf.ImportNode(micasaEnum,true); ccf.DocumentElement.AppendChild(gotit); } else { // Null comes only when it failed to talk to miCASA. #if LINUX Logger.DbgLog("A-D Lib:Failed to Connect to miCASA"); #endif } #if LINUX if (gkEngine != null) { XmlNode gkSecrets = gkEngine.Aggregate(); if( null != gkSecrets ) { XmlNode gkImportedNode = ccf.ImportNode(gkSecrets,true); ccf.DocumentElement.AppendChild(gkImportedNode); } else { Logger.DbgLog("A-D Lib:Failed to Connect to Gnome Keyring"); } } if(kwEngine != null ) { XmlNode KwEnum = kwEngine.Aggregate(); if (KwEnum != null) //Atleast should come incase of no secrets { XmlNode kwImported = ccf.ImportNode(KwEnum,true); ccf.DocumentElement.AppendChild(kwImported); } else { // Null comes only when it failed to talk to Kwallet. Logger.DbgLog("A-D Lib:Failed to Connect to KWallet"); } } if (ffEngine != null) { XmlNode ffSecrets = ffEngine.Aggregate(); if( null != ffSecrets ) { XmlNode ffImportedNode = ccf.ImportNode(ffSecrets,true); ccf.DocumentElement.AppendChild(ffImportedNode); } else { Logger.DbgLog("A-D Lib:Failed to Connect to Gnome FireFox"); } } else Logger.DbgLog("A-D Lib:Could not aggregate Gnome FireFox since FireFoxEngine not instantiated"); #endif return ccf; } /******************************************************************************** Modifying a Secret SetSecret will modify the Value(s) of a Key(s) for an existing secret SetSecret will also add new secrets public int SetSecret(XmlNode secret, int StoreID) Parameters secret : Secrets XMLNode 1. If a Key node of a secret is missing then that key will be deleted 2. For Gnome keyring, Key having Id "GkPassword" cannot be deleted as Gnome Api's do not allow it. 3. All Time nodes for a Secret need not be passed as they cannot be set. 4. Keyring attributes have a fixed datatype of Int and String. Currently we support only String types. To support int types CCF needs to be modified accordingly. 5. SetSecret overloaded method, without the opnType parameter, is not supported for GnomeKeyring opnType : Operation Type ConstStrings.OPERATION_ADD_SECRET ConstStrings.OPERATION_MODIFY_SECRET StoreID : int value Novell.CASA.DataEngines.Common.ConstStrings.CASA_STORE_KWALLET = 3; Novell.CASA.DataEngines.Common.ConstStrings.CASA_STORE_GK = 4 Returns An Error code or 0 if operation is successfull. *********************************************************************************/ public int SetSecret(XmlNode secret, int opnType, int StoreID) { if (StoreID == ConstStrings.CASA_STORE_MICASA) return micasaengine.SetSecret(secret, opnType); #if LINUX if (StoreID == ConstStrings.CASA_STORE_KWALLET) return kwEngine.SetSecret(secret, opnType); if (StoreID == ConstStrings.CASA_STORE_GK) return gkEngine.SetSecret(secret, opnType); #endif else { #if LINUX Logger.DbgLog("A-D Lib:Failed to Set Secret in to miCASA"); #endif return -1; } } /******************************************************************************** Modifying a Secret SetSecret will modify the Value(s) of a Key(s) for an existing secret SetSecret will also add new secrets public int SetSecret(XmlNode secret, int StoreID) Parameters secret : Secrets XMLNode 1. If a Key node of a secret is missing then that key will be deleted 2. For Gnome keyring, Key having Id "GkPassword" cannot be deleted as Gnome Api's do not allow it. 3. All Time nodes for a Secret need not be passed as they cannot be set. 4. Keyring attributes have a fixed datatype of Int and String. Currently we support only String types. To support int types CCF needs to be modified accordingly. StoreID : int value Novell.CASA.DataEngines.Common.ConstStrings.CASA_STORE_KWALLET = 3; Novell.CASA.DataEngines.Common.ConstStrings.CASA_STORE_GK = 4 Returns An Error code or 0 if operation is successfull. *********************************************************************************/ public int SetSecret(XmlNode secret, int StoreID) { if (StoreID == ConstStrings.CASA_STORE_MICASA) return micasaengine.SetSecret(secret); #if LINUX if (StoreID == ConstStrings.CASA_STORE_KWALLET) return kwEngine.SetSecret(secret); if (StoreID == ConstStrings.CASA_STORE_GK) return gkEngine.SetSecret(secret); #endif else { #if LINUX Logger.DbgLog("A-D Lib:Failed to Set Secret in to miCASA"); #endif return -1; } } public int GetSecret(XmlNode secret, int StoreID) { //TBD: Check for Store ID and call the right DataEngine. if (StoreID == ConstStrings.CASA_STORE_MICASA) return micasaengine.GetSecret(secret); else { #if LINUX Logger.DbgLog("A-D Lib: Failed to Get Secret in to miCASA"); #endif return -1; } } /******************************************************************************* Remove will delete a Secret. public int Remove(XmlNode secret, int StoreID) Parameters secret : Secrets XmlNode 1. This node will be deleted from its parent. StoreID : int value Novell.CASA.DataEngines.Common.ConstStrings.CASA_STORE_KWALLET = 3; Novell.CASA.DataEngines.Common.ConstStrings.CASA_STORE_GK = 4 Returns An Error code or 0 if operation is successfull. *********************************************************************************/ public int Remove(XmlNode secret, int StoreID) { if (StoreID == ConstStrings.CASA_STORE_MICASA) return micasaengine.Remove(secret); #if LINUX if (StoreID == ConstStrings.CASA_STORE_KWALLET) return kwEngine.Remove(secret); if (StoreID == ConstStrings.CASA_STORE_GK) return gkEngine.Remove(secret); #endif return -1; } /******************************************************************************* Aggregates a Store specified by the storeID. public int AggregateStore(XmlNode secret, int StoreID) Parameters secret : outDoc 1. The aggregated store's XML document. StoreID : int value Novell.CASA.DataEngines.Common.ConstStrings.CASA_STORE_KWALLET = 3; Novell.CASA.DataEngines.Common.ConstStrings.CASA_STORE_GK = 4 Novell.CASA.DataEngines.Common.ConstStrings.CASA_STORE_FF Returns An Error code or 0 if operation is successfull. *********************************************************************************/ public int AggregateStore(XmlDocument outDoc, int StoreID) { // This need not be policy aware. GUI knows what its doing. XmlNode secEnum; DataEngine engine; XmlNode toproot = outDoc.DocumentElement; if (toproot == null) { XmlElement elem = outDoc.CreateElement("CCF"); outDoc.AppendChild(elem); } if ( StoreID == ConstStrings.CASA_STORE_MICASA ) // If its miCASA { engine = micasaengine; secEnum = engine.Aggregate(); if (secEnum != null ) { XmlNode root = outDoc.DocumentElement; XmlNodeList miCASANodes = root.SelectNodes("descendant::miCASA"); // Console.WriteLine("ADLIB: Count is " + miCASANodes.Count); if (miCASANodes.Count != 0) // If there is something remove it { root.RemoveChild(miCASANodes[0]); } XmlNode gotit = outDoc.ImportNode(secEnum,true); root.AppendChild(gotit); return ConstStrings.CASA_SUCCESS; } else return ConstStrings.CASA_STORE_NOT_AVAILABLE; } #if LINUX else if( StoreID == ConstStrings.CASA_STORE_GK ) { gkEngine = new GKEngine(); secEnum = gkEngine.Aggregate(); if (secEnum != null ) { XmlNode root = outDoc.DocumentElement; XmlNodeList gkNode = root.SelectNodes("descendant::GK"); if (gkNode.Count != 0) // If there is something remove it { root.RemoveChild(gkNode[0]); } XmlNode gkImportNode = outDoc.ImportNode(secEnum,true); root.AppendChild(gkImportNode); return ConstStrings.CASA_SUCCESS; } else return ConstStrings.CASA_STORE_NOT_AVAILABLE; } else if(StoreID == ConstStrings.CASA_STORE_KWALLET) { kwEngine = new KWalletEngine(); secEnum = kwEngine.Aggregate(); if (secEnum != null ) { XmlNode root = outDoc.DocumentElement; XmlNodeList gkNode = root.SelectNodes("descendant::KWallet"); if (gkNode.Count != 0) // If there is something remove it { root.RemoveChild(gkNode[0]); } XmlNode kwImportNode = outDoc.ImportNode(secEnum,true); root.AppendChild(kwImportNode); return ConstStrings.CASA_SUCCESS; } else { //Console.WriteLine("KWallet some issue"); return ConstStrings.CASA_STORE_NOT_AVAILABLE; } } else if(StoreID == ConstStrings.CASA_STORE_FFOX) { //Use the existing instance of firefox if(ffEngine == null) ffEngine = new FFEngine(); if(ffEngine != null) { secEnum = ffEngine.Aggregate(); if (secEnum != null ) { XmlNode root = outDoc.DocumentElement; XmlNodeList ffNode = root.SelectNodes("descendant::FireFox"); if (ffNode.Count != 0) // If there is something remove it { root.RemoveChild(ffNode[0]); } XmlNode ffImportNode = outDoc.ImportNode(secEnum,true); root.AppendChild(ffImportNode); return ConstStrings.CASA_SUCCESS; } else { //Console.WriteLine("FireFox some issue"); return ConstStrings.CASA_STORE_NOT_AVAILABLE; } } else Logger.DbgLog("A-D Lib:Aggregatestore:Could not aggregate Gnome FireFox since FireFoxEngine not instantiated"); } Logger.DbgLog("A-D Lib: Unknown Operation Requested"); #endif return ConstStrings.CASA_OPERATION_FAILED; } public int InitAD() { return ConstStrings.CASA_SUCCESS; } public int CleanUP_AD() { return ConstStrings.CASA_SUCCESS; } /*********************************************************************************************** IsStoreAvailable : Checks If Store Is Available It loads the required dlls for a particular store and returns true if all required dll/.so are present. public static Boolean IsStoreAvailable(int StoreID); Parameters StoreID : int value Novell.CASA.DataEngines.Common.ConstStrings.CASA_STORE_KWALLET = 3; Novell.CASA.DataEngines.Common.ConstStrings.CASA_STORE_GK = 4 Remarks 1. This API needs to be called before any other API of the particular store is called. 2. This API needs to be called before Aggregate() and AD_Facade constructor is called as these initializes the Datangines based on the Aggregate Policy set. 3. The Aggregate Policy needs to be reset appropriately based on the return value of this call. ***********************************************************************************************/ public static Boolean IsStoreAvailable(int StoreID) { if (StoreID == ConstStrings.CASA_STORE_GK) return GKEngine.IsStoreAvailable(); if (StoreID == ConstStrings.CASA_STORE_KWALLET) return KWalletEngine.IsStoreAvailable(); if (StoreID == ConstStrings.CASA_STORE_FFOX) return FFEngine.IsStoreAvailable(); return true; } /*********************************************************************************************** //isMasterPasswordSet : Checks If a MasterPassword is set for the store //Parameters: // int StoreID // //Return // // @return true master password is set // false master password not set //Notes: // This API is to be invoked on an AD instance and currently is supported only for the FireFox wallet // For FireFox, The check is profile specific with only the default profile supported currently // For FireFox, The check assumes that the profile needs to be initialized first. Hence the call to instanciate FFEngine ***********************************************************************************************/ public Boolean IsMasterPasswordSet(int StoreID) { if (StoreID == ConstStrings.CASA_STORE_FFOX) { int methodStatusCode=0; //Use the existing instance of firefox else instantiate if(ffEngine == null) ffEngine = new FFEngine(); methodStatusCode=ffEngine.isMasterPasswordSet(); if(methodStatusCode==1) return true; else return false; } return true; } /*********************************************************************************************** //VerifyMasterPassword : Verifies\Checks the validity of the MasterPassword for the store //Parameters: None // //Return // // @return true the specified master password is correct // false the specified master password is wrong //Notes: // This API is to be invoked on an AD instance and currently is supported only for the FireFox wallet // For FireFox, The set is profile specific with only the default profile supported currently // For FireFox, The set assumes that the profile needs to be initialized first. Hence the call to instanciate FFEngine ***********************************************************************************************/ public Boolean VerifyMasterPassword(string masterPassword,int StoreID) { if (StoreID == ConstStrings.CASA_STORE_FFOX) { int methodStatusCode=0; //Use the existing instance of firefox else instantiate if(ffEngine == null) ffEngine = new FFEngine(); methodStatusCode=ffEngine.verifyMasterPassword(masterPassword); if(methodStatusCode==1) return true; else return false; } return true; } } }