1 | /* |
2 | * PROGRAM: Firebird samples. |
3 | * MODULE: CryptKeyHolder.cpp |
4 | * DESCRIPTION: Sample of how key holder 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 <stdio.h> |
28 | #include <string.h> |
29 | |
30 | #include "firebird.h" |
31 | #include "firebird/Crypt.h" |
32 | |
33 | #include "../common/classes/fb_atomic.h" |
34 | |
35 | using namespace Firebird; |
36 | |
37 | namespace |
38 | { |
39 | |
40 | IMaster* master = NULL; |
41 | IPluginManager* pluginManager = NULL; |
42 | |
43 | class PluginModule : public IPluginModule |
44 | { |
45 | public: |
46 | PluginModule() |
47 | : flag(false) |
48 | { } |
49 | |
50 | void registerMe() |
51 | { |
52 | pluginManager->registerModule(this); |
53 | flag = true; |
54 | } |
55 | |
56 | ~PluginModule() |
57 | { |
58 | if (flag) |
59 | { |
60 | pluginManager->unregisterModule(this); |
61 | doClean(); |
62 | } |
63 | } |
64 | |
65 | int FB_CARG getVersion() |
66 | { |
67 | return FB_PLUGIN_MODULE_VERSION; |
68 | } |
69 | |
70 | IPluginModule* FB_CARG getModule() |
71 | { |
72 | return this; |
73 | } |
74 | |
75 | void FB_CARG doClean() |
76 | { |
77 | flag = false; |
78 | } |
79 | |
80 | private: |
81 | bool flag; |
82 | }; |
83 | |
84 | PluginModule module; |
85 | |
86 | class CryptKeyHolder : public IKeyHolderPlugin |
87 | { |
88 | public: |
89 | explicit CryptKeyHolder(IPluginConfig* cnf) |
90 | : callbackInterface(this), config(cnf), key(0), owner(NULL) |
91 | { |
92 | config->addRef(); |
93 | } |
94 | |
95 | ~CryptKeyHolder() |
96 | { |
97 | config->release(); |
98 | } |
99 | |
100 | // IKeyHolderPlugin implementation |
101 | virtual int FB_CARG keyCallback(IStatus* status, ICryptKeyCallback* callback); |
102 | virtual ICryptKeyCallback* FB_CARG keyHandle(IStatus* status, const char* keyName); |
103 | |
104 | int FB_CARG release() |
105 | { |
106 | if (--refCounter == 0) |
107 | { |
108 | delete this; |
109 | return 0; |
110 | } |
111 | return 1; |
112 | } |
113 | |
114 | void FB_CARG addRef() |
115 | { |
116 | ++refCounter; |
117 | } |
118 | |
119 | int FB_CARG getVersion() |
120 | { |
121 | return FB_KEYHOLDER_PLUGIN_VERSION; |
122 | } |
123 | |
124 | IPluginModule* FB_CARG getModule() |
125 | { |
126 | return &module; |
127 | } |
128 | |
129 | void FB_CARG setOwner(Firebird::IRefCounted* o) |
130 | { |
131 | owner = o; |
132 | } |
133 | |
134 | IRefCounted* FB_CARG getOwner() |
135 | { |
136 | return owner; |
137 | } |
138 | |
139 | UCHAR getKey() |
140 | { |
141 | return key; |
142 | } |
143 | |
144 | private: |
145 | class CallbackInterface : public ICryptKeyCallback |
146 | { |
147 | public: |
148 | explicit CallbackInterface(CryptKeyHolder* p) |
149 | : parent(p) |
150 | { } |
151 | |
152 | unsigned int FB_CARG callback(unsigned int, const void*, unsigned int length, void* buffer) |
153 | { |
154 | UCHAR k = parent->getKey(); |
155 | if (!k) |
156 | { |
157 | return 0; |
158 | } |
159 | |
160 | if (length > 0 && buffer) |
161 | { |
162 | memcpy(buffer, &k, 1); |
163 | } |
164 | return 1; |
165 | } |
166 | |
167 | int FB_CARG getVersion() |
168 | { |
169 | return FB_CRYPT_CALLBACK_VERSION; |
170 | } |
171 | |
172 | IPluginModule* FB_CARG getModule() |
173 | { |
174 | return &module; |
175 | } |
176 | |
177 | private: |
178 | CryptKeyHolder* parent; |
179 | }; |
180 | |
181 | CallbackInterface callbackInterface; |
182 | |
183 | IPluginConfig* config; |
184 | UCHAR key; |
185 | |
186 | AtomicCounter refCounter; |
187 | IRefCounted* owner; |
188 | |
189 | void noKeyError(IStatus* status); |
190 | }; |
191 | |
192 | void CryptKeyHolder::noKeyError(IStatus* status) |
193 | { |
194 | ISC_STATUS_ARRAY vector; |
195 | vector[0] = isc_arg_gds; |
196 | vector[1] = isc_random; |
197 | vector[2] = isc_arg_string; |
198 | vector[3] = (ISC_STATUS) "Key not set" ; |
199 | vector[4] = isc_arg_end; |
200 | status->set(vector); |
201 | } |
202 | |
203 | int FB_CARG CryptKeyHolder::keyCallback(IStatus* status, ICryptKeyCallback* callback) |
204 | { |
205 | status->init(); |
206 | |
207 | if (key != 0) |
208 | { |
209 | return 1; |
210 | } |
211 | |
212 | IConfig* def = config->getDefaultConfig(); |
213 | IConfigEntry* confEntry = def->find("Auto" ); |
214 | def->release(); |
215 | |
216 | if (confEntry) |
217 | { |
218 | char v = *(confEntry->getValue()); |
219 | confEntry->release(); |
220 | if (v == '1' || v == 'y' || v == 'Y' || v == 't' || v == 'T') |
221 | { |
222 | key = 0x5a; |
223 | return 1; |
224 | } |
225 | } |
226 | |
227 | if (callback && callback->callback(0, NULL, 1, &key) != 1) |
228 | { |
229 | key = 0; |
230 | return 0; |
231 | } |
232 | |
233 | return 1; |
234 | } |
235 | |
236 | ICryptKeyCallback* FB_CARG CryptKeyHolder::keyHandle(IStatus* status, const char* keyName) |
237 | { |
238 | if (strcmp(keyName, "sample" ) != 0) |
239 | { |
240 | return NULL; |
241 | } |
242 | |
243 | return &callbackInterface; |
244 | } |
245 | |
246 | class Factory : public IPluginFactory |
247 | { |
248 | public: |
249 | int FB_CARG getVersion() |
250 | { |
251 | return FB_PLUGIN_FACTORY_VERSION; |
252 | } |
253 | |
254 | IPluginModule* FB_CARG getModule() |
255 | { |
256 | return &module; |
257 | } |
258 | |
259 | IPluginBase* FB_CARG createPlugin(IPluginConfig* factoryParameter) |
260 | { |
261 | CryptKeyHolder* p = new CryptKeyHolder(factoryParameter); |
262 | p->addRef(); |
263 | return p; |
264 | } |
265 | }; |
266 | |
267 | Factory factory; |
268 | |
269 | } // anonymous namespace |
270 | |
271 | extern "C" void FB_PLUGIN_ENTRY_POINT(IMaster* m) |
272 | { |
273 | master = m; |
274 | pluginManager = master->getPluginManager(); |
275 | |
276 | module.registerMe(); |
277 | pluginManager->registerPluginFactory(PluginType::KeyHolder, "CryptKeyHolder_example" , |
278 | &factory); |
279 | } |
280 | |