Merge commit 'origin/master'
[versaplex.git] / vxodbc / wvssl_necessities.cc
blob87a6175e075fa88cbe1cf7688d41bc183e609b54
1 #include "wvssl_necessities.h"
2 #include "wvmoniker.h"
3 #include "wvsslstream.h"
4 #include "wvstrutils.h"
5 #include "uniconfroot.h";
6 #include "wvlinkerhack.h"
8 #include <wincrypt.h>
9 #include "wvbase64.h"
11 WV_LINK_TO(UniGenHack);
13 WvX509Mgr *clicert = NULL;
15 /* So like... what the fsck? Why, if we're overloading the SSL creation
16 * moniker anyway, don't we pass in a suitable function for the callback, and
17 * instead use the global assignment? Well, good question.
19 * There is also an sslcert moniker, which need our callback, but takes a
20 * certificate already encoded on the command line. It's possible, however
21 * unlikely, that someone would want to use that method (for, oh, say, testing).
23 * I don't want to overload sslcert... that thing is hairy. So, I only
24 * overload SSL so that it actually uses *a* certificate, and with the global
25 * assignment to global_vcb, either method will get the callback! Yay!
27 static IWvStream *create_ssl(WvStringParm s, IObject *obj)
29 return new WvSSLStream(IWvStream::create(s, obj), clicert, 0, false);
32 static WvMoniker<IWvStream> ssl_override("ssl", create_ssl, true);
34 static char *dbus_cert = NULL;
36 #ifdef _WIN32
37 static WvString wvunprotectdata(WvStringParm data)
39 /* Data is base64 encoded, must first decrypt it */
40 WvBase64Decoder decoder64;
41 WvDynBuf databuf;
43 decoder64.flushstrbuf(data, databuf, true);
44 DATA_BLOB decrypt_me, return_me;
45 decrypt_me.cbData = databuf.used();
46 decrypt_me.pbData = new BYTE[decrypt_me.cbData];
47 databuf.copy(decrypt_me.pbData, 0, decrypt_me.cbData);
48 WvString ret = WvString::null;
50 char *strdata;
51 if (!CryptUnprotectData(&decrypt_me, NULL, NULL, NULL, NULL, 0, &return_me))
53 goto out;
56 /* Since, clearly, all went well, we should have a null-terminated
57 * char * array stored in return_me.pbData */
58 strdata = new char[return_me.cbData];
59 memcpy(strdata, return_me.pbData, return_me.cbData);
60 ret = WvString(strdata).unique();
62 delete [] strdata;
63 LocalFree(return_me.pbData);
64 out:
65 delete [] decrypt_me.pbData;
66 return ret;
68 #else
69 #define wvunprotectdata
70 #endif
72 static bool verify_server(WvX509 *, WvSSLStream *s)
74 if (dbus_cert)
76 WvString pcert = s->getattr("peercert");
77 if (!strcmp(dbus_cert, trim_string(pcert.edit())))
78 return true;
81 return false;
84 static bool inited = false;
86 void init_wvssl()
88 if (inited)
89 return;
91 UniConfRoot conf;
92 #ifndef _WIN32
93 #warning On Linux, testing SSL requires a vxodbc.ini file. Check template.
94 conf.mount("ini:vxodbc.ini");
95 #else
96 conf.mount("registry:HKEY_CURRENT_USER/Software/Versabanq/VxODBC");
97 #endif
99 if (conf.isok() && conf["cert"].exists() && conf["privrsa"].exists())
101 clicert = new WvX509Mgr;
102 clicert->decode(WvX509::CertPEM, wvunprotectdata(*conf["cert"]));
103 clicert->decode(WvRSAKey::RsaPEM, wvunprotectdata(*conf["privrsa"]));
105 if (!clicert->isok())
106 WVRELEASE(clicert);
109 if (conf.isok() && conf["dbuscert"].exists())
111 WvString dcert = *conf["dbuscert"];
112 dbus_cert = new char[dcert.len() + 1];
113 dbus_cert = trim_string(strcpy(dbus_cert, dcert.cstr()));
114 WvSSLStream::global_vcb = verify_server;
117 inited = true;
120 void cleanup_wvssl()
122 WVRELEASE(clicert);
123 WvSSLStream::global_vcb = NULL;
124 delete [] dbus_cert;
125 inited = false;