Allowing Paste Linux Files Into a TextBox

If you are playing a lot with Linux, sooner or later you will see that pasting files produced by it will usually yield weird results on Windows as far as line ending goes.

You see, Linux uses Line Feed character (LF, ASCII 10) to signal the end of line. Windows uses a combination of Carriage Return and Line Feed (CRLF, ASCII 13+10). When Windows sees CRLF it will go to the next row. If it sees just LF, it will ignore it and you will see all in the same line unless application is a bit smarter. Unfortunately many are not.

Well, not much you can do about other people applications. However, you can ensure your application supports both CRLF and LF as a line ending. The only trick is to split text being pasted by CRLF, LF, and CR and to recombine it using CRLF (on Windows).

To catch paste, we can simply inherit existing TextBox control and override handling of WM_PASTE message:

internal class TextBoxEx : TextBox {
    protected override void WndProc(ref Message m) {
        if (m.Msg == NativeMethods.WM_PASTE) {
            if (Clipboard.ContainsText()) {
                var lines = Clipboard.GetText().Split(new string[] { "\r\n", "\n", "\r" }, StringSplitOptions.None);
                this.SelectedText = string.Join(Environment.NewLine, lines);
            }
        } else {
            base.WndProc(ref m);
        }
    }


    private static class NativeMethods {
        internal const Int32 WM_PASTE = 0x0302;
    }
}

Whenever you use TextBoxEx instead of TextBox, you will have your multiline paste working whether line ends in CRLF, LF, or even long-forgotten CR.

Visual Studio 2017

Illustration

After a long wait, Visual Studio 2017 is here.

Even better, if you download it until March 14 (π), you will get 60 days of Xamarin Univerity for free. But wait, that is not all - if you react now, there is a knife set just waiting… :)

First thing you will notice is a new installer. Yes, you could already see it during RC phase, but this one got a bit more options and new, a bit uglier :), interface. You might be temporarily scared a bit when you notice there are no ISO files to download. Fear not - you can still make an offline installer yourself. However, do notice that downloading everything will be around 24 GB (77 GB when installed). You might want to consider limiting yourself to just the workloads you need.

Full list of features you can find in release notes but I can already guess that most of people are interested into C# 7. My personal favorite is actually possibility to declare out variables in-line. Yes, I know that out variables should be used sparingly as quite often people get puzzled by them. However when you do lot of parsing, out variables can actually be the cleanest way to get something out without introducing helper class explosion. Other features in C# 7, local functions, is expressions, value tuples, ref returns…, are following the same line of simplifying the code without introducing extra fluff.

Additionally .NET Core finally got integrated properly into Visual Studio. I am all ok with doing ghetto project creation but there is something to be said about getting the big guns out when necessary. Debugging comfort simply does not compare between the two in my opinion.

Of course, there are some already known issues but I found nothing of real significance. I admit not being to clone SSH repository does sound damning but realistically most of time you are going to do that from command line and not from Visual studio so that doesn’t really count :P. Also, don’t forget to install .NET Framework 3.5 development tools if you have any legacy .NET 2.0 applications - otherwise they will be marked as 4.0.

I personally already moved to Visual Studio 2017 Community Edition but that might have not been a huge step as I dabbled in Release Candidate too. As for you, what are you waiting?

PS: Unfortunately Express editions are still not available but there is a positive confirmation they are coming really soon.

PPS: Xamarin University offer is actually not that impressive - it is pretty much useless as anything interesting requires subscription upgrade.

[2017-09-15: Express 2017 for Windows Desktop (preview) is available!]

[2017-10-16: Express 2017 for Windows Desktop is here - albeit for the last time.]

Creating Mikrotik's VPN Certificates With OpenSSL

What would be use of having your own certificate authority if one couldn’t use it to create Mikrotik-compatible OpenVPN or SSTP certificates?

Since we are our own CA we always start with creation of certificate signing request. For server certificate just take care CN matches whatever external domain you will be using to access your router (important for SSTP). All other values fill (or leave blank/default) at will:

