QNetworkAccesssManager icinga / nagios acknowledge - qt

I have a function who sending ack into the icinga / nagios server.
Function - sendAcknowledge
void MNetworkConnector::sendAcknowledge(QString service, QString host)
{
QNetworkAccessManager *ackmanager;
ackmanager = new QNetworkAccessManager();
QString ackcommand = "http://nagioscore.demos.nagios.com/nagios/cgi-bin/cmd.cgi?cmd_typ=34&cmd_mod=2&host=#host#&service=#service#&com_author=nagiosadmin&com_data=Sent:+mMonitor&btnSubmit=Commit";
service = service.replace(" ", "+");
ackcommand = ackcommand.replace("#host#", host).replace("#service#", service);
connect(ackmanager, SIGNAL(finished(QNetworkReply*)),this, SLOT(replyFinished2(QNetworkReply*)));
QNetworkRequest myReq;
QUrl myUrl(ackcommand);
myUrl.setUserName("nagiosadmin");
myUrl.setPassword("nagiosadmin");
myReq.setUrl(myUrl);
myReq.setRawHeader("Referer", "http://nagioscore.demos.nagios.com/nagios/cgi-bin/cmd.cgi");
ackmanager->get(myReq);
}
Function - replyFinished2
void MNetworkConnector::replyFinished2(QNetworkReply *r)
{
qDebug() << "reply output:" << r->readAll();
}
System returned several errors.
If I test this source on my corporate icinga server, I have error:
Not all commands could be send off successfully - Not Authorized
If I test it manualy on my corporate icinga server, I have error: Error: This appears to be a CSRF attack! The command wasn't issued via Classic-UI itself!
If I test it manualy on nagios test site, I have no error. Set service ack is Ok.
If I test this source I have error:Sorry, but you are not authorized to commit the specified command.
What's wrong? Thank you for all your ideas. At first I need solved problem in Icinga, the nagios test page I used only as alternative tests.

When the website requests authentication QNetworkAccessManager will emit the authenticationRequired() signal. Try connecting the signal with a slot and then set the username and password on the QAuthenticator object passed as argument to the slot.
Connection:
connect(ackmanager, SIGNAL(authenticationRequired(QNetworkReply *, QAuthenticator *)), this, SLOT(authenticationRequired(QNetworkReply *, QAuthenticator *)));
Slot:
void MNetworkConnector::authenticationRequired(QNetworkReply *r, QAuthenticator *authenticator)
{
authenticator->setUser("nagiosadmin");
authenticator->setPassword("nagiosadmin");
}

The problem was sensitive to uppercase and lowercase letters in the HOST.

Related

How could I make grpc server do other work when there is no client calls?

I have a simple function that is served with grpc, the starting method of this service is like this:
void start_server() {
string addr("0.0.0.0:50002");
ImageServiceImpl service;
ServerBuilder builder;
builder.AddListeningPort(addr, grpc::InsecureServerCredentials());
builder.RegisterService(&service);
builder.SetMaxSendMessageSize(1L << 31);
builder.SetMaxReceiveMessageSize(1L << 31);
std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
std::cout << "service started, listening to: " << addr << std::endl;
server->Wait();
}
It is a standard grpc server. My problem is that, I need the server to execute other programs when there is no client request called. And when a client request comes, the server program would be 'interrupted' and the server will deal with the request. After dealing with the request, the server continues executing its 'leisure time' program. The problem is that the program would block at the server->Wait(), thus when there is not client request comes, the server can do nothing but wait, which is not what I need it to do.
I hope I have expressed myself clearly. How could I do this with grpc ?
Does running a thread before server->Wait() not solve this problem?
On .NET C #, I solved it like this:
...
// Start other work
MainTask mainTask = new MainTask(configurator, _gRPCManager);
Thread mainThread = new Thread(mainTask.Run);
mainThread.IsBackground = true;
mainThread.Start();
// Start gRPS
CreateHostBuilder(args, configurator).Build().Run();

Qt 5.8 Apple Notification Server Handshake failed

