Saturday, 3 March 2018

Why smartwatches are dumb


TLDR; Apple and Google showed that providing an open ecosystem for running code on phones could lead to market dominance. So why isn't it hppenning for wearables?
I was thinking to myself the other day that a combination of Google authenticator and a smartwatch was a match made in heaven. I'd been toying with the idea of jumping on the smartwatch bandwagon to get my geek on – but fitness trackers don't really light my fire. And, like email, I read my texts when I've got time to, not when they arrive. So I wasn't left with a lot of reasons for spending money on a watch with an irritatingly short battery life. 

Then I thought of 2FA. 

I use it for work with a ridiculously expensive RSA token. I recently had to get a new one after losing one somewhere. A TOTP generator on my phone is not a great idea – my work pays for a blackberry where they enforce a silly password policy. Do I really want to type a 12 character password into my phone in order to start an app to get a token so I can then log into something else? But dongles are just something else to carry. And I need something which is convenient to carry around....BING....light bulb moment.
A quick look round the internet revealed Gear 4 Android (not really clear if the watch itself runs android or if it just talks to an android phone) and Apple iWatches. But at a price starting around £150, it's rather a lot for pet project. Pebble watches have a really good SDK, but the original company went bankrupt and I don't know if the new owners of the technology really want to continue in the same market. And they're not much cheaper.

The first computer I ever bought cost me around £70 in 1981 and came with 1k RAM, no permanent storage built in, and hooked up to a TV to use as a display. But today I can buy an ARM based device with a lithium battery and a full colour screen for under a tenner. Sadly, the ZX81 was easier to program!  

People are actively hacking these U8 devices but we still seem to be a long way from being able to use them as general purpose computers.

There's no end of fitness bands available for under £20. They promise much longer battery life than the fullblown smartwatch and more than enough processing/memory/display capabilities to also support TOTP, but it seems that none of them are programmable. Even the ones which claim to come with anSDK (actually its an SDK to write code for Android/iOS to poll the ANT+/Google fit APIs) don't actually provide a development chain.

Yes, I know there's lots of people building cunning, but ugly devices out of arduino's and 3D printing cases. But that's a bit hardcore for me (and would end up costing me a lot more than a Pebble/Android watch). I could buy a ready-made one but its still so UGLY.

Googling for smartwatches, I eventually came across “metawatch” which claims to be an open-source smart watch – but currently unavailable on Amazon.

Hexiwear? UGLY

The inpulse and WIMM aren't ugly – but they are expensive.

Microsoft's smartwatch came and went so quickly nobody even saw it.

Why can't I get a watch for under £100 where I can run my own code?

Stop Press: I did just find this but do I really want to strap a full blown android phone to my wrist? And there are a growing number of MTK6737 Android watches appearing. But what about the battery life?

Wednesday, 29 November 2017

Unexpected PHP/MySQL failure!

Somehow my life/code is never as simple as the examples on w3schools.

Once again I should to explain a lot of the context (and apologize for some of it) before I get to the point. But the short version is both the mysql and mysqli extensions seem to cast all mysql data as strings.

Normally this goes unnoticed when you're working with PHP - its dynamic type conversion handles all the bumps. But not this time.

I wrote an application for tracking data quality some time ago. This runs various rules against several large datasets and collects the exceptions in a single polymorphic table which looks something like:

rule VARCHAR(20)
yearmonth INTEGER
PK1 INTEGER
PK2 VARCHAR(30)
PK3 VARCHAR(30)
data CLOB
age INTEGER

Each row of output from each rule is stored in a record in this table. Periodically the historic data is deleted.

Yes, I confess I'm holding a structured opaque data blob in a relational database! But by synthesizing PK1, PK2 and PK3 from the rule data it means I can compare month on month outputs to get the age of the exception. And I have a reliable unique identifier for each record in the (very large) table.