openssl req -new -key server.key -sha256 -out server.csr
 Country Name (2 letter code) [AU]: .
 State or Province Name (full name) [Some-State]: .
 Locality Name (eg, city) []: .
 Organization Name (eg, company) [Internet Widgits Pty Ltd]: .
 Organizational Unit Name (eg, section) []: .
 Common Name (e.g. server FQDN or YOUR name []: *.example.com
 Email Address []:`` ^^.^^

Well, now we can use this request against a CA to get ourselves a sweet signature. For my case, I have a ghetto CA setup so all signing will be done in a single albeit a bit long line. Notice I manually specify the key usage - important for OpenVPN:

openssl x509 -req -CA ca.cer -CAkey ca.key -set_serial 0x$(openssl rand -hex 16) -days 3650 -extfile <(echo -e "keyUsage=digitalSignature,keyEncipherment\nextendedKeyUsage=serverAuth") -in server.csr -out server.cer

A few password prompts later and we have ourselves a signed server certificate.

Now we need to repeat these steps with a slight modification if a client certificate is needed too. Essentially the only difference is in key usage and common name:

openssl req -new -key client.key -sha256 -out client.csr
 Country Name (2 letter code) [AU]: .
 State or Province Name (full name) [Some-State]: .
 Locality Name (eg, city) []: .
 Organization Name (eg, company) [Internet Widgits Pty Ltd]: .
 Organizational Unit Name (eg, section) []: .
 Common Name (e.g. server FQDN or YOUR name []: client.example.com
 Email Address []: .
openssl x509 -req -CA ca.cer -CAkey ca.key -set_serial 0x$(openssl rand -hex 16) -days 3650 -extfile <(echo -e "extendedKeyUsage=clientAuth") -in client.csr -out client.cer

Once done and copied to router, on Mikrotik we only need to import CA, server and client certificate along with server’s private key:

/certificate import
 passphrase: ***********************************
      certificates-imported: 3
      private-keys-imported: 1
             files-imported: 3
        decryption-failures: 0
   keys-with-no-certificate: 0

Once imported we only need to adjust VPN server setup in PPP menu on Mikrotik and configure our clients as discussed in previous posts (OpenVPN/SSTP).

Creating Your Own Certificate Authority

If you are playing a lot with SSL/TLS, at certain point it starts making sense to create your own self-signed certificate authority. However, where to make something that needs to be as secret as possible?

For CA creation I personally love to use Raspberry Pi with Raspbian Jessie Lite for this. Once you create SD image, and assuming you don’t plug the network in, it is as close to secure computer as it can get.

While ideally (and in this guide) you are not going to save anything to disk without password, if you do slip it is really easy to recover on Raspberry Pi. Just destroy the SD card you used and no leaks will occur. Of course, paranoid should destroy SD card regardless. Just in case. :)

But let’s get back to creation of our certificate authority.

First we need to create a key. With OpenSSL you can even choose to protect it with password from the very start. Guess what? We’re gonna use that:

openssl genrsa -aes256 -out ca.key 2048

Once key is there, we need to sign it. Considering RSA 2048 key (approximately 112 bits of security) is considered by NIST to be acceptable until 2030, 10 years duration seems reasonable. You can fill as much or as little information as you wish. If nothing else, fill out common name to simplify your life:

openssl req -new -x509 -key ca.key -sha256 -days 3650 -extensions myext -config <(cat /etc/ssl/openssl.cnf <(echo -e "\n[myext]\nbasicConstraints=CA:true\nkeyUsage=cRLSign,keyCertSign")) -out ca.cer
 Country Name (2 letter code) [AU]: .
 State or Province Name (full name) [Some-State]: .
 Locality Name (eg, city) []: .
 Organization Name (eg, company) [Internet Widgits Pty Ltd]: .
 Organizational Unit Name (eg, section) []: .
 Common Name (e.g. server FQDN or YOUR name []: .
 Email Address []: .

With this our certificate is ready. I still like to make a PKCS #12 packet for safe keeping. Do not forget to set the passphrase here too (it will ask):

openssl pkcs12 -export -in ca.cer -inkey ca.key -out ca.p12

To get all this out of Pi, we can cheat and use FAT32 partition on SD card:

sudo mkdir /boot/ca
sudo cp *.cer /boot/ca/
sudo cp *.p12 /boot/ca/

Now we have a self-signed CA we can use it to create other server or client keys.

Mikrotik Configuration Backup

For start, I will assume that SSH user with appropriate rights is already configured as described in one previous blog post. From there getting Mikrotik’s configuration is easy:

ssh backup@192.168.88.1 "/export"

However, there are a few things wrong with it. First of all, all lines end with CRLF instead of more conventional LF (at least in the world of Linux/Unix). Fortunately this is easily fixed:

ssh backup@192.168.88.1 "/export" | tr -d '\r'

Next you will notice that exported config has a line continuation character (\) on its longer lines. While this is nice for viewing config, if we are to automatically process result with diff it is better to have each configuration line on its own. Getting Mikrotik to stop wrapping lines under all terminals is pretty much impossible, even using the +t4200w trick. However, sed can do wonders with enough cryptic code:

ssh backup@192.168.88.1 "/export" \
  | tr -d '\r' \
  | awk '{sub(/^ +/, "", $0); if (sub(/\\$/,"")) printf "%s", $0; else print $0}'

And finally, you might notice there is a time on top of the exported script. This, usually a handy information, will cause any automatic diff to always find a difference. So, removing it is in order:

ssh backup@192.168.88.1 "/export" \
  | tr -d '\r' \
  | awk '{sub(/^ +/, "", $0); if (sub(/\\$/,"")) printf "%s", $0; else print $0}' \
  | sed "s/^#.* by RouterOS/# RouterOS/"

With this we have a nice, repeatable, and diff-friendly configuration exported.

PS: If you are wondering why I am not using dos2unix, it is because I wanted code to run on NAS4Free that has quite restricted command line.