1 | /* |
2 | * PROGRAM: Firebird samples. |
3 | * MODULE: DbCrypt.cpp |
4 | * DESCRIPTION: Sample of how diskcrypt may be written. |
5 | * |
6 | * The contents of this file are subject to the Initial |
7 | * Developer's Public License Version 1.0 (the "License"); |
8 | * you may not use this file except in compliance with the |
9 | * License. You may obtain a copy of the License at |
10 | * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. |
11 | * |
12 | * Software distributed under the License is distributed AS IS, |
13 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. |
14 | * See the License for the specific language governing rights |
15 | * and limitations under the License. |
16 | * |
17 | * The Original Code was created by Alex Peshkov |
18 | * for the Firebird Open Source RDBMS project. |
19 | * |
20 | * Copyright (c) 2012 Alex Peshkov <peshkoff at mail.ru> |
21 | * and all contributors signed below. |
22 | * |
23 | * All Rights Reserved. |
24 | * Contributor(s): ______________________________________. |
25 | */ |
26 | |
27 | #include "firebird.h" |
28 | #include "firebird/Crypt.h" |
29 | |
30 | #include "../common/classes/fb_atomic.h" |
31 | |
32 | using namespace Firebird; |
33 | |
34 | namespace |
35 | { |
36 | |
37 | IMaster* master = NULL; |
38 | IPluginManager* pluginManager = NULL; |
39 | |
40 | class PluginModule : public IPluginModule |
41 | { |
42 | public: |
43 | PluginModule() |
44 | : flag(false) |
45 | { } |
46 | |
47 | void registerMe() |
48 | { |
49 | pluginManager->registerModule(this); |
50 | flag = true; |
51 | } |
52 | |
53 | ~PluginModule() |
54 | { |
55 | if (flag) |
56 | { |
57 | pluginManager->unregisterModule(this); |
58 | doClean(); |
59 | } |
60 | } |
61 | |
62 | int FB_CARG getVersion() |
63 | { |
64 | return FB_PLUGIN_MODULE_VERSION; |
65 | } |
66 | |
67 | IPluginModule* FB_CARG getModule() |
68 | { |
69 | return this; |
70 | } |
71 | |
72 | void FB_CARG doClean() |
73 | { |
74 | flag = false; |
75 | } |
76 | |
77 | private: |
78 | bool flag; |
79 | }; |
80 | |
81 | PluginModule module; |
82 | |
83 | class DbCrypt : public IDbCryptPlugin |
84 | { |
85 | public: |
86 | explicit DbCrypt(IPluginConfig* cnf) |
87 | : config(cnf), key(0), owner(NULL) |
88 | { |
89 | config->addRef(); |
90 | } |
91 | |
92 | ~DbCrypt() |
93 | { |
94 | config->release(); |
95 | } |
96 | |
97 | // ICryptPlugin implementation |
98 | void FB_CARG encrypt(IStatus* status, unsigned int length, const void* from, void* to); |
99 | void FB_CARG decrypt(IStatus* status, unsigned int length, const void* from, void* to); |
100 | void FB_CARG setKey(IStatus* status, unsigned int length, IKeyHolderPlugin** sources); |
101 | |
102 | int FB_CARG release() |
103 | { |
104 | if (--refCounter == 0) |
105 | { |
106 | delete this; |
107 | return 0; |
108 | } |
109 | return 1; |
110 | } |
111 | |
112 | void FB_CARG addRef() |
113 | { |
114 | ++refCounter; |
115 | } |
116 | |
117 | int FB_CARG getVersion() |
118 | { |
119 | return FB_DBCRYPT_PLUGIN_VERSION; |
120 | } |
121 | |
122 | IPluginModule* FB_CARG getModule() |
123 | { |
124 | return &module; |
125 | } |
126 | |
127 | void FB_CARG setOwner(IRefCounted* o) |
128 | { |
129 | owner = o; |
130 | } |
131 | |
132 | IRefCounted* FB_CARG getOwner() |
133 | { |
134 | return owner; |
135 | } |
136 | |
137 | private: |
138 | IPluginConfig* config; |
139 | UCHAR key; |
140 | |
141 | AtomicCounter refCounter; |
142 | IRefCounted* owner; |
143 | |
144 | void noKeyError(IStatus* status); |
145 | }; |
146 | |
147 | void DbCrypt::noKeyError(IStatus* status) |
148 | { |
149 | ISC_STATUS_ARRAY vector; |
150 | vector[0] = isc_arg_gds; |
151 | vector[1] = isc_random; |
152 | vector[2] = isc_arg_string; |
153 | vector[3] = (ISC_STATUS)"Key not set" ; |
154 | vector[4] = isc_arg_end; |
155 | status->set(vector); |
156 | } |
157 | |
158 | void FB_CARG DbCrypt::encrypt(IStatus* status, unsigned int length, const void* from, void* to) |
159 | { |
160 | status->init(); |
161 | |
162 | if (!key) |
163 | { |
164 | noKeyError(status); |
165 | return; |
166 | } |
167 | |
168 | const UCHAR* f = static_cast<const UCHAR*>(from); |
169 | UCHAR* t = static_cast<UCHAR*>(to); |
170 | |
171 | while (length--) |
172 | { |
173 | *t++ = (*f++) + key; |
174 | } |
175 | } |
176 | |
177 | void FB_CARG DbCrypt::decrypt(IStatus* status, unsigned int length, const void* from, void* to) |
178 | { |
179 | status->init(); |
180 | |
181 | if (!key) |
182 | { |
183 | noKeyError(status); |
184 | return; |
185 | } |
186 | |
187 | const UCHAR* f = static_cast<const UCHAR*>(from); |
188 | UCHAR* t = static_cast<UCHAR*>(to); |
189 | |
190 | while (length--) |
191 | { |
192 | *t++ = (*f++) - key; |
193 | } |
194 | } |
195 | |
196 | void FB_CARG DbCrypt::setKey(IStatus* status, unsigned int length, IKeyHolderPlugin** sources) |
197 | { |
198 | status->init(); |
199 | |
200 | if (key != 0) |
201 | return; |
202 | |
203 | IConfig* def = config->getDefaultConfig(); |
204 | IConfigEntry* confEntry = def->find("Auto" ); |
205 | def->release(); |
206 | if (confEntry) |
207 | { |
208 | char v = *(confEntry->getValue()); |
209 | confEntry->release(); |
210 | if (v == '1' || v == 'y' || v == 'Y' || v == 't' || v == 'T') |
211 | { |
212 | key = 0x5a; |
213 | return; |
214 | } |
215 | } |
216 | |
217 | for (unsigned n = 0; n < length; ++n) |
218 | { |
219 | ICryptKeyCallback* callback = sources[n]->keyHandle(status, "sample" ); |
220 | if (!status->isSuccess()) |
221 | { |
222 | return; |
223 | } |
224 | |
225 | if (callback && callback->callback(0, NULL, 1, &key) == 1) |
226 | { |
227 | return; |
228 | } |
229 | } |
230 | |
231 | key = 0; |
232 | noKeyError(status); |
233 | } |
234 | |
235 | class Factory : public IPluginFactory |
236 | { |
237 | public: |
238 | int FB_CARG getVersion() |
239 | { |
240 | return FB_PLUGIN_FACTORY_VERSION; |
241 | } |
242 | |
243 | IPluginModule* FB_CARG getModule() |
244 | { |
245 | return &module; |
246 | } |
247 | |
248 | IPluginBase* FB_CARG createPlugin(IPluginConfig* factoryParameter) |
249 | { |
250 | DbCrypt* p = new DbCrypt(factoryParameter); |
251 | p->addRef(); |
252 | return p; |
253 | } |
254 | }; |
255 | |
256 | Factory factory; |
257 | |
258 | } // anonymous namespace |
259 | |
260 | extern "C" void FB_PLUGIN_ENTRY_POINT(IMaster* m) |
261 | { |
262 | master = m; |
263 | pluginManager = master->getPluginManager(); |
264 | |
265 | module.registerMe(); |
266 | pluginManager->registerPluginFactory(PluginType::DbCrypt, "DbCrypt_example" , &factory); |
267 | } |
268 | |