#include #include "stringutils.h" #include "debug.h" #include "ConfigApi.h" #include "FileFunctions.h" #include "findcert.h" #include #ifndef _WIN32 #include #endif // note: CryptBinaryToString is not available on win2k or older systems. // // http://msdn.microsoft.com/library/en-us/mobilesdk5/html/wce51conconfigurationserviceproviderreferenceforwindowsmobiledevices.asp // OMA-SyncML-DevInfo-DTD-V1_1_2-20030505-D.dtd // OMA-WAP-ProvCont-v1_1-20021112-C // http://www.openmobilealliance.org/release_program/index.html // // // // // // // // // // // // // // done: return errlevel when the operation failed. // const char* storenames[]= { "Privileged Execution Trust Authorities", "Unprivileged Execution Trust Authorities", "SPC", "CA", "Root", "MY", }; bool CalcSha1(const ByteVector& data, ByteVector &hash) { #ifdef _WIN32 HCRYPTPROV hProv; HCRYPTHASH hHash; if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { error("CryptAcquireContext"); hProv= NULL; return false; } if (!CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash)) { error("CryptCreateHash"); return false; } if (!CryptHashData(hHash, vectorptr(data), data.size(), 0)) { error("CryptHashData"); return false; } DWORD dwSize; if (!CryptGetHashParam(hHash, HP_HASHVAL, NULL, &dwSize, 0)) { error("CryptGetHashParam"); return false; } hash.resize(dwSize); if (!CryptGetHashParam(hHash, HP_HASHVAL, vectorptr(hash), &dwSize, 0)) { error("CryptGetHashParam"); return false; } CryptDestroyHash(hHash); hHash= NULL; CryptReleaseContext(hProv, 0); hProv= NULL; return true; #else #ifndef OPENSSL_NO_SHA1 #define SHA1_DIGEST_LENGTH SHA_DIGEST_LENGTH typedef SHA_CTX SHA1_CTX; #endif SHA1_CTX ctx; hash.resize(SHA1_DIGEST_LENGTH); SHA1_Init(&ctx); SHA1_Update(&ctx, &data[0], data.size()); SHA1_Final(&hash[0], &ctx); return true; #endif } std::string CalcSha1Hex(const ByteVector& data) { ByteVector hash; if (!CalcSha1(data, hash)) return "ERROR"; std::string hex; for (size_t i=0 ; i6) { if (dest) dest[written]=base64[((temp>>(bits-6))&63)]; ++written; bits-=6; } } if (bits) { temp<<=(6-bits); if (dest) dest[written]=base64[temp&63]; ++written; } while (written&3) { if (dest) dest[written]='='; ++written; } return written; } std::string ToBase64(const ByteVector& data) { #if 0 // not using CryptBinaryToString, to be w2k compatible. DWORD dwSize= 0; if (!CryptBinaryToString(vectorptr(data), data.size(), CRYPT_STRING_BASE64, NULL, &dwSize)) { error("CryptBinaryToString"); return "ERROR"; } std::string str; str.resize(dwSize); if (!CryptBinaryToString(vectorptr(data), data.size(), CRYPT_STRING_BASE64, stringptr(str), &dwSize)) { error("CryptBinaryToString#2"); return "ERROR"; } #endif std::string str; str.resize((data.size()*8)/6+1); unsigned result= fmt_base64(stringptr(str), vectorptr(data), data.size()); str.resize(result); return str; } #ifdef _WIN32 typedef HRESULT (FAR WINAPI *fnCeProcessConfig)(LPCWSTR pszWXMLin, DWORD dwFlags, WCHAR **presult); fnCeProcessConfig CeProcessConfig; HMODULE rapiModule; #endif bool LoadRapi() { if (FAILED(CeRapiInit())) { error("CeRapiInit failed\n"); return false; } #ifdef _WIN32 rapiModule = LoadLibrary(TEXT("rapi.dll")); if (rapiModule==NULL || rapiModule==INVALID_HANDLE_VALUE) { error("LoadLibrary(rapi.dll)"); return false; } // todo: figure out why this gives a warning: // warning C4191: 'type cast' : unsafe conversion from 'FARPROC' to 'fnCeProcessConfig' CeProcessConfig= (fnCeProcessConfig)GetProcAddress(rapiModule, (LPCSTR)0x19); if (CeProcessConfig==NULL) { error("GetProcAddress"); return false; } #endif return true; } void UnloadRapi() { #ifdef _WIN32 CeProcessConfig= NULL; FreeLibrary(rapiModule); rapiModule= NULL; #endif CeRapiUninit(); } // policy handlers std::string pd_SetSecurityPolicy(DWORD dwPolicyId, DWORD dwValue) { return stringformat(" ", dwPolicyId, dwValue); } std::string pd_GetSecurityPolicy(DWORD dwPolicyId) { return stringformat(" ", dwPolicyId); } std::string pd_DeleteSecurityPolicy(DWORD dwPolicyId) { return stringformat(" ", dwPolicyId); } // certificate handlers std::string pd_LoadCertificate(const std::string& storename, DWORD dwRole, const ByteVector &certificate) { std::string sha1hex_str= CalcSha1Hex(certificate); std::string base64_str= ToBase64(certificate); return stringformat(" ", storename.c_str(), sha1hex_str.c_str(), base64_str.c_str(), dwRole); } std::string pd_QueryCertificateStore(const std::string& storename) { return stringformat(" ", storename.c_str()); } std::string pd_QueryCertificateStore(const std::string& storename, const std::string& certsha1) { return stringformat(" ", storename.c_str(), certsha1.c_str()); } std::string pd_DeleteCertificate(const std::string& storename, const std::string& sha1hex_str) { return stringformat(" ", storename.c_str(), sha1hex_str.c_str()); } // registry handlers std::string pd_DeleteRegistryValue(const std::string &key, const std::string &valname) { return stringformat(" ", key.c_str(), valname.c_str()); } std::string pd_DeleteRegistryValues(const std::string &key, StringList::const_iterator begin, StringList::const_iterator end) { std::string xml; for (StringList::const_iterator i=begin ; i!=end ; ++i) xml += stringformat("", (*i).c_str()); return stringformat(" %s ", key.c_str(), xml.c_str()); } std::string pd_DeleteRegistryKey(const std::string &key) { return stringformat(" ", key.c_str()); } std::string pd_QueryRegistryValue(const std::string &key, const std::string &valname) { return stringformat(" ", key.c_str(), valname.c_str()); } std::string pd_QueryRegistryKey(const std::string &key) { return stringformat(" ", key.c_str()); } std::string pd_SetRegistryValue(const std::string &key, const std::string &valname, const std::string &type, const std::string &value) { std::string datatype; if (!type.empty()) datatype= stringformat(" datatype=\"%s\"", type.c_str()); return stringformat(" ", key.c_str(), valname.c_str(), datatype.c_str(), value.c_str()); } std::string pd_SetRegistryInteger(const std::string &key, const std::string &valname, DWORD value) { return pd_SetRegistryValue(key, valname, "integer", stringformat("%d", value)); } std::string pd_SetRegistryString(const std::string &key, const std::string &valname, const std::string &value) { return pd_SetRegistryValue(key, valname, "string", value); } std::string pd_SetRegistryStringList(const std::string &key, const std::string &valname, const StringList &value) { return pd_SetRegistryValue(key, valname, "multiplestring", JoinStringList(value, "")+""); } // metabase handlers std::string pd_SetMetabaseKey(const std::string& key, DWORD rwaccess, DWORD role) { return stringformat(" ", key.c_str(), rwaccess, role); } std::string pd_DeleteMetabaseKey(const std::string& key) { return stringformat(" ", key.c_str()); } std::string pd_QueryMetabaseKey(const std::string& key) { return stringformat(" ", key.c_str()); } // main functions bool LoadProvisioningDoc(const std::string& xml, std::string& answer) { WCHAR *reply= NULL; HRESULT hr = CeProcessConfig(ToWString(xml).c_str(), CFGFLAG_PROCESS, &reply); if (hr) { error(uint32_t(hr), "CeProcessConfig - r=%08lx ce=%08lx le=%08lx hr=%08lx\n", reply, CeGetLastError(), GetLastError(), hr); if (reply) answer= ToString(reply); return false; } answer= ToString(reply); return true; } bool calc_cert_sha1(const std::string& certfile, std::string& sha1hex_str) { if (certfile.find('.')==std::string::npos && certfile.length()==40) { sha1hex_str= certfile; return true; } ByteVector cert; if (!get_cert_from_file(certfile, cert)) { return false; } sha1hex_str= CalcSha1Hex(cert); return true; } bool get_cert_from_file(const std::string& certfile, ByteVector& cert) { if (FindCertificate(certfile, cert)) return true; return LoadFileData(certfile, cert); // todo: // decode base64 cert ( 'PEM' encoded ) : wrapped in -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- lines }