i tried it some ours now but i could not get it to work. I want to push some notifications from a Qt Application. Tried to get it to work on macOS Sierra with Qt 5.8 installation and on Pi3 also with Qt 5.8.
I created my push certificate with "fastlane pem" and i tested it with "Pusher" and it works correct. But i cannot get it to work in Qt....
At first is the code i use to initialize and connect the QSslSocket:
QSslSocket * ssl = new QSslSocket;
connect(ssl, &QSslSocket::encrypted, this, &IOSPusher::encrypted );
connect(ssl, static_cast<void(QSslSocket::*)(const QList<QSslError> &)>(&QSslSocket::sslErrors),this,&IOSPusher::sslErrors);
connect(ssl, static_cast<void(QSslSocket::*)(QAbstractSocket::SocketError)>(&QSslSocket::error),this, &IOSPusher::error );
connect(ssl,&QSslSocket::stateChanged,this,&IOSPusher::stateChanged );
Loading the certificate
QString path = QStandardPaths::writableLocation(certificateLocation) + "/apns.pem";
const auto certs = QSslCertificate::fromPath(path);
if(certs.count() > 0){
qDebug() << "IOSPusher: Certificate loaded successfully";
}else{
qDebug() << "Could not load certificate : " + path;
}
QSslConfiguration config = QSslConfiguration::defaultConfiguration();
config.setCaCertificates(certs);
ssl->setSslConfiguration(config);
ssl->connectToHostEncrypted( gateway.sandbox.push.apple.com,2195 );
And thats the output i get:
IOSPusher: Certificate loaded successfully
IOSPusher::stateChanged QAbstractSocket::HostLookupState
IOSPusher::stateChanged QAbstractSocket::ConnectingState
IOSPusher::stateChanged QAbstractSocket::ConnectedState
IOSPusher::error QAbstractSocket::SocketError(13)
IOSPusher::stateChanged QAbstractSocket::ClosingState
IOSPusher::stateChanged QAbstractSocket::UnconnectedState
So according to the Qt documentation the error:
QAbstractSocket::SocketError(13)
means the following:
SslHandshakeFailedError
And
> the SSL/TLS handshake failed and the encrypted channel could not be established. The sslErrors() signal should have been emitted.
But the sslErrors() signal will not be emitted in my case....
The SSL/TLS handshake failed, so the connection was closed (only used in QSslSocket)
Any ideas or samples how i can establish a encrypted connection to apple?
Thanks in advance!
Okay like so often when i try to get help from anyone i got it now :D
The solution which worked for me now is:
Create the *.pem cert with fastlane pem with a password (maybe it works without password too but that was the last i tried now and....never change a running system haha)
fastlane pem --development -p <private_key_password> -a <your_app_identifier>
Then to connect with the QSslSocket do the following... as before in my question...
QSslSocket * ssl = new QSslSocket;
QString path = QStandardPaths::writableLocation(certificateLocation) + "/apns.pem";
connect(ssl, &QSslSocket::encrypted, this, &IOSPusher::encrypted );
connect(ssl, static_cast<void(QSslSocket::*)(const QList<QSslError> &)>(&QSslSocket::sslErrors),this,&IOSPusher::sslErrors);
connect(ssl, static_cast<void(QSslSocket::*)(QAbstractSocket::SocketError)>(&QSslSocket::error),this, &IOSPusher::error );
connect(ssl,&QSslSocket::stateChanged,this,&IOSPusher::stateChanged );
QSslCertificate cert;
const auto certs = QSslCertificate::fromPath(path);
if(certs.count() > 0){
cert = certs.at(0);
qDebug() << "IOSPusher: Certificate loaded successfully";
}else{
qDebug() << "Could not load certificate : " + path;
return false;
}
Now here comes the magic what it did for me
Use the private_key (.pkey) file which will also be created with fastlane pem
//Use the path to the .pkey file from fastlane
QFile keyfile(path + "/apns.pkey");
keyfile.open(QFile::ReadOnly);
//Create the QSslKey as private key
QSslKey privateKey(&keyfile,QSsl::Rsa,QSsl::Pem,QSsl::PrivateKey,QByteArray("<private_key_password_from_fastlane>"));
//Close the file
keyfile.close();
And add the private key and the certificate to the ssl config
QSslConfiguration config = QSslConfiguration::defaultConfiguration();
config.setLocalCertificate(cert);
config.setPrivateKey(privateKey);
as you can see here this time i not use the config.setCaCertificates method but instead the config.setLocalCertificate method. That was a mistake on my side...
At least add the config to the ssl socket and FIRE!
ssl->setSslConfiguration(config);
ssl->connectToHostEncrypted( "gateway.sandbox.push.apple.com",2195 );
Thats all
Now the encrypted() signal gets emitted! Yeah..

QNetworkReply error signal not detected when connection is lost

