Hans was still thinking about the Wolf as he headed into town to get supplies. It was a nice day so he decided to wander down the side of the stream. As he passed the mill he looked up at the water wheel. The stream had been diverted into a wooden channel to power the wheel and then following the mill pond it rejoined the main flow.
"If I use a VPN client on the Yun then I could control my own channel to the weather service", he thought. When Hans reached the market he posted a letter to the weather service explaining his idea, bought the provisions and headed home.
Special Delivery
A few days later there was a knock on the door. "Hello", said the uniformed man. "You're not our usual postman" said Hans. "No", said the man, "he's off sick so I've come from the next town to stand in", and he handed Hans a letter.
The letter was sealed with a red wax seal with a big Y!. Inside was a paper with an official header on it that he instantly recognised. It was a letter from the weather service and it was not the news that Hans wanted to hear. Yes they could provide a VPN but it would need extra equipment installed in their office so would cost Hans 1000 gold coins per month. Hans and Matilda could not afford that but there must be another way.
Hans thought about the sealed envelope and the company identifier and wondered if the Yun could be configured for HTTPS connections. Simply adding the "s" to the end of the URL returned nothing so he added an extra parameter to try to capture the error stream back to the Arduino.
#include <Process.h> void setup() { // Initialize Bridge Bridge.begin(); // Initialize Serial Serial.begin(9600); // Wait until a Serial Monitor is connected. while (!Serial); // run various example processes runCurl(); } void loop() { // Do nothing here. } void runCurl() { // Launch "curl" command and get Arduino ascii art logo from the network // curl is command line program for transferring data using different internet protocols Process p; // Create a process and call it "p" p.begin("curl"); // Process that launch the "curl" command p.addParameter("https://query.yahooapis.com/v1/public/yql?q=select%20item.condition.text%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22Chicago%20IL%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys"); // Add the URL parameter to "curl" p.addParameter("&2>1"); // should pipe error output to stdout but does not p.run(); // Run the process and wait for its termination while (p.available()>0) { char c = p.read(); Serial.print(c); } // Ensure the last bit of data is sent. Serial.flush(); }
That did not work so Han's tried a different approach using runShellCommand because the "&2>1" may need to be interpreted by the shell.
#include <Process.h> void setup() { // Initialize Bridge delay(2500); Bridge.begin(); // Initialize Serial Serial.begin(9600); // Wait until a Serial Monitor is connected. while (!Serial); Serial.println("Running Curl"); // run various example processes runCurl(); Serial.println("Done"); } void loop() { // Do nothing here. } void runCurl() { Process p; // Create a process and call it "p" p.runShellCommand("curl \"https://query.yahooapis.com/v1/public/yql?q=select%20item.condition.text%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22Chicago%20IL%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys\" 2>&1"); while (p.available()>0) { char c = p.read(); Serial.print(c); } // Ensure the last bit of data is sent. Serial.flush(); }
This displayed the following error message:
Running Curl % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 curl: (60) SSL certificate problem: unable to get local issuer certificate More details here: http://curl.haxx.se/docs/sslcerts.html curl performs SSL certificate verification by default, using a "bundle" of Certificate Authority (CA) public keys (CA certs). If the default bundle file isn't adequate, you can specify an alternate file using the --cacert option. If this HTTPS server uses a certificate signed by a CA represented in the bundle, the certificate verification probably failed due to a problem with the certificate (it might be expired, or the name might not match the domain name in the URL). If you'd like to turn off curl's verification of the certificate, use the -k (or --insecure) option. Done
Hans installed the certificates into /etc/ssl/certs using the package manager.
opkg update opkg install ca-certificates
However the problem persisted.
After several hours of reading and googling the solution was found on the OpenWRT forum.
"The ca-certificates package is missing the HASH-links to the certificates"
https://forum.openwrt.org/viewtopic.php?id=50661
These can be added using openssl-util and a shell script provided in that article
#! /bin/sh OPENSSL=/usr/bin/openssl CERTDIR=/etc/ssl/certs # Install openssl-util if need [ ! -f ${OPENSSL} ] && opkg update && opkg install openssl-util for CERTFILE in ${CERTDIR}/*; do # create symbolic link from hash echo -en "Certificate ${CERTFILE##*/}\n generating hash: " HASH=$(${OPENSSL} x509 -hash -noout -in ${CERTFILE}) echo "$HASH" # handle hash collision SUFFIX=0 while [ -h "${CERTDIR}/${HASH}.${SUFFIX}" ]; do let "SUFFIX += 1" done echo " linking ${HASH}.${SUFFIX} -> ${CERTFILE##*/}" ln -s ${CERTFILE##*/} ${CERTDIR}/${HASH}.${SUFFIX} done
Hans fired up the Arduino Serial monitor and the script returned the forecast, it was going to be a great day!
Hans was now happy that he had secure end to end communications.
Reference:
http://curl.haxx.se/docs/sslcerts.html
http://wiki.openwrt.org/doc/howto/wget-ssl-certs
Next: Enchanted Objects Design Challenge - The snake, the troll and the fighting dwarves
Top Comments