How would I create a HTTPS request in vala? - vala

I am trying to create a github issue app in vala and need to get the list of issues from https://api.github.com/repos/vmg/redcarpet/issues?state=closed.
I have tried using this example in my code but this is not working for SSL.
https://wiki.gnome.org/Projects/Vala/GIONetworkingSample
I have also tried soup but this seems to have a problem where it can't find its dev headers.
Any help would be much appreciated.

You have to set the tls property to true on the SocketClient object, and
you have to connect to the correct port (443). This works for me:
var client = new SocketClient() { tls = true };
// Or do this (does the same):
// var client = new SocketClient();
// client.tls = true;
var socket = client.connect_to_host (hostname, 443);
If the server you are connecting to are using a self-signed certificate,
you also have to change the TLS validation flags:
client.set_tls_validation_flags (...);
But it's probably easier with Soup, as another commenter pointed out.
God luck. Vala is a sweet language.

Related

Filtering requests by header - GunDB

So, basically I would like to filter the requests between nodes using some kind of security. I think a simple static token access based scenario is enough. The idea is to not let anyone to just connect and consult sensitive data. I already tried this solution, but I think it's outdated: JWT authentication with gundb.
Really appreciate some help :)
OBS: Im using the latest version of gundb. My server is the nodejs vanilla. Here's my code, but I dont know if it helps
const GUN = require('gun');
var listOfPeers = ["http://localhost:8081/gun"];
const server = require('http').createServer().listen(8080);
const gun = GUN({web: server, peers: listOfPeers});
gun.get("poems/2").put({foo: "bar"})

How can I make a TLS connection using Vala?