All well and good. This is currently tracking 320 rules and the application maintains summary level data. It has been running for about 8 years. But users as *so* demanding! They wanted to see one of the rules (customer whose email addresses pass a regex check but fail MX lookup) decorated with information come a separate database. Not such a big deal. The application has the capability to mailmerge the output of one ruleset to create a query for another (clever, eh?). So all that was needed was a bit of configuration.

But now the story takes a twist. The number of records involved is.....lets just say a lot. This all runs on a very old version of MySQL (because that's how RHEL rolls its distro, and everyone hates systemd) which was originally configured to give great performance on low latency storage (i.e. MyISAM) but now runs on a SAN with very high latency (but massive bandwidth).

Because of these considerations, along with the fact that I rarely rebuild the indexes, joining the output of the two rules was HORRENDOUSLY slow. Its supposed to be available at the click of a button, but I got bored waiting after one hour. This version of MySQL does not do merge joins. So I wrote my own in PHP. This took around 5 seconds to retrieve the data. But huge chunks of the data were missing! I eventually tracked this down to the fact that the mysql PHP extension was converting the PK1 integer attribute to a string. So "110" was greater than "1000" and my code was discarding lots of rows when trying to join the two datasets.

I can understand that there would be a cost if the library had to call back to the DBMS to get the type of each attribute in a resultset, but looking at the C API, it looks like the client lib is returning a correctly typed attribute, but the PHP engine is casting it as a string!

But, of course, the MySQL extension has long been deprecated. So I decided to see of MySQLi was similarly afflicted. After a brief diversion when I discovered about SO_PEERCRED I found that MySQLi does the same thing.

Saturday, 22 July 2017

Validate Input : Escape Output


When training inexperienced programmers, there are 2 mantras I always need to repeat:

  1. You don't write code for computers to understand; you write it for humans to understand.
  1. validate input : escape output

Since this the latter has cropped up a few times recently, I have documented the reasoning here.

Both validation and escaping are about protecting your system against attack and ensuring good data quality.

Validate input

Validating input means checking that the input falls within the acceptable boundaries for your application. Does it look like the right data type? Is it within a sensible range? Does it contain malware?

The first 2 examples are there to avoid processing data which is obviously wrong. People make mistakes when entering data – and prompting them to fix the error is massively cheaper than trying to find and fix the bad data later. Checking for malware might be as simple as rejecting content which looks like HTML markup, or you might test the content against a complete AP14 gateway with multiple heuristic malware checkers. The point is that your code must decide whether to accept the data and process it or reject it .

Why not transform input?

If your underlying platform is vulnerable to buffer overflows or similar attacks, then by the time the thread of execution reaches your code your system is already compromised.
Later in your processing you may well transform the data, but not at the point where it enters your code. You need to ensure that you know how the data is represented anywhere you are processing it; the simplest way to do that here is to leave it in as raw a state as possible.

Exceptions

Validating input

In some cases you may choose to reject the data silently, or re-route it to a honeypot – but that is a very esoteric edge case. And both are still forms of validation.

Transforming input

Again, there are some edge cases where it is necessary to modify the input in order to validate it, for example:
  • your code expects data encrypted with specific keys
  • the input data has tamper resistance added which should be removed before processing (such as anti-csrf tokens)

Escape output

Escaping output means transforming it to a form where:
  • the original data is recoverable in a suitable state/representation for further processing
  • the content of the data does no interfere with the control channel for the data
That second one is a bit tricky. When writing to an SQL database or creating HTML/CSS/Javascript for a browser the data is sent over the same channel as the control structures. The relevant languages have syntax for keeping the data and control seperate. Sometimes this syntax is abstracted by an API (such as PDOs data binding or the json_encode() function).
Any time is leaving your code and going somewhere is it should be rendered in an appropriate format for the receiving process. Sometimes a single script may have multiple output vectors – a local record in a database, a notification email to the user, html to the browser. Each need different representations of the data.
Hence to ensure the right representation of the data for the target, the transformation should be near to the point where it is output – both in the sequence of execution and the in the structure of the code.
While a few of the transformation functions have both an encode and decode implementation in PHP, it doesn't make any sense to try to reverse the encoding of the data for one output channel in order to write it to another within the scope of a single script. All the programming languages I have used are similarly asymmetric.

Exceptions

The only exception to the "Escape output" rule is If the data channel is independent from the control channel - for example when writing to a local file (although even then, you need to be careful not to write en EOF character as data to a file opened for text).

Monday, 6 March 2017

Today I saved the planet

Well, prolonged its demise a little.

My teenage son, despite repeated requests, frequently walks away from the computer leaving it running. And now that I've got a shiny new and very quiet computer it is not always obvious that it has been left running.

While formerly I would just changed the program the window manager invoked as a screensaver Linux systems have got a lot more convoluted. Whether this complexity is a good or necessary thing - I will reserve judgement.

Anyway, to cut a long story short, the solution for me was to use xautolock which, once started, monitors for a period of inactivity then runs a program. Setting it to start automatically on my Mint / mate box (no XClients / Xsession) was a matter of adding a .desktop entry to the XDG autostart directory:

[Desktop Entry]
Type=Application
Exec=xautolock -detectsleep -time 50 -locker "/sbin/shutdown -h now"
Hidden=false
X-MATE-Autostart-enabled=true
Name[en_GB]=xautolock
Name=xautolock
Comment[en_GB]=
Comment=

Monday, 26 December 2016

Installing Linux (Fedora) on a Lenovo Yoga 510

Given the brexit vote, falling pound and a reasonable bank balance, the whole family got new computers this year for Christmas. A Lenovo M700 MT desktop for myself, a HP laptop for my son and a Lenovo Yoga 510 for my daughter.

(I was rather surprised doing my initial research to discover that desktop computers now cost more than a laptop of equivalent spec - even though the latter also includes a battery and a screen.)

While my son just wanted MSWindows on his, my daughter wanted Linux. We had an interesting conversation with the salesman at PC-World. When she asked him if it would run Linux, he said that installing Linux would void the warranty. "But its just software?" she replied. He insisted that installing anything other than what it came with would void the warranty. I interjected at this point and asked him to clarify "Installing any other software than MS-Windows will void the warranty?"

"Yes - I can't get my manager if you don't believe me".

So we bought her computer from John Lewis.

Unlike my desktop which came with MSWindows 7, shrinking the C drive in Windows 10 actually worked! Getting into the UEFI setup to change the boot order was a bit harder though - no messages at startup to advice what key press would open the setup or allow the boot order to be changed.F1, F2, escape and F12 during boot had no effect.

The only option was to select restart from a running MSWindows session while holding down the left shift button. This rather enforced the option of dual boot - but with a 1Tb disk, there was plenty of room to spare.

I was rather surprised to discover that although I could get into the UEFI setup, the keyboard was completely unresponsive. Plugging in an external keyboard solved that problem. Boot order changed and I was ready to go.

Since it's a touch screen device, I decided to go with a Gnome 3 desktop. And since it came with SecureBoot, I decided to go with Fedora (which has a signed boot loader). I'll maybe get a bit more adventurous in future, but for now, baby steps.

Running from the USB stick was a bit ropey, but these problems went away when I installed to the hard disk. Everything is working apart from the touch screen. That's quite a big omission, but as relatively new hardware running with a very new display system (Fedora 25 uses Wayland rather than Xorg) it may take a while to get it sorted - meanwhile I'll let my daughter play around.

Even without the touchscreen stuff, this wee device is a viable proposition as a laptop - there are a lot of devices available at this price point, but this is notable in feeling very sturdy.

Keyboard nirvana? Almost.

Having blogged about keyboards twice before, you may have got the impression I'm slightly obsessive. I am.

While my old PC was merely getting a bit past its sell-by-date, the keyboard I was using was horrible - a really nasty HiPoint silicone bump device purchased as a temporary measure until I could do some proper research.

As before I had started with what I thought was a reasonable set of requirements:
  • UK layout
  • Compact (i.e. full-sized keys, but without a numeric keypad) to save space on my small desk, and avoid having to reach so far for my mouse.
  • Nice tactile action
  • High contrast between the lettering and background on the keys (or illumination)
  • Wired (i.e. USB, despite the fact my new PC still comes with PS/2 mouse and keyboard connectors)
  • NOT CHICLET KEYS!
But it proved remarkably difficult to find anything even coming close to this bill. From much trudging around shops, I was able to identify that Cherry MX red's seemed to provide the right feel (albeit with rather a lot of travel needed). Even just reducing the list down to Cherry MX red / compact / UK layout, I could not find anything online. It seemed the only option I had to meet these requirements was to get a keyboard built to order by a specialist at a cost in the region of £150+ and even then, finding a tenkeyless offering was proving difficult.

Instead, I decided to take a gamble on a keyboard found on eBay - a Bakker Elkhuizen 840.
This has scissor keys rather than Cherry MXs, but has (IMHO) a really nice action. The keys are:
  • the right size
  • in the right place
  • legible with black on light grey
It feels solid and well-built. And, as a bonus, is a USB hub with 2 connectors.

I'm well pleased.

Lenovo ThinkCentre M700

My HP Pavillion desktop (4Gb, dual Athlon 2200) was getting a bit long in the tooth, and I decided to treat myself to a new rig.

In the past I've been rather impressed with the robustness of high-end PCs - I had a dual Pentium II HP Kayak XM600 for many years before I passed it on my mother for an extended tour of duty. Apart from the RD-RAM which never came down in price while the cost of DDR tumbled. Add to that the fact that running the X Window system, I wasn't going to see a lot of benefit from a fancy graphics card, I really wanted to get the fastest CPU I could. I did consider getting a retired server - but they are typically horrendously noisy. Then I thought about a used HP Z400. But looking at the behaviour of my current system, while the CPU was frequently maxed out,  it was usually with just one or 2 processes causing all the pain. Having 8-16 CPUs wasn't going to help unless they were a lot faster than what I already had.

Looking at the single-core benchmarks, the 3.7GHz i3 6100 seemed to hit a sweet spot for budget/performance profile. So I started shopping for such a device. Form factor was a consideration - I have a small desk which my computer sits underneath - so a tower case was important. I ended up choosing a Lenovo ThinkCentre M700 from eBuyer.
The device itself is not as substantial as the PCs I've owned before - and despite the tower case, there is limited scope for expansion. Adding a couple of hard disks is about the limit. There are 2 DDR4 slots (one occuppied with a 4GB module), 3 PCI Express connectors (2 very small, and one small - I'm not familiar with the technology). The blanking plate behid one of PCIe connectors is filled with an external SATA connector (which could be moved elsewhere to make the slot usable). But apart from an SSD and possibly more RAM later I'm not looking at add a lot more hardware to this machine.

The handle at the front/top is not particularly sturdy, but adequate for occassionally lugging the device about.

Powered up, it seems remarkably quiet compared both to the HP Pavillion its replacing and the HP i5 generic corporate device I use at work.

Accessing the BIOS (sorry UEFI setup) was easy - just F1 at boot. The default configuration came with Windows 7 and Secure boot disabled. As I'm doing a lot more MSWindows dev and admin stuff these days, I decided to keep it as dual boot. Shrinking the C drive in MSWindows proved to be a complete PITA - even after disabling swap, updates and rollbacks, it still wouldn't release more than around 10Gb due to "unmoveable" files. And having to use the horrible tools with MSWindows was just too painful - so I booted up with a Mint install disk and had no problem shrinking the drive down to 100Gb.

Installing Mint 18.1 from a DVD I had prepared earlier was a no-brainer. I created the same users on the new machine as existed on the old, rsynched /home and everything worked - but a lot faster!

The onboard ethernet works with the RTL8168g driver. Its a 500Gb Western Digital HD. This feels a little slower than the 2 x Seagate 250Gb disks in the old machine (configured as OS+Backup and home+var+data+swap rather than in any RAID setup). But the planned SSD upgrade should fix that.

If only the laptop had been this easy! (details coming in a later post).