/* (C) 2003-2007 Willem Jan Hengeveld * Web: http://www.xs4all.nl/~itsme/ * http://wiki.xda-developers.com/ * * $Id: prapi.cpp 1749 2008-03-11 17:12:13Z itsme $ */ #include #include "debug.h" #include #include "stringutils.h" #include "args.h" #include "filefunctions.h" // 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. // enum CertifiateStore { CERTSTORE_PRIVILEGED, // for privileged apps (OEM_CERTIFY_TRUST) CERTSTORE_UNPRIVILEGED, // for un-privileged apps (OEM_CERTIFY_RUN) CERTSTORE_SPC, // for signed cabs CERTSTORE_CA, // browser certificate authorities CERTSTORE_ROOT, // browser root certificates CERTSTORE_MY, // my browser certificates }; const char* storenames[]= { "Privileged Execution Trust Authorities", "Unprivileged Execution Trust Authorities", "SPC", "CA", "Root", "MY", }; #define CFGFLAG_PROCESS 0x0001 #define CFGFLAG_METADATA 0x0002 bool CalcSha1(const ByteVector& data, ByteVector &hash) { 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; } 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); int result= fmt_base64(stringptr(str), vectorptr(data), data.size()); str.resize(result); return str; } typedef HRESULT (WINAPI *fnCeProcessConfig)(LPCWSTR pszWXMLin, DWORD dwFlags, WCHAR **presult); fnCeProcessConfig CeProcessConfig; HMODULE rapiModule; bool LoadRapi() { if (FAILED(CeRapiInit())) { error("CeRapiInit failed\n"); return false; } rapiModule = LoadLibrary(TEXT("rapi.dll")); if (rapiModule==NULL || rapiModule==INVALID_HANDLE_VALUE) { error("LoadLibrary(rapi.dll)"); return false; } CeProcessConfig= (fnCeProcessConfig)GetProcAddress(rapiModule, (LPCSTR)0x19); if (CeProcessConfig==NULL) { error("GetProcAddress"); return false; } return true; } void UnloadRapi() { CeProcessConfig= NULL; FreeLibrary(rapiModule); rapiModule= NULL; 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(hr, "CeProcessConfig - r=%08lx ce=%08lx le=%08lx hr=%08lx\n", reply, CeGetLastError(), GetLastError(), hr); printf("%ls\n", 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 (!LoadFileData(certfile, cert)) { return false; } sha1hex_str= CalcSha1Hex(cert); return true; } void usage() { printf("(C) 2003-2008 Willem jan Hengeveld itsme@xs4all.nl\n"); debug("Usage: prapi [-q|-d] [-p | -s | -c | -m] \n"); debug(" -q -p : query policy setting\n"); debug(" -p : set policy\n"); debug(" -d -p : delete policy setting\n"); debug(" -q -m : query metabase key\n"); debug(" -m [-r role] [-a access] : set metabase key\n"); debug(" -d -m : delete metabase key\n"); debug(" -q [] : query registry key or value\n"); debug(" -s : set registry key\n"); debug(" -d [] : delete registry key or value\n"); debug(" -q -c[STORE] [file.cer] : query certificate, whole store, or one cert\n"); debug(" -c[STORE] [-r role] : add certificate to store\n"); debug(" -d -c[STORE] : delete certificate from store\n"); debug("Stores: codesigning: p=privileged, u=unprivileged, c=SPC/cabsigning\n"); debug(" ssl/webserver: a=Certificate Authorities, r=root, m=my\n"); } int main(int argc, char **argv) { DebugStdOut(); bool bPrintAnswer= false; bool doSetSecurityPolicy= false; bool doSetRegistryValue= false; bool doSetMetabase= false; bool doDelete= false; bool doQuery= false; bool doLoadCertificate= false; DWORD dwCertStore= 0; DWORD role=0; DWORD rwaccess=3; StringList args; for (int i=1 ; i=2) xml= pd_DeleteRegistryValues(args[0], args.begin()+1, args.end()); else { usage(); return 1; } } else { usage(); return 1; } if (!LoadRapi()) return 1; if (xml.empty()) { printf("error - no query selected\n"); usage(); return 1; } std::string answer; if (!LoadProvisioningDoc(xml, answer)) { UnloadRapi(); return 1; } if (bPrintAnswer) { for (size_t i=answer.find("><") ; i!=answer.npos ; i= answer.find("><", i+1)) answer.replace(i, 2, ">\n<"); // .. don't use debug here, it truncates at 16K fputs(answer.c_str(), stdout); } UnloadRapi(); return 0; }