I'm trying to figure out how can I make a proper TLS connection using Gio. The Gio documentation says you can create a TLS connection just by setting the tls flag on the SocketClient. Below is a Gio networking sample from the gnome wiki. When I set the tls flag, the TLS layer is configured automatically but validating the certificates fails unless I skip the validation.
Do I have to validate certificates myself or is GLib supposed to do the validation? Can somebody provide a full example on how to use TLS in Vala?
var host = "developer.gnome.org";
try {
// Resolve hostname to IP address
var resolver = Resolver.get_default ();
var addresses = resolver.lookup_by_name (host, null);
var address = addresses.nth_data (0);
print (#"Resolved $host to $address\n");
// Connect
var client = new SocketClient ();
client.set_tls(true);
// skips certificate validation
client.set_tls_validation_flags( 0 );
var conn = client.connect (new InetSocketAddress (address, 443));
print (#"Connected to $host\n");
// Send HTTP GET request
var message = #"GET / HTTP/1.1\r\nHost: $host\r\n\r\n";
conn.output_stream.write (message.data);
print ("Wrote request\n");
// Receive response
var response = new DataInputStream (conn.input_stream);
var status_line = response.read_line (null).strip ();
print ("Received status line: %s\n", status_line);
} catch (Error e) {
stderr.printf ("%s\n", e.message);
}
And another thing I want to ask is; when I run the code above I get this output:
Resolved developer.gnome.org to 8.43.85.14
Connected to developer.gnome.org
Wrote request
Received status line: HTTP/1.1 200 OK
But when I try to connect 'developer.mozilla.org', I'm getting the following error:
Resolved developer.mozilla.org to 54.192.235.2
Error performing TLS handshake: A packet with illegal or unsupported version was received.
Can anybody tell me the reason why I am getting this error? (By the way the version of GLib installed on my system is 2.64.6)
What you're doing so far is mostly correct, but you will probably want to do a little bit more to handle potential certificate errors during the TLS handshaking (see below).
Do I have to validate certificates myself or is GLib supposed to do the validation?
Note that SocketClient.set_tls_validation_flags is deprecated. To handle validation errors you can connect to the accept_certificate signal on the TlsClientConnection prior to handshaking:
var client = new SocketClient ();
client.set_tls(true);
client.event.connect ((SocketClientEvent event, SocketConnectable connectable, IOStream? connection) => {
if (event == SocketClientEvent.TLS_HANDSHAKING) {
((TlsClientConnection) connection).accept_certificate.connect ((peer_cert, errors) => {
// Return true to accept, false to reject
});
}
});
The errors are GLib.TlsCertificateFlags, so you'll want to determine which (if any) are acceptable. Ideally if there are any errors you would reject the certificate altogether, but if you want to allow self-signed certificates for example, that is possible this way.
You can simply check against the flags to see which ones are included in the errors:
TlsCertificateFlags[] flags = new TlsCertificateFlags[] {
TlsCertificateFlags.BAD_IDENTITY,
TlsCertificateFlags.EXPIRED,
TlsCertificateFlags.GENERIC_ERROR,
TlsCertificateFlags.INSECURE,
TlsCertificateFlags.NOT_ACTIVATED,
TlsCertificateFlags.REVOKED,
TlsCertificateFlags.UNKNOWN_CA
};
foreach (var flag in flags) {
if ((errors & flag) != 0) {
// The flag was included in the errors - respond accordingly
}
}
But when I try to connect 'developer.mozilla.org', I'm getting the
following error:
Resolved developer.mozilla.org to 54.192.235.2 Error performing TLS
handshake: A packet with illegal or unsupported version was received.
Can anybody tell me the reason why I am getting this error? (By the
way the version of GLib installed on my system is 2.64.6)
This is probably due to developer.mozilla.org using an old implementation of TLS (probably 1.0 or 1.1). These were disabled in GLib networking as of 2.64.x according to this bug report: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=954742
They may have upgraded to TLS 1.2 since you posted this question - I just did a quick test and connected using TLSv1.2 successfully.
Try run the program with export G_MESSAGES_DEBUG=all for full debug messages.
Also, for a full working example of code that uses TLS written in Vala via GIO, check out the code for this Gemini browser: https://github.com/koyuspace/fossil/blob/main/src/util/connection_helper.vala
I hope that this is somewhat useful to you.

what is MQTT url to my thingsboard instance

I have a thingsboard UI available at "thingsboard.MYDOMAIN.io:8080". I'm using NodeJS and MQTT.js. I can connect using the sample code on that page. But I don't know what URL i would use in that connect string. I've tried using that URL and putting MQTT:// on the front of it to no avail.
It's just one device coming into a thingsboard. I wouldn't think i would need to add anything other than the default thingsboard.
If someone could tell what the expect default URL would be?
The default MQTT port number is 1883 so something like
mqtt://thingsboard.mydomain.io:1883
would be a good starting point. You should even be able to leave the port number off e.g.
mqtt://thingsboard.mydomain.io
Connection code should be something like this:
var mqtt = require('mqtt');
const thingsboardHost = "127.0.0.1";
const ACCESS_TOKEN = "**********";
// Initialization of mqtt client using Thingsboard host and device access token
console.log('Connecting to: %s using access token: %s', thingsboardHost, ACCESS_TOKEN);
var client = mqtt.connect('mqtt://'+ thingsboardHost, { username: ACCESS_TOKEN });
The default MQTT port number is 1883, but you don't have to manually set that value. Take a look at the source code.
https://github.com/mqttjs/MQTT.js

Swift-NIO secured websocket server

I am trying to create websocket server and client in my iOS app, which i successfully managed to do with the help of sample implementation here. (https://github.com/apple/swift-nio/tree/master/Sources/NIOWebSocketServer) - so current working situation is, i run the websocket server when app launches and then I load the client in a webview which can connect to it.
Now my problem is I want my server to secured websocket server (Basically connect to the websocket server from a HTTPS html page)
I am new to network programming and Swift-nio documentation is lacking to say the least. As far as I understand I could use (https://github.com/apple/swift-nio-transport-services)
I found this thread which is exactly what I need - https://github.com/apple/swift-nio-transport-services/issues/39 - I could disable the TLS authentication as I dont care in my usecase as long as I could get the websocket connected.
So my question is how to I extend my client (https://github.com/apple/swift-nio/tree/master/Sources/NIOWebSocketClient) and server (https://github.com/apple/swift-nio/tree/master/Sources/NIOWebSocketServer) to use swift-nio-transport-service.
I could add the NIOSSLContext and stuff but I think I need to add the EventLoopGroup and new bootstrap methods. I know the answers is right there.... but I just cannot seem to pinpoint it.
Any pointer would be appreciated.
Thanks.
To translate a simple NIO Server to a NIOTransportServices one, you need to make the following changes:
Add a dependency on NIOTransportServices to your server.
Change MultiThreadedEventLoopGroup to NIOTSEventLoopGroup.
Change ClientBootstrap to NIOTSConnectionBootstrap.
Change ServerBootstrap to NIOTSListenerBootstrap.
Build and run your code.
Some ChannelOptions don’t work in NIOTransportServices, but most do: the easiest way to confirm that things are behaving properly is to quickly test the common flow.
This doesn’t add any extra functionality to your application, but it does give you the same functionality using the iOS APIs.
To add TLS to either NIOTSConnectionBootstrap or NIOTSListenerBootstrap, you use the .tlsOptions function. For example:
NIOTSListenerBootstrap(group: group)
.tlsOptions(myTLSOptions())
Configuring a NWProtocolTLS.Options is a somewhat tricky thing to do. You need to obtain a SecIdentity, which requires interacting with the keychain. Quinn has discussed this somewhat here.
Once you have a SecIdentity, you can use it like so:
func myTLSOptions() -> NWProtocolTLS.Options {
let options = NWProtocolTLS.Options()
let yourSecIdentity = // you have to implement something here
sec_protocol_options_set_local_identity(options.securityProtocolOptions, sec_identity_create(yourSecIdentity)
return options
}
Once you have that code written, everything should go smoothly!
As an extension, if you wanted to secure a NIO server on Linux, you can do so using swift-nio-ssl. This has separate configuration as the keychain APIs are not available, and so you do a lot more loading of keys and certificates from files.
I needed a secure websocket without using SecIdentity or NIOTransportServices, so based on #Lukasa's hint about swift-nio-ssl I cobbled together an example that appears to work correctly.
I dunno if it's correct, but I'm putting it here in case someone else can benefit. Error-handling and aborting when the try's fail is left out for brevity.
let configuration = TLSConfiguration.forServer(certificateChain: try! NIOSSLCertificate.fromPEMFile("/path/to/your/tlsCert.pem").map { .certificate($0) }, privateKey: .file("/path/to/your/tlsKey.pem"))
let sslContext = try! NIOSSLContext(configuration: configuration)
let upgradePipelineHandler: (Channel, HTTPRequestHead) -> EventLoopFuture<Void> = { channel, req in
WebSocket.server(on: channel) { ws in
ws.send("You have connected to WebSocket")
ws.onText { ws, string in
print("Received text: \(string)")
}
ws.onBinary { ws, buffer in
// We don't accept any Binary data
}
ws.onClose.whenSuccess { value in
print("onClose")
}
}
}
self.eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 2)
let port: Int = 5759
let promise = self.eventLoopGroup!.next().makePromise(of: String.self)
_ = try? ServerBootstrap(group: self.eventLoopGroup!)
// Specify backlog and enable SO_REUSEADDR for the server itself
.serverChannelOption(ChannelOptions.backlog, value: 256)
.serverChannelOption(ChannelOptions.socketOption(.so_reuseaddr), value: 1)
.childChannelInitializer { channel in
let handler = NIOSSLServerHandler(context: sslContext)
_ = channel.pipeline.addHandler(handler)
let webSocket = NIOWebSocketServerUpgrader(
shouldUpgrade: { channel, req in
return channel.eventLoop.makeSucceededFuture([:])
},
upgradePipelineHandler: upgradePipelineHandler
)
return channel.pipeline.configureHTTPServerPipeline(
withServerUpgrade: (
upgraders: [webSocket],
completionHandler: { ctx in
// complete
})
)
}.bind(host: "0.0.0.0", port: port).wait()
_ = try! promise.futureResult.wait()
try! server.close(mode: .all).wait()

Error trying to Connect to GMail with MailKit

I've got the following code...
var credential = GoogleWebAuthorizationBroker.AuthorizeAsync(new ClientSecrets
{
ClientId = "<< MY CLIENT ID>>",
ClientSecret = "<<MY CLIENT SECRET>>"
},
new[] { "https://www.googleapis.com/auth/gmail.readonly" },
"<<EMAIL ADDRESS>>",
CancellationToken.None,
new FileDataStore("Mail2.Auth.Store")).Result;
using (var client = new ImapClient())
{
// THE CODE FAILS ON THIS NEXT LINE
client.Connect("imap.gmail.com", 993, SecureSocketOptions.SslOnConnect);
client.Authenticate("<<EMAIL ADDRESS>>", credential.Token.AccessToken);
}
When run, the code fails on the indicated like with AuthenticationException: The remote certificate is invalid according to the validation procedure.
I initially thought that is was 'cos the account had 2-step authentication on. So, I set up another account ensuring it just used the regular authentication settings and I got the same error.
I have found a number of posts, here and elsewhere, that deal with this exception but they seem to deal with the issue of working with the SmtpClient() and here, as you can see from the code, I'm getting the error with the ImapClient().
Can anyone suggest what it is that may be the cause of the error? Is it GMail? MailKit? .NET? All of the above?
The problem is that your system does not accept the GMail's SSL certificate.
You can override client.ServerCertificateValidationCallback.
A very simple example of a solution might look like this:
client.ServerCertificateValidationCallback = () => true;
Obviously that means that if anyone ever spoofed imap.gmail.com, your software would get caught in a MITM attack, so that's not ideal.
You'll likely want to match the certificate's thumbprint against a known thumbprint or else add the certificate to your local certificate store and assign a trust level to it.

Resources