I'm downloading files from a remote server with Qt5.5 and everything works fine but I can't detect when a QNetworkReply returns an error.
In fact, I am trying to check the case if the user is downloading a file and suddenly, he loses his Internet connection (because why not :-) ). To do that, I start a download and unplug my Ethernet cable a few seconds after.
Is the signal QNetworkReply::error(QNetworkReply::NetworkError) emitted in this case? If yes, why am I not entering my slot in my code below?
void MyClass::download(QUrl url)
{
QNetworkRequest request = QNetworkRequest(url);
QNetworkReply *reply = pManager.get(request);
// finished() is called after error(), but try both
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(requestError(QNetworkReply::NetworkError)));
connect(reply, SIGNAL(finished()), this, SLOT(requestFinished()));
}
void MyClass::requestError(QNetworkReply::NetworkError err)
{
qDebug() << "error";
}
void MyClass::requestFinished()
{
qDebug() << "finished";
}
I also connected the access manager like this :
connect(&pManager, SIGNAL(finished(QNetworkReply*)), SLOT(requestFinished(QNetworkReply*)));
When the Internet connection is not interrupted, I am going in the slot requestFinished(), but if there's not Internet anymore, I am not entering any slot.
Am I doing something wrong?
Ok, nevermind, I was doing it wrong. Since I want to check the internet connection, I have to check the network availability via QNetworkAccessManager, by doing this :
QNetworkConfigurationManager manager;
pManager.setConfiguration(manager.defaultConfiguration());
connect(&pManager, SIGNAL(networkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility)), this, SLOT(networkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility)));
And when the Internet breaks down, I will be in the corresponding slot.

QNetworkReply error "Connection closed" when getting a simple URL

I'm trying to make a simple file downloader. Here is my code segment for downloading a URL; This code works fine, if I try to get simple URLs like "http://stackoverflow.com".
But when I specify URLs which redirects, it throws an error saying "Connection closed".
//Sets a sample URL which redirects.
QString url = "http://downloads.sourceforge.net/project/gretl/gretl/1.9.92/gretl-1.9.92.tar.xz"
QNetworkAccessManager * networkAccessManager = new QNetworkAccessManager(this);
QNetworkRequest * networkRequest = new QNetworkRequest(QUrl(url));
//Getting the URL
QNetworkReply * networkReply = networkAccessManager->get(*networkRequest);
Additionally I've connected the following signal-slot to recognize network errors:
//Connects networkReply object's error signal to a slot which prints the error.
connect(networkReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(printError(QNetworkReply::NetworkError)));
Here is the slot which prints errors if networkReply's error signal is emitted:
void printError(QNetworkReply::NetworkError code)
{
qDebug() << "Network Error Code: " << code;
qDebug() << networkReply->errorString();
}
Because of this error, networkReply object never receives any header.
My need is to read the HTTP status code by this method: QNetworkReply::attribute(QNetworkRequest::HttpStatusCodeAttribute)
I can't read the HTTP Status code, because I don't get the headers.
Can anyone say whats going on?
Thanks in advance! :)
Here and here are good examples of handling this scenario - basically you add a slot for finished signal, then check the HTTP status code for 301 and/or QNetworkRequest::RedirectionTargetAttribute attribute to see if you are being redirected and if so issue a new request for the redirect link.

Reading HTTP headers

I am trying to connect my application with a web service and here ,a user suggested to send custom headers back to my application.
I am using this code
void Coonnec::serviceRequestFinished(QNetworkReply *reply)
{
QByteArray bytes = reply->readAll();
if (reply->error() != QNetworkReply::NoError) {
qDebug() << "Reply error: " + reply->errorString();
}
else
{
qDebug() << "Uploaded: " + QDateTime::currentDateTime().toString();
qDebug() << reply->rawHeaderList();
}
reply->close();
bytes.clear();
reply->deleteLater();
}
from php i send this header
header('XAppRequest-Status: complete');
When running the application i can see that i get this header but i can't take the value of it cause
reply->rawHeader(bytes);
returns nothing.
How can i take the value 'complete'?
I suggest to connect a slot to the void QNetworkReply::metaDataChanged () signal of your reply.
The Qt doc says
This signal is emitted whenever the metadata in this reply changes.
metadata is any information that is not the content (data) itself,
including the network headers. In the majority of cases, the metadata
will be known fully by the time the first byte of data is received.
However, it is possible to receive updates of headers or other
metadata during the processing of the data.
I do use web-services/client with Qt and I noticed that some header's information are not available when I expected it to be ! I had to 'wait' for this signal to check the header content.

Resources