vpnui/vpnpolins/src/vpndevlockhandler.cpp
changeset 0 33413c0669b9
--- /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;
+    }
+