GRPC CreateChannel() error Could not get default pem root certs - c++

I am using grpc 1.35.0 on Windows 10 and following sample code here to create a grpc channel for client to use. But I have a provide a root cert to create the channel, otherwise it complains below error.
Then I write my client in a python version and I can create the channel without giving root cert.
So, is this a grpc bug or I misunderstand the sample code?
GRPC sample code
// Create a default SSL ChannelCredentials object.
auto channel_creds = grpc::SslCredentials(grpc::SslCredentialsOptions());
// Create a channel using the credentials created in the previous step.
auto channel = grpc::CreateChannel(server_name, channel_creds);
// Create a stub on the channel.
std::unique_ptr<Greeter::Stub> stub(Greeter::NewStub(channel));
// Make actual RPC calls on the stub.
grpc::Status s = stub->sayHello(&context, *request, response);
my code
const std::string SECURE_GRPC_CHANNEL_ADDRESS = <MY_SERVER>;
class GrpcChannel
{
GrpcChannel()
{
auto ca_cert = get_file_contents(cacert_path);
SslCredentialsOptions options = { ca_cert, "", "" };
auto channel_creds = SslCredentials(options);
channel_ = grpc::CreateChannel(SECURE_GRPC_CHANNEL_ADDRESS, channel_creds);
}

Turns out it's grpc document issue, grpc-core C++ for windows does not support default root cert and need specify one by user. Please refer to here.

Related

How to use libmosquitto to make a request and get response using MQTT v5?

I'm trying to use libmosquitto to make a request (publish to a 'test/topic' topic) and I want to get a response based on the client (sender) id. So that means the client will publish to 'test/topic' and it will automatically subscribe 'test/topic/<client_id>'
The server has already subscribed on 'test/topic' and when it becomes the message, it will send a response (publish) to 'test/topic/<client_id>', which the client subscribed to receive that response in the first place.
The challenge here is how do I get the <client_id>, right. I already done this in python and js, where the client will send metadata or properties in the payload, which the server can unpack to get the client_id. However, I'm using C++ now and it's frustrating because I can't figure out how to get these properties.
Here is an example of how to do this in python. I just want to do the same with c++
I'm using the libmosquitto as I mentionned. I don't even have an example to show because I didn't find how to do this. There is literally no example on how to do this with the mosquitto c++ lib (which is confusing since mosquitto is a famous lib I guess).
I hope someone had a similar problem or can post an example for c++ and mosquitto lib. Thanks in advance.
When in doubt, look at the tests:
const char *my_client_id = ...;
mosquitto_property *proplist = NULL;
mosquitto_property_add_string_pair(&proplist, MQTT_PROP_USER_PROPERTY, "client_id", my_client_id);
mosquitto_publish_v5(mosq, &sent_mid, "test/topic", strlen("message"), "message", 0, false, proplist);
mosquitto_property_free_all(&proplist);
Since you asked in the comments, you can retrieve these properties from published messages by first setting an on_message callback using mosquitto_message_v5_callback_set and the implementing it like so:
void on_message(struct mosquitto *mosq, void *obj, const struct mosquitto_message *message, const mosquitto_property *props) {
std::string topic{message->topic};
if (topic == "test/topic") {
const char *client_id = nullptr;
mosquitto_property_read_string_pair(props, MQTT_PROP_USER_PROPERTY, nullptr, &client_id, false);
if (client_id) {
/* client_id contains a client id. */
}
}

WebView2 proxy C++

I found this thread on GitHub, but seems that the code is not C++:
WebView2 _webView2 = new WebView2();
CoreWebView2EnvironmentOptions options = new CoreWebView2EnvironmentOptions();
// Set a proxy pac for the browser
// options.AdditionalBrowserArguments = "--proxy-pac-url=http://myproxy.com/my.pac";
// Set the proxy for the browser
options.AdditionalBrowserArguments = "--proxy-server=\"foopy:99\"";
// Create the environment manually
CoreWebView2Environment env = await CoreWebView2Environment.CreateAsync(null, null, options);
await _webView2 .EnsureCoreWebView2Async(env);
So the only what am I asking for is to provide the solution for setting up a proxy for WebView2 via C++.
I have ICoreWebView2 interface, but it doesn’t have EnsureCoreWebView2Async method. In another hand, I have CoreWebView2EnvironmentOptions class.
auto opt = Microsoft::WRL::Make<CoreWebView2EnvironmentOptions>();
opt->put_AdditionalBrowserArguments(L"--proxy-server=\"SERVER\"");
CreateCoreWebView2EnvironmentWithOptions(nullptr, nullptr, opt.Get(), Microsoft::WRL::Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(
[hwnd](HRESULT result, ICoreWebView2Environment* env) -> HRESULT {
...
}).Get());
Instead of SERVER put ip address or something else.
I tested, it works, but seems there is a bug (or feature): you can’t create two or more webviews with different run-arguments.
To those looking to specify webview environment options and cannot find CoreWebView2EnvironmentOptions in C++ similar to what is available in .Net. Visit documentation page for ICoreWebView2EnvironmentOptions and you should find this line:
A default implementation is provided in WebView2EnvironmentOptions.h
Include WebView2EnvironmentOptions.h and create CoreWebView2EnvironmentOptions as below
#include <WebView2EnvironmentOptions.h>
auto options = Microsoft::WRL::Make<CoreWebView2EnvironmentOptions>();
// Use options however you want. I simply added an argument to autoplay videos.
options->put_AdditionalBrowserArguments(L"--autoplay-policy=no-user-gesture-required");
HRESULT hr = CreateCoreWebView2EnvironmentWithOptions(
subFolder, m_userDataFolder.c_str(), options.Get(),
Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(
this, &AppWindow::OnCreateEnvironmentCompleted)
.Get());

ApplyChangeFailed does not fired on conflict

I'm trying to sync two SQL Server DBs by following Microsoft example from here Synchronizing SQL Server and SQL Express and the basic sync is working for me.
Now, I tried to create a conflict by changing the same row on both DB to different values but when I run my sync process the ApplyChangeFailed is not fired.
I read this question Microsoft Sync Framework Conflict Event does not fire but I don't understand why when I sync client<->server configuration the framework ignore conflicts.
Here is my code, just for reference, I have a remote SQL 2008 R2 Server as the server and a local SQL 2012 Express as the client:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using Microsoft.Synchronization;
using Microsoft.Synchronization.Data;
using Microsoft.Synchronization.Data.SqlServer;
using Microsoft.Synchronization.Data.SqlServerCe;
namespace ExecuteExpressSync
{
class Program
{
static void Main(string[] args)
{
SqlConnection clientConn = new SqlConnection(#"Data Source=.\SQLEXPRESS; Initial Catalog=SyncExpressDB; Trusted_Connection=Yes");
SqlConnection serverConn = new SqlConnection("Data Source=X.Y.Z.W; Initial Catalog=SyncDB; uid=sa;password=******;Integrated Security=False");
// create the sync orhcestrator
SyncOrchestrator syncOrchestrator = new SyncOrchestrator();
// set local provider of orchestrator to a sync provider associated with the
// ProductsScope in the SyncExpressDB express client database
syncOrchestrator.LocalProvider = new SqlSyncProvider("ProductsScope", clientConn);
// set the remote provider of orchestrator to a server sync provider associated with
// the ProductsScope in the SyncDB server database
syncOrchestrator.RemoteProvider = new SqlSyncProvider("ProductsScope", serverConn);
// set the direction of sync session to Upload and Download
syncOrchestrator.Direction = SyncDirectionOrder.UploadAndDownload;
// subscribe for errors that occur when applying changes to the client
((SqlSyncProvider)syncOrchestrator.LocalProvider).ApplyChangeFailed += new EventHandler<DbApplyChangeFailedEventArgs>(Program_ApplyChangeFailed);
// execute the synchronization process
SyncOperationStatistics syncStats = syncOrchestrator.Synchronize();
// print statistics
Console.WriteLine("Start Time: " + syncStats.SyncStartTime);
Console.WriteLine("Total Changes Uploaded: " + syncStats.UploadChangesTotal);
Console.WriteLine("Total Changes Downloaded: " + syncStats.DownloadChangesTotal);
Console.WriteLine("Complete Time: " + syncStats.SyncEndTime);
Console.WriteLine(String.Empty);
}
static void Program_ApplyChangeFailed(object sender, DbApplyChangeFailedEventArgs e)
{
// display conflict type
Console.WriteLine(e.Conflict.Type);
// display error message
Console.WriteLine(e.Error);
}
}
}
As #JuneT notes this line is missing:
// subscribe for errors that occur when applying changes to the client
((SqlSyncProvider)syncOrchestrator.RemoteProvider).ApplyChangeFailed += new EventHandler<DbApplyChangeFailedEventArgs>(Program_ApplyChangeFailed);

Java API for Informatica

I am trying to use Java API to connect with informatica. I am tyring to run the samples at location
C:\Program Files\Informatica\PowerCenter8.6.1\MappingSDK\samples\src\com\informatica\powercenter\sdk\mapfwk\samples which uses com.informatica.powercenter.sdk.mapfwk.core.* libraries.
When I try to run CreateConnectionSample.java(simple connection to repository) I am getting exception.
code:
CachedRepositoryConnectionManager rpMgr = new CachedRepositoryConnectionManager(
new PmrepRepositoryConnectionManager());
Repository rep = new Repository();
RepoProperties repoProp = new RepoProperties();
repoProp.setProperty(RepoPropsConstant.PC_CLIENT_INSTALL_PATH,
"C:\\Program Files\\Informatica\\PowerCenter8.6.1\\client\\bin");
repoProp.setProperty(RepoPropsConstant.TARGET_REPO_NAME, "EDW_DEV_REPO");
repoProp.setProperty(RepoPropsConstant.REPO_SERVER_DOMAIN_NAME, "DOM_GWM_DEV01");
repoProp.setProperty(RepoPropsConstant.SECURITY_DOMAIN, "MSSB_INFA_DVLPR_DEV");
repoProp.setProperty(RepoPropsConstant.ADMIN_USERNAME, "Username");
repoProp.setProperty(RepoPropsConstant.ADMIN_PASSWORD, "Password");
repoProp.setProperty(RepoPropsConstant.TARGET_FOLDER_NAME,"CORE");
rep.setProperties(repoProp);
rep.setRepositoryConnectionManager(rpMgr);
ConnectionObject connObj = new ConnectionObject("Con", ConnectionAttributes.CONN_TYPE_RELATION);
rep.createConnection(connObj);
I am getting exception
com.informatica.powercenter.sdk.mapfwk.exceptions.ConnectionFailedException: Failed to list connections in PowerCenter Repository
Have anyone done this earlier? Can anyone help me to setup the Java API.
Well, this is really old, and hopefully you ended up getting connected using the SDK. Here's some recent code I put together to get a connection and query some stuff about workflows.
public static void main(String[] args) throws Exception {
if(System.getenv("INFA_DOMAINS_FILE") == null) // make sure .infa file exists
throw new Exception("INFA_DOMAINS_FILE path not set in environment variables.");
Repository rep = new Repository();
RepoConnectionInfo rci = new RepoConnectionInfo();
rci.setRepoServerHost("your host DNS name"); // set host URI
rci.setRepoServerPort("your host port number"); // host port
rci.setRepoServerDomainName("your-domain-name"); // repository domain name
rci.setTargetRepoName("your-repository"); // repository
rci.setSecurityDomain("e-directory"); // security type
rci.setAdminUsername("your-credentials"); // uid
rci.setAdminPassword(getPassword()); // pwd (stored in environment variable -- encoded so it's not cleartext)
rci.setPmrepCacheFolder("c:\\users\\your-credentials\\Informatica\\"); // some cache folder that must be set
rci.setPcClientInstallPath("C:\\Informatica\\9.0.1\\clients\\PowerCenterClient\\client\\bin\\");
rep.setRepoConnectionInfo(rci); // provide connection info to rep object
RepositoryConnectionManager repmgr = new PmrepRepositoryConnectionManager(); // set up repository connection manager
rep.setRepositoryConnectionManager(repmgr); // tell repository to use connection manager
System.out.println("Folders:");
System.out.println("===========================================================================");
List<Folder> folders = rep.getFolders();
for(Folder f: folders) { System.out.println(f);}
}

How do I duplicate certificate authentication (Mumble (c/c++)) in Python?

Alright so, before I really get into this post, I am going to have to warn you that this might not be an easy fix. Whoever reads and is able to reply to this post must know a lot of c/c++, and at least some python to be able to answer the question I have above.
Basically, I have a connection method from Mumble (a VOIP client), that connects to a server and sends it an SSL certificate for authentication purposes. I also have a Python script that connects to the same Mumble VOIP server, but I don't send a certificate.
I need to modify my existing code to send a certificate, as the current Mumble client does.
--
Here is the C++ code that seems to send a certificate:
ServerHandler::ServerHandler() {
MumbleSSL::addSystemCA();
{
QList<QSslCipher> pref;
foreach(QSslCipher c, QSslSocket::defaultCiphers()) {
if (c.usedBits() < 128)
continue;
pref << c;
}
if (pref.isEmpty())
qFatal("No ciphers of at least 128 bit found");
QSslSocket::setDefaultCiphers(pref);
}
void ServerHandler::run() {
qbaDigest = QByteArray();
QSslSocket *qtsSock = new QSslSocket(this);
qtsSock->setPrivateKey(g.s.kpCertificate.second);
qtsSock->setLocalCertificate(g.s.kpCertificate.first.at(0));
QList<QSslCertificate> certs = qtsSock->caCertificates();
certs << g.s.kpCertificate.first;
qtsSock->setCaCertificates(certs);
cConnection = ConnectionPtr(new Connection(this, qtsSock));
qtsSock->setProtocol(QSsl::TlsV1);
qtsSock->connectToHostEncrypted(qsHostName, usPort);
void ServerHandler::serverConnectionConnected() {
tConnectionTimeoutTimer->stop();
qscCert = cConnection->peerCertificateChain();
qscCipher = cConnection->sessionCipher();
if (! qscCert.isEmpty()) {
const QSslCertificate &qsc = qscCert.last();
qbaDigest = sha1(qsc.publicKey().toDer());
bUdp = Database::getUdp(qbaDigest);
} else {
bUdp = true;
}
QStringList tokens = Database::getTokens(qbaDigest);
foreach(const QString &qs, tokens)
mpa.add_tokens(u8(qs));
QMap<int, CELTCodec *>::const_iterator i;
for (i=g.qmCodecs.constBegin(); i != g.qmCodecs.constEnd(); ++i)
mpa.add_celt_versions(i.key());
sendMessage(mpa);
--
And alas, this is what I do to connect to it right now (in python):
try:
self.socket.connect(self.host)
except:
print self.threadName,"Couldn't connect to server"
return
self.socket.setblocking(0)
print self.threadName,"connected to server"
--
Soo... what do I need to do more to my Python source to connect to servers that require a certificate? Because my source currently connects just fine to any mumble server with requirecert set to false. I need it to work on all servers, as this will be used on my own server (which ironically enough, has requirecerts on.)
I can pregenerate the certificate as a .p12 or w/e type file, so I don't need the program to generate the cert. I just need it to send the cert as the server wants it (as is done in the c++ I posted).
Please help me really soon! If you need more info, message me again.
Stripped out all irrelevant code, now it's just the code that deals with ssl.
From the C++ code it looks like you simply need to have ssl support and negotiate with the correct certification file and encrypt the payload with the correct private key. Those certifications and privates keys are most likely stored in your original program somewhere. If there are non-standard Authorities that the C++ might be loading up you'll need to find out where to put those root authorities in your python installation, or make sure python simply ignores those issues, which is less secure.
In python you can create a socket, like above, except with urllib. This library has support for HTTPs and providing the certification and private keys. URLOpener
Example Usage:
opener = urllib.URLopener(key_file = 'mykey.key', cert_file = 'mycert.cer')
self.socket = opener.open(url)
You'll probably need to make it more robust with the appropriate error checking and such, but hopefully this info will help you out.