source: trunk/EraserDll/SecurityManager.cpp @ 20

Revision 20, 7.7 KB checked in by lowjoel, 7 years ago (diff)

Garrett's updated code.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1// SecurityManager.cpp
2//
3// Eraser. Secure data removal. For Windows.
4// Copyright © 1997-2001  Sami Tolvanen (sami@tolvanen.com).
5// Copyright © 2001-2006  Garrett Trant (support@heidi.ie).
6//
7// This program is free software; you can redistribute it and/or
8// modify it under the terms of the GNU General Public License
9// as published by the Free Software Foundation; either version 2
10// of the License, or (at your option) any later version.
11//
12// This program is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15// GNU General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License
18// along with this program; if not, write to the Free Software
19// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20// 02111-1307, USA.
21#include "stdafx.h"
22#include "SecurityManager.h"
23#include "SecManDlg.h"
24
25#include <vector>
26#include <atlbase.h>
27#include <atlcrypt.h>
28#include <atlsecurity.h>
29#define REG_PROTECT_KEY "Software\\Heidi Computers Ltd\\Eraser\\PROTECT"
30#define REG_PRODUCT_KEY "Software\\Heidi Computers Ltd\\Eraser"
31
32#define PROTECTION "protection"
33#define SECRET "sec"
34
35#pragma comment( lib, "Crypt32" )
36
37enum
38{
39    PROTECTION_ON = 1, PROTECTION_OFF = 0
40};
41
42__declspec(dllexport) bool no_registry;
43
44CSecurityManager::CSecurityManager(void)
45{
46}
47
48CSecurityManager::~CSecurityManager(void)
49{
50}
51static void init_sa(CSecurityAttributes& sa)
52{
53    TCHAR tcUser[1024];
54    DWORD dwSize = sizeof (tcUser);
55    if (FALSE == GetUserName(tcUser, &dwSize))
56    {
57        throw std::runtime_error("User detection error");
58    }
59
60    CDacl ac;   
61    ac.AddAllowedAce(CSid(tcUser), MAXIMUM_ALLOWED|GENERIC_ALL);
62    ac.AddAllowedAce(Sids::Users(), GENERIC_READ);
63    ac.AddAllowedAce(Sids::World(), GENERIC_READ);
64    ac.AddAllowedAce(Sids::Admins(), GENERIC_ALL);
65
66
67    CSecurityDesc sd;
68    sd.SetDacl(ac); 
69    sa.Set(sd);
70
71}
72void 
73CSecurityManager::Protect(const char* szSecret )
74{
75    extern bool no_registry;
76    if (no_registry)
77        return;
78
79    CRegKey protect;       
80    SetLastError(0);
81    DWORD dwErrorCode = 0;
82
83    if (ERROR_SUCCESS != protect.Create(HKEY_LOCAL_MACHINE, REG_PRODUCT_KEY ))
84        throw std::runtime_error("Unable to create key");
85
86
87    CSecurityAttributes sa;
88    init_sa(sa);
89
90    dwErrorCode = protect.Create(HKEY_LOCAL_MACHINE, 
91        REG_PROTECT_KEY
92        , REG_NONE
93        , REG_OPTION_NON_VOLATILE
94        , KEY_READ | KEY_WRITE
95        , &sa);
96
97
98    if (ERROR_SUCCESS != dwErrorCode)
99    {
100        if (ERROR_ACCESS_DENIED == dwErrorCode)
101            throw std::runtime_error("Access denied");         
102        throw std::runtime_error("Unable to create key");
103    }
104
105
106    DATA_BLOB data_in;
107    data_in.cbData = static_cast<DWORD>(strlen(szSecret) + 1);
108    data_in.pbData = reinterpret_cast<BYTE*>(const_cast<LPTSTR>(szSecret));
109    CRYPTPROTECT_PROMPTSTRUCT promt;
110    ZeroMemory(&promt, sizeof(promt));
111    promt.cbSize = sizeof(promt);
112    promt.dwPromptFlags = 0;
113    DATA_BLOB data_out;
114    DATA_BLOB data_entropy = data_in;
115
116
117    if(!CryptProtectData(
118        &data_in,
119        L"Eraser's protection",// A description string.
120        &data_entropy ,                               // Optional entropy
121
122        NULL,                               // Reserved.
123        &promt,                      // Pass a PromptStruct.
124        0,
125        &data_out))
126    {
127        throw std::runtime_error("Encryption error");
128    }
129
130    dwErrorCode = protect.SetBinaryValue(SECRET, data_out.pbData, data_out.cbData);
131
132    LocalFree(data_out.pbData);
133
134    if (ERROR_SUCCESS != dwErrorCode )
135    {
136
137        throw std::runtime_error("Unable set protection off");
138    }
139
140    protect.Close();
141
142}
143
144void 
145CSecurityManager::Unprotect()
146{
147    extern bool no_registry;
148    if (no_registry)
149        return;
150
151    CRegKey protect;
152
153    DWORD dwErrorCode = protect.Open(HKEY_LOCAL_MACHINE, REG_PRODUCT_KEY);
154    if (ERROR_SUCCESS != dwErrorCode )
155    {
156        if (ERROR_ACCESS_DENIED == dwErrorCode)
157            throw std::runtime_error("Access denied"); 
158
159        return;
160    }
161
162    dwErrorCode = protect.DeleteSubKey("PROTECT");
163    /*
164    if (ERROR_SUCCESS != dwErrorCode ) 
165    throw std::runtime_error("Unable to unprotect");   
166    */
167}
168
169bool 
170CSecurityManager::Check(const char* szSecret )
171{
172    extern bool no_registry;
173    if (no_registry)
174        return true;
175
176    CRegKey protect;
177
178    DWORD dwErrorCode = protect.Open(HKEY_LOCAL_MACHINE, REG_PROTECT_KEY, KEY_READ);
179    if (ERROR_SUCCESS != dwErrorCode )
180    {
181        if (ERROR_ACCESS_DENIED == dwErrorCode )
182            throw std::runtime_error("Access denied");
183        return true;
184    }   
185
186    ULONG blob_len;
187    if (ERROR_SUCCESS != protect.QueryBinaryValue(SECRET, NULL, &blob_len))
188        throw std::runtime_error("No data");
189
190    std::vector<unsigned char> blob;
191    blob.resize(blob_len); 
192
193    if (ERROR_SUCCESS != protect.QueryBinaryValue(SECRET, &blob[0], &blob_len))
194        throw std::runtime_error("No data");
195
196    LPWSTR pDescrOut = NULL;
197
198    DATA_BLOB data_verify;
199    DATA_BLOB data_enc;
200    DATA_BLOB data_entropy;
201    data_entropy.cbData = static_cast<DWORD>(strlen(szSecret) + 1);
202    data_entropy.pbData = reinterpret_cast<BYTE*>(const_cast<LPTSTR>(szSecret));
203    data_enc.cbData = blob_len;
204    data_enc.pbData = reinterpret_cast<BYTE*>(&blob[0]);
205
206    CRYPTPROTECT_PROMPTSTRUCT promt;
207    ZeroMemory(&promt, sizeof(promt));
208    promt.cbSize = sizeof(promt);
209    promt.dwPromptFlags = 0;
210
211    if (!CryptUnprotectData(
212        &data_enc,
213        &pDescrOut,
214        &data_entropy,                 // Optional entropy
215        NULL,                 // Reserved
216        &promt,        // Optional PromptStruct
217        0,
218        &data_verify))
219    {
220
221        return false;
222    }
223    bool ret = (0 == memcmp(data_verify.pbData, szSecret, data_verify.cbData));
224    LocalFree(pDescrOut);
225    LocalFree(data_verify.pbData);
226    return ret;
227}
228bool
229CSecurityManager::IsProtected()
230{
231    extern bool no_registry;
232    if (no_registry)
233        return false;
234
235    CRegKey protect;
236
237    DWORD dwErrorCode = protect.Open(HKEY_LOCAL_MACHINE, REG_PROTECT_KEY, KEY_READ);
238    if (ERROR_SUCCESS != dwErrorCode )         
239        return ERROR_ACCESS_DENIED == dwErrorCode;     
240
241
242    ULONG blob_len(1);
243    dwErrorCode  = protect.QueryBinaryValue(SECRET, NULL, &blob_len);
244    if (ERROR_ACCESS_DENIED == dwErrorCode  )
245        return true;
246
247    return ERROR_SUCCESS == dwErrorCode;
248
249}
250
251bool CheckAccess(DWORD dwMaxError /*= 3*/)
252{
253
254    bool is_ok(false);
255    try
256    {
257        if (!CSecurityManager::IsProtected())   
258            return true;
259        AFX_MANAGE_STATE(AfxGetStaticModuleState( ))
260
261   
262        CSecManDlg dlg;
263        dlg.SetMode(CSecManDlg::CHECKUP);
264        for (DWORD  i = 0; i <dwMaxError;)
265        {
266            dlg.Clear();
267            if (IDOK  != dlg.DoModal())
268                return false;
269           
270            is_ok = CSecurityManager::Check(dlg.GetSecret());
271
272            if (is_ok)                         
273                return true;
274            ++i;                       
275            AfxGetApp()->GetMainWnd()->MessageBox("Password incorrect", "Security error", MB_OK|MB_ICONERROR);
276        }
277    }
278    catch (const CAtlException& )
279    {
280        is_ok = false;
281    }
282    catch (CException* ee)
283    {
284        ee->ReportError();
285        ee->Delete();
286        is_ok = false;
287    }
288    catch (const std::exception& e)
289    {
290        AfxGetApp()->GetMainWnd()->MessageBox(e.what(), "Security error", MB_OK|MB_ICONERROR);
291        is_ok = false;
292    }
293   
294    return is_ok;
295}
296
297bool SetProtection()
298{
299    bool is_ok(false);
300    try
301    {   
302        if (!CheckAccess(1))
303            return false;
304
305        AFX_MANAGE_STATE(AfxGetStaticModuleState( ))
306
307        CSecManDlg dlg;
308        dlg.SetMode(CSecManDlg::SETUP);
309        if (IDOK  != dlg.DoModal())
310            return false;
311
312        CSecurityManager::Protect(dlg.GetSecret());
313        is_ok = true;
314    }
315    catch (const CAtlException& )
316    {
317        is_ok = false;
318    }
319    catch (CException* ee)
320    {
321        ee->ReportError();
322        ee->Delete();
323        is_ok = false;
324    }
325    catch (const std::exception& e)
326    {
327        AfxGetApp()->GetMainWnd()->MessageBox(e.what(), "Security error", MB_OK|MB_ICONERROR);
328        is_ok = false;
329    }
330    return is_ok;
331}
332
333bool ClearProtection()
334{
335    bool is_ok(false);
336    try
337    {
338        if (!CheckAccess(1))
339            return false;
340
341        CSecurityManager::Unprotect();
342        is_ok = true;
343    }
344    catch (const CAtlException& )
345    {
346        is_ok = false;
347    }
348    catch (CException* ee)
349    {
350        ee->ReportError();
351        ee->Delete();
352        is_ok = false;
353    }
354    catch (const std::exception& e)
355    {
356        AfxGetApp()->GetMainWnd()->MessageBox(e.what(), "Security error", MB_OK|MB_ICONERROR);
357        is_ok = false;
358    }
359    return is_ok;
360}
Note: See TracBrowser for help on using the repository browser.