--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/vpnui/vpnpolins/src/vpndevlockhandler.cpp Thu Dec 17 09:14:51 2009 +0200
@@ -0,0 +1,679 @@
+/*
+* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Utility classes for device lock handling
+*
+*/
+
+
+
+#include <e32std.h>
+
+#include "vpndevlockhandler.h"
+#include "policyinstaller_constants.h"
+#include "logvpncommon.h"
+#include "vpntcstub.h"
+
+
+// 64bit integer's string representation can be at
+// most 20 bytes (+ sign) long...
+#define MAX_INT_STR_LEN 21
+
+
+//////////////
+// CVpnDevLockPolicy implementation
+
+CVpnDevLockPolicy* CVpnDevLockPolicy::NewL(const TInt aPolicy)
+ {
+ LOG_("-> CVpnDevLockPolicy::NewL()");
+
+ CVpnDevLockPolicy* self = new (ELeave) CVpnDevLockPolicy();
+ CleanupStack::PushL(self);
+ self->ConstructL(aPolicy);
+ CleanupStack::Pop(self);
+
+ LOG_("<- CVpnDevLockPolicy::NewL()");
+
+ return self;
+ }
+
+CVpnDevLockPolicy* CVpnDevLockPolicy::NewLC(const TInt aPolicy)
+ {
+ LOG_("-> CVpnDevLockPolicy::NewLC()");
+
+ CVpnDevLockPolicy* self = new (ELeave) CVpnDevLockPolicy();
+ CleanupStack::PushL(self);
+ self->ConstructL(aPolicy);
+
+ LOG_("<- CVpnDevLockPolicy::NewLC()");
+
+ return self;
+ }
+
+CVpnDevLockPolicy* CVpnDevLockPolicy::NewLC()
+ {
+ LOG_("-> CVpnDevLockPolicy::NewLC()");
+
+ CVpnDevLockPolicy* self = new (ELeave) CVpnDevLockPolicy();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+
+ LOG_("<- CVpnDevLockPolicy::NewLC()");
+
+ return self;
+ }
+
+CVpnDevLockPolicy::CVpnDevLockPolicy()
+ {
+ }
+
+CVpnDevLockPolicy::~CVpnDevLockPolicy()
+ {
+ LOG_("-> CVpnDevLockPolicy::CVpnDevLockPolicy()");
+
+ // Delete each entry from the policy attributes array,
+ // and then reset the array itself
+ if (iPolicyArray)
+ {
+ for (TInt i = iPolicyArray->Count() - 1; i >= 0; i--)
+ {
+ delete iPolicyArray->At(i);
+ }
+ iPolicyArray->Reset();
+ }
+
+ delete iPolicyArray;
+
+ LOG_("<- CVpnDevLockPolicy::CVpnDevLockPolicy()");
+ }
+
+void CVpnDevLockPolicy::ConstructL(const TInt aPolicy)
+ {
+ LOG_("-> CVpnDevLockPolicy::ConstructL()");
+ ConstructL();
+ SetPolicyLevelL(aPolicy);
+ LOG_("<- CVpnDevLockPolicy::ConstructL()");
+ }
+
+void CVpnDevLockPolicy::ConstructL()
+ {
+ LOG_("-> CVpnDevLockPolicy::ConstructL()");
+ iPolicyArray = new (ELeave) CArrayFixFlat<CVpnDevLockAttribute*>(3);
+ LOG_("<- CVpnDevLockPolicy::ConstructL()");
+ }
+
+void CVpnDevLockPolicy::SetPolicyAttributeL(const TInt aAttrib, const TInt aVal)
+ {
+ LOG_("-> CVpnDevLockPolicy::SetPolicyAttributeL() int variant");
+
+ CVpnDevLockAttribute* attrib = CVpnDevLockAttribute::NewL(aAttrib, aVal);
+ CleanupStack::PushL(attrib);
+ iPolicyArray->AppendL(attrib);
+
+ // ownership's been transferred to array
+ CleanupStack::Pop(attrib);
+
+
+ // Remove this (or rather flag for debug builds only)
+ TInt val(0);
+ attrib->AttributeValueAsIntL(val);
+
+ LOG_1(" Items in array: %d", iPolicyArray->Count());
+ LOG8_1(" Attrib ID: %d", attrib->AttributeId());
+ LOG8_1(" Attrib val: %d", val);
+
+ LOG_("<- CVpnDevLockPolicy::SetPolicyAttributeL() int variant");
+ }
+
+
+void CVpnDevLockPolicy::SetPolicyAttributeL(const TInt aAttrib, const TDesC8& aVal)
+ {
+ LOG_("-> CVpnDevLockPolicy::SetPolicyAttributeL() str variant");
+
+ // Create a new attribute and add it to the existing array of attributes
+ CVpnDevLockAttribute* attrib = CVpnDevLockAttribute::NewL(aAttrib, aVal);
+ CleanupStack::PushL(attrib);
+ iPolicyArray->AppendL(attrib);
+
+ // ownership's been transferred to array
+ CleanupStack::Pop(attrib);
+
+ LOG8_1(" Attrib ID: %d", attrib->AttributeId());
+
+ LOG_("<- CVpnDevLockPolicy::SetPolicyAttributeL() str variant");
+ }
+
+/**
+ * Description of device lock levels (from SUB 415-467)
+ *
+ * 0. Do not enforce device lock
+ * - installing this policy has no impact on the device lock settings
+ * 1. Enforce device lock with policy 1
+ * - no special requirements on lock code
+ * - autolock timeout 30 minutes
+ * - wipe after 20 unsuccessful unlocking attempts
+ * 2. Enforce device lock with policy 2
+ * - lock code minimum length 5 characters
+ * - autolock timeout 10 minutes
+ * - wipe after 10 unsuccessful unlocking attempts
+ * 3. Enforce device lock with policy 3
+ * - lock code mimimum length 5 characters
+ * - both characters and numbers required
+ * - both upper and lower case letters required
+ * - passcode expires every 30 days and must be changed
+ * - new passcode must not match any of the 5 previous passcodes
+ * - autolock timeout 5 minutes
+ * - wipe after 10 unsuccessful unlocking attempts
+ *
+ */
+void CVpnDevLockPolicy::SetPolicyLevelL(const TInt aPolLevel)
+ {
+ LOG_("-> CVpnDevLockPolicy::SetPolicyLevelL()");
+
+ LOG_1(" Setting policy level: %d", aPolLevel);
+
+ // Setting the policy level
+ // See VPN device lock SUB for exact device lock policy level descriptions
+ switch (aPolLevel)
+ {
+ case 0:
+ // No changes to existing devlock policy,
+ // when policy level is 0
+ break;
+ case 1:
+ // Only enforce timeout and max number of passcode attempts
+ SetPolicyAttributeL(RTerminalControl3rdPartySession::ETimeout, 30);
+ SetPolicyAttributeL(RTerminalControl3rdPartySession::EPasscodeMaxAttempts, 20);
+ SetPolicyAttributeL(RTerminalControl3rdPartySession::EMaxTimeout, 30);
+ break;
+ case 2:
+ // Enforce stricter timeout as well, and a minimum length for passcode
+ SetPolicyAttributeL(RTerminalControl3rdPartySession::ETimeout, 10);
+ SetPolicyAttributeL(RTerminalControl3rdPartySession::EPasscodeMinLength, 5);
+ SetPolicyAttributeL(RTerminalControl3rdPartySession::EPasscodeMaxAttempts, 10);
+ SetPolicyAttributeL(RTerminalControl3rdPartySession::EMaxTimeout, 10);
+ break;
+ case 3:
+ // Enforce even more password-related rules
+ SetPolicyAttributeL(RTerminalControl3rdPartySession::ETimeout, 5);
+ SetPolicyAttributeL(RTerminalControl3rdPartySession::EPasscodeMinLength, 5);
+ SetPolicyAttributeL(RTerminalControl3rdPartySession::EPasscodeMaxAttempts, 10);
+ SetPolicyAttributeL(RTerminalControl3rdPartySession::EPasscodeRequireCharsAndNumbers,
+ 1);
+ SetPolicyAttributeL(RTerminalControl3rdPartySession::EPasscodeRequireUpperAndLower,
+ 1);
+ SetPolicyAttributeL(RTerminalControl3rdPartySession::EPasscodeExpiration, 30);
+ SetPolicyAttributeL(RTerminalControl3rdPartySession::EPasscodeHistoryBuffer, 5);
+ SetPolicyAttributeL(RTerminalControl3rdPartySession::EMaxTimeout, 5);
+ break;
+ default:
+ // Policy levels 4+ not supported, leave (tried to instantiate an illegal policy)
+ LOG_("<- CVpnDevLockPolicy::SetPolicyLevelL() LEAVE: illegal policy level");
+ User::Leave(KErrNotSupported);
+ break;
+ }
+
+ LOG_("<- CVpnDevLockPolicy::SetPolicyLevelL()");
+ }
+
+TInt CVpnDevLockPolicy::AttributeCount()
+ {
+ LOG_("-> CVpnDevLockPolicy::AttributeCount()");
+
+ TInt ret(0);
+ if (iPolicyArray)
+ {
+ ret = iPolicyArray->Count();
+ }
+
+ LOG_1("<- CVpnDevLockPolicy::AttributeCount() ret: %d", ret);
+ return ret;
+ }
+
+CVpnDevLockAttribute* CVpnDevLockPolicy::GetPolicyAttributeAt(const TInt aIdx)
+ {
+ LOG_("-> CVpnDevLockPolicy::GetPolicyAttributeAt()");
+ CVpnDevLockAttribute* ret(NULL);
+
+ if (iPolicyArray && (aIdx < iPolicyArray->Count()))
+ {
+ LOG_1(" Found valid attribute at index %d", aIdx);
+ ret = iPolicyArray->At(aIdx);
+ }
+
+ LOG_("<- CVpnDevLockPolicy::GetPolicyAttributeAt()");
+ return ret;
+ }
+
+
+//////////////
+// CVpnDevLockHandler implementation
+
+/**
+ * Constructor, and
+ *
+ */
+CVpnDevLockHandler::CVpnDevLockHandler()
+ {
+ LOG_("-> CVpnDevLockHandler::CVpnDevLockHandler()");
+
+ LOG_("<- CVpnDevLockHandler::CVpnDevLockHandler()");
+ }
+
+void CVpnDevLockHandler::ConstructL()
+ {
+ // Connect to terminal control (if available)
+ LoadTCLibraryL();
+ }
+
+void CVpnDevLockHandler::LoadTCLibraryL()
+ {
+ LOG_("-> CVpnDevLockHandler::LoadTCLibraryL()");
+
+ TInt status = iTcLib.Load(KVpnDevLockWrapperDll, KNullUid);
+
+ LOG_1(" DLL load status: %d", status);
+
+ if (status == KErrNone)
+ {
+ LOG_(" Suitable library found, instantiating dev lock object");
+
+ TLibraryFunction entry = iTcLib.Lookup(1);
+
+ // Entry point function (NewTcStubL) might leave,
+ // although it isn't readily obvious from the syntax
+ iTcStub = (CVpnTcStub*)entry();
+
+ LOG_(" Dev lock object instantiated");
+ iDevLockAvailable = ETrue;
+ }
+ else
+ {
+ LOG_(" No suitable library found!");
+ iDevLockAvailable = EFalse;
+ }
+
+ LOG_("<- CVpnDevLockHandler::LoadTCLibraryL()");
+ }
+
+CVpnDevLockHandler::~CVpnDevLockHandler()
+ {
+ LOG_("-> CVpnDevLockHandler::CVpnDevLockHandler()");
+
+ LOG_(" Deleting TC stub");
+ delete iTcStub;
+
+ LOG_(" Closing TC library");
+ iTcLib.Close();
+
+ LOG_("<- CVpnDevLockHandler::CVpnDevLockHandler()");
+ }
+
+void CVpnDevLockHandler::TerminalControlSupportsVpnL()
+ {
+ LOG_("-> CVpnDevLockHandler::TerminalControlSupportsVpnL()");
+
+ HBufC8* attrib(NULL);
+
+ // If the lib stub is available, try to read a device lock attribute
+ // (read may fail))
+ if (iTcStub)
+ {
+ LOG_(" TC stub is valid");
+ attrib = iTcStub->GetTCAttributeL(RTerminalControl3rdPartySession::ETimeout);
+
+ if (attrib)
+ {
+ LOG8_1(" Attribute: '%S'", attrib);
+ delete attrib;
+ }
+ else
+ {
+ LOG_(" Attribute couldn't be read");
+ User::Leave(KErrAccessDenied);
+ }
+ }
+ else
+ {
+ LOG_(" No stub available, terminating");
+ User::Leave(KErrAccessDenied);
+ }
+
+ LOG_("<- CVpnDevLockHandler::TerminalControlSupportsVpnL()");
+ }
+
+void CVpnDevLockHandler::SetTerminalControlPolicyL(const TInt aPolLevel)
+ {
+ LOG_("-> CVpnDevLockHandler::SetTerminalControlPolicyL()");
+ LOG_1(" Setting policy level %d", aPolLevel);
+
+ CVpnDevLockPolicy* devpolicy = CVpnDevLockPolicy::NewL(aPolLevel);
+ CleanupStack::PushL(devpolicy);
+
+ // Iterate through all the attributes that VPN policy requires.
+ // For each one found, check if it's stricter than the old device lock setting,
+ // and only if that is the case, update the actual value on device.
+
+ TInt attribs = devpolicy->AttributeCount();
+ LOG_1(" Iterating through %d attributes", attribs);
+
+ TBool forceLock(EFalse);
+
+ for (TInt i = 0; i < attribs; i++)
+ {
+ CVpnDevLockAttribute* attrib = devpolicy->GetPolicyAttributeAt(i);
+ if (!attrib)
+ {
+ LOG_("<- CVpnDevLockHandler::SetTerminalControlPolicyL() LEAVE: Not found");
+ User::Leave(KErrNotFound);
+ }
+
+ LOG_1(" Attribute ID: %d", attrib->AttributeId());
+
+ // Only set the attribute if the existing one was not as strict
+ // (definition of "strict" depends on attribute's semantics)
+ TBool override(EFalse);
+ TRAPD(err, override = OverrideExistingL(*attrib));
+
+ if ((err == KErrNone && override) || err == KErrNotFound)
+ {
+ SetDevAttributeL(*attrib);
+ forceLock = ETrue;
+ }
+
+ }
+
+ // If at least one lock parameter was (succesfully) changed, force device lock after
+ // import
+ if (forceLock)
+ {
+ LOG_(" Forcing device lock activation");
+
+ // Force lock
+ CVpnDevLockAttribute* attrib = CVpnDevLockAttribute::NewL(RTerminalControl3rdPartySession::ELock,
+ 1);
+ CleanupStack::PushL(attrib);
+
+ // Expire password (force password change)
+ CVpnDevLockAttribute* attrib2 =
+ CVpnDevLockAttribute::NewL(RTerminalControl3rdPartySession::EPasscodeExpiration, -1);
+ CleanupStack::PushL(attrib2);
+
+ LOG_(" Expiring old passcode");
+ SetDevAttributeL(*attrib2);
+ CleanupStack::PopAndDestroy(attrib2);
+
+ LOG_(" Forcing device lock");
+ SetDevAttributeL(*attrib);
+ CleanupStack::PopAndDestroy(attrib);
+ }
+
+
+ CleanupStack::PopAndDestroy(devpolicy);
+
+ LOG_("<- CVpnDevLockHandler::SetTerminalControlPolicyL()");
+ }
+
+TBool CVpnDevLockHandler::OverrideExistingL(const CVpnDevLockAttribute& aNew)
+ {
+ LOG_("-> CVpnDevLockHandler::OverrideExisting()");
+ TBool ret(EFalse);
+
+ HBufC8* existingAttrib = GetDevAttribValueL(aNew.AttributeId());
+ CleanupStack::PushL(existingAttrib);
+
+ // At the moment, we can rely on the fact that all relevant
+ // attributes are numerical... This may change in future
+ TInt newVal(-1);
+ TInt oldVal(-1);
+ TLex8 lexer(*existingAttrib);
+ User::LeaveIfError(lexer.Val(oldVal));
+ aNew.AttributeValueAsIntL(newVal);
+
+ switch (aNew.AttributeId())
+ {
+ case RTerminalControl3rdPartySession::ETimeout:
+ // If device lock timeout is set to lower value than the old one,
+ // then we need to update the policy
+ LOG_(" Case ETimeout");
+ if (newVal < oldVal || oldVal == 0)
+ {
+ ret = ETrue;
+ }
+ break;
+ case RTerminalControl3rdPartySession::EPasscodeMinLength:
+ // If passcode minimum length requirement is longer than the
+ // old one, then we need to update the policy
+ LOG_(" Case EPasscodeMinLength");
+ if (newVal > oldVal)
+ {
+ ret = ETrue;
+ }
+ break;
+ case RTerminalControl3rdPartySession::EPasscodeMaxAttempts:
+ // If max attempts lower, override
+ LOG_(" Case EPasscodeMaxAttempts");
+ if (newVal < oldVal || oldVal == 0)
+ {
+ ret = ETrue;
+ }
+ break;
+ case RTerminalControl3rdPartySession::EPasscodeRequireCharsAndNumbers:
+ // If alphanum requirement didn't exist before, override
+ LOG_(" Case EPasscodeRequireCharsAndNumbers");
+ if (newVal > oldVal)
+ {
+ ret = ETrue;
+ }
+ break;
+ case RTerminalControl3rdPartySession::EPasscodeRequireUpperAndLower:
+ // If UC/LC requirement didn't exist before, override
+ LOG_(" Case EPasscodeRequireUpperAndLower");
+ if (newVal > oldVal)
+ {
+ ret = ETrue;
+ }
+ break;
+ case RTerminalControl3rdPartySession::EPasscodeExpiration:
+ // If less days before passcode expiration, override
+ LOG_(" Case EPasscodeExpiration");
+ if (newVal < oldVal || oldVal == 0)
+ {
+ ret = ETrue;
+ }
+ break;
+ case RTerminalControl3rdPartySession::EPasscodeHistoryBuffer:
+ // If the proposed passcode history is longer, override
+ LOG_(" Case EPasscodeHistoryBuffer");
+ if (newVal > oldVal)
+ {
+ ret = ETrue;
+ }
+ break;
+ case RTerminalControl3rdPartySession::EMaxTimeout:
+ // If the proposed max timeout is shorter, override
+ LOG_(" Case EMaxTimeout");
+ if ((oldVal == 0) || (newVal < oldVal))
+ {
+ ret = ETrue;
+ }
+ break;
+ default:
+ LOG_(" ERROR: Case default, unknown attribute!");
+ User::Leave(KErrNotFound);
+ break;
+ }
+ CleanupStack::PopAndDestroy(existingAttrib);
+
+ LOG_1(" Old value: %d", oldVal);
+ LOG_1(" New value: %d", newVal);
+ LOG( if (ret)
+ {
+ LOG_(" => Old value needs to be updated");
+ }
+ );
+
+ LOG_1("<- CVpnDevLockHandler::OverrideExisting() ret: %d", ret);
+ return ret;
+ }
+
+HBufC8* CVpnDevLockHandler::GetDevAttribValueL(const TInt aAttribId)
+ {
+ LOG_("-> CVpnDevLockHandler::GetDevAttribValueL()");
+
+ HBufC8* buffer(NULL);
+
+ if (iTcStub)
+ {
+ buffer = iTcStub->GetTCAttributeL(aAttribId);
+ if (buffer)
+ {
+ LOG8_1(" Buffer: '%S'", buffer);
+ }
+ }
+
+ LOG_("<- CVpnDevLockHandler::GetDevAttribValueL()");
+
+ return buffer;
+ }
+
+void CVpnDevLockHandler::SetDevAttributeL(const CVpnDevLockAttribute& aNew)
+ {
+ LOG_("-> CVpnDevLockHandler::SetDevAttribValueL()");
+
+ if (iTcStub)
+ {
+ iTcStub->SetTCAttributeL(aNew.AttributeId(), aNew.AttributeValue());
+ }
+
+ LOG_("<- CVpnDevLockHandler::SetDevAttribValueL()");
+ }
+
+
+//////////////
+// CVpnDevLockAttribute implementation
+
+CVpnDevLockAttribute* CVpnDevLockAttribute::NewL(const TInt aId, const TDesC8& aVal)
+ {
+ LOG_("-> CVpnDevLockAttribute::NewL()");
+
+ CVpnDevLockAttribute* self = new (ELeave) CVpnDevLockAttribute();
+ CleanupStack::PushL(self);
+ self->ConstructL(aId, aVal);
+ CleanupStack::Pop(self);
+
+ LOG_("<- CVpnDevLockAttribute::NewL()");
+ return self;
+ }
+
+CVpnDevLockAttribute* CVpnDevLockAttribute::NewL(const TInt aId, const TInt aVal)
+ {
+ LOG_("-> CVpnDevLockAttribute::NewL()");
+
+ CVpnDevLockAttribute* self = new (ELeave) CVpnDevLockAttribute();
+ CleanupStack::PushL(self);
+ self->ConstructL(aId, aVal);
+ CleanupStack::Pop(self);
+
+ LOG_("<- CVpnDevLockAttribute::NewL()");
+ return self;
+ }
+
+CVpnDevLockAttribute* CVpnDevLockAttribute::NewLC(const TInt aId, const TDesC8& aVal)
+ {
+ LOG_("-> CVpnDevLockAttribute::NewLC()");
+
+ CVpnDevLockAttribute* self = new (ELeave) CVpnDevLockAttribute();
+ CleanupStack::PushL(self);
+ self->ConstructL(aId, aVal);
+
+ LOG_("<- CVpnDevLockAttribute::NewLC()");
+
+ return self;
+ }
+
+CVpnDevLockAttribute::~CVpnDevLockAttribute()
+ {
+ LOG_("-> CVpnDevLockAttribute::~CVpnDevLockAttribute()");
+ delete iAttributeVal;
+ LOG_("<- CVpnDevLockAttribute::~CVpnDevLockAttribute()");
+ }
+
+CVpnDevLockAttribute::CVpnDevLockAttribute()
+ {
+ LOG_("-> CVpnDevLockAttribute::CVpnDevLockAttribute()");
+ LOG_("<- CVpnDevLockAttribute::CVpnDevLockAttribute()");
+ }
+
+void CVpnDevLockAttribute::ConstructL(const TInt aId, const TDesC8& aVal)
+ {
+ iAttributeId = aId;
+ iAttributeVal = aVal.AllocL();
+ }
+
+void CVpnDevLockAttribute::ConstructL(const TInt aId, const TInt aVal)
+ {
+ // Convert int to a string
+ iAttributeId = aId;
+ TBuf8<MAX_INT_STR_LEN> buf;
+ buf.Num(aVal);
+ iAttributeVal = buf.AllocL();
+ }
+
+TPtrC8 CVpnDevLockAttribute::AttributeValue() const
+ {
+ return *iAttributeVal;
+ }
+
+void CVpnDevLockAttribute::AttributeValueAsIntL(TInt& aVal) const
+ {
+ if (iAttributeVal)
+ {
+ TLex8 lexer(*iAttributeVal);
+ User::LeaveIfError(lexer.Val(aVal));
+ }
+ }
+
+TInt CVpnDevLockAttribute::AttributeId() const
+ {
+ return iAttributeId;
+ }
+
+
+
+CVpnDevLockHandler* CVpnDevLockHandler::NewL()
+ {
+ LOG_("-> CVpnDevLockHandler::NewL()");
+
+ CVpnDevLockHandler* self = new (ELeave) CVpnDevLockHandler();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+
+ LOG_("<- CVpnDevLockAttribute::NewL()");
+ return self;
+ }
+
+CVpnDevLockHandler* CVpnDevLockHandler::NewLC()
+ {
+ LOG_("-> CVpnDevLockAttribute::NewLC()");
+
+ CVpnDevLockHandler* self = new (ELeave) CVpnDevLockHandler();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+
+ LOG_("<- CVpnDevLockAttribute::NewLC()");
+
+ return self;
+ }
+