Adding an Apple Watch App or Widget to Cordova

Intro

If you want to add native code to Cordova you’re pretty much on your own because the framework won’t help you with it.
Trying to add an iOS 14 widget and an Apple Watch app cost me 2 weeks of digging around in Cordovas source code and figuring out the Xcode project file. This article hopes to save you those 2 weeks.

The method

So obviously the first thing you would try when doing anything that has to do with a native feature in Cordova is you wold look for a plugin that does it for you. Unfortunately the few plugins that exist don’t work anymore. So we need to get our hands dirty ourselves.

The biggest pain point when integrating native features in Cordova is that the Xcode project file is created on every build overwriting any change you did manually.

The birds eye view of what I did is:
1. Build the Cordova app to generate the Xcode config
2. Add the iOS 14 widget and the Apple Watch target
3. See what parts of the Xcode config step 2 changed
4. Write a script to make those changes on every build

Build the Cordova app to generate the Xcode config

This part is very simple. Just build your app the way you always do. After you build the app, Cordova will have regenerated the Xcode project file at platforms/ios/yourapp.xcodeproj/project.pbxproj. Store this file at a different location or check it in to git, you will compare it with a later version.

Add the iOS 14 widget and the Apple Watch target

Now add your iOS 14 or Apple Watch target. If you have both I would recommend doing them one by one.
Since there are plenty of tutorials on this part I won’t go into detail here.

See what parts of the Xcode config step 2 changed

Now that you have two Xcode config files we need to compare the contents. Since the files are sort of json (they aren’t real json and can’t be parsed as such) you could just compare them with a graphical diffing tool such as Xcode -> Open Developer Tool > FileMerge. It is helpful to have an understanding of how the Xcode config file works.
The way I found very helpful though was to convert both Xcode config files into json and then using an online tool to compare them. Apple provides a tool to convert legacy plist (which is what the Xcode config is) into json.
– convert with plutil -convert json project.pbxproj
– diff the json with http://jsondiff.com/

Write a script to make those changes on every build

Birds eye view:
– Cordova build
– Runs add watch / widget hook
– Hook converts Xcode config to json
– Hook adds stuf to the Xcode config as json
– Hook converts the Xcode config back to the legacy plist format so Cordova is happy

Now this is the hard part. You might want to break it into steps and keep comparing the result of your script with the Xcode config you got after adding the Watch app or iOS 14 widget.

Because there are no good parsers for the Xcode config (except the one of CocaPods maybe but that’s Ruby and I don’t know Ruby yet) I opted to just convert the Xcode config in a Cordova hook to json and edit it.

Since the Xcode config is just a legacy plist file Xcode will recognize it if it is converted to json. So we just leave it as json right? Well I wish it was that easy but there is also Cordova and that has it’s own Xcode config parser that is actually quite bad cordova-node-xcode. It must have the legacy plist format and to make matters even worth it also needs the comments preserved.

What I ended up doing was converting the json back to the legacy plist format that Cordova know how to handle. Since there is no code for that already I wrote it.

Converting json Xcode config to legacy plist format

The Xcode config in legacy plist format looks like this

// !$*UTF8*$!
{
    archiveVersion = 1;
    classes = {
    };
    objectVersion = 46;
    objects = {

    // add sections here

    };
    rootObject = "...projectid..." /* Project object */;
}

The objects object holds Xcode config sections. Each object has a property named isa. For Cordova to recognize this file you need to loop through all the objects in your json and sort them by the isa. Then wrap each ISA section with the following comments.

/* Begin PBXBuildFile section */

// ...

/* End PBXBuildFile section */

Where PBXBuildFile in this example is just on ISA but you would have to do this for all the ISAs in your Xcode config.

If you’re curios why on earth we’d need to retain the comments https://github.com/apache/cordova-node-xcode/blob/master/lib/parser/pbxproj.js#L235. This is unfortunately the way the “parser” for Cordova is build.

Also see http://www.monobjc.net/xcode-project-file-format.html for information on the Xcode config file format.

Adding the script as Cordova hook

The script you just wrote needs to be run by Cordova on each build process.

In your config.xml add

    <hook src="hooks/convert.py" type="before_run" />
    <hook src="hooks/convert.py" type="before_build" />

Cordova bugs

There are plenty of bugs in Cordova making our lives harder here that we need to adress.

Cordovas ProjectFile.js has code that overwirtes the bundle id of every Xcode build target to the one defined in config.xml. This is bad because the widget and watch targets need differing bundle ids.
Some upcoming version of Cordova might include a fix but for now an easy solution is to:
– Fix the file on the fly with our hook. See https://github.com/apache/cordova-ios/issues/764#issuecomment-669317730 for details on how the file needs to be patched.

  • If you are using the iOS 14 widget or if your Apple Watch app is written in Swift you also need to patch a line in Cordovas config that breaks Swift code.
    Comment out the following line
    SWIFT_OBJC_BRIDGING_HEADER = $(PROJECT_DIR)/$(PROJECT_NAME)/Bridging-Header.h in build.xcconfig. This has to do with https://issues.apache.org/jira/browse/CB-10072.
    Note though that if you have a Cordova plugin that is written in swift it might break by changing that line and you’d need a different solution. Since support for most Cordova plugins was dropped long ago and are written in ObjC it wasn’t an issue for me.

There is one more bug worth mentioning although I didn’t find a way to do anything about it https://github.com/apache/cordova-ios/issues/1049 it basically prevents building the app without a real smartphone attached if you have the watch target.

And certainly not the last Cordova bug only the last I ran into. You can’t set a version lower than iOS 14 because for Cordova you need to set every target to the same minal version and the widget (at least if you wrote it with SwiftUI) requies iOS 14.

Resources

iOS Apps that support automation

This is a list of some of the iOS Apps that I use that are actually useful and become even more powerful when combined with the Workflow app.

Apps that support X-URL-Callback or a at least a URL Shem.

Pythonista write and execute Python scripts right on iOS.

Today helps build and keep track of your habits.

WaterMinder keep track of your daily water intake.

RemoteBoot WOL start a computer via “wake on lan”.

Anki a great flashcard app.

Things a todo list app thats better than apples native one.

you can find some more on the following links they might however not be as useful.

Apps with Siri shortcuts (for the Siri Shortcut app).

None yet. We will see the first once as iOS 12 comes out.

Making “CMS Made Simple” GDPR Compliant

Please Note: This might not be all required steps. These are just the steps I have found to work for me.

In the database

Open the Database for your “CMS Made Simple” instance and type

select * from cms_templates where template_content like ‘%fonts.googleapis.com%’;

to check if there is a template violating the GDPR.

Now all you have to do is to change the CSS. You could do that with an SQL Update or just the Database Administration Tool of your choice.

What I did is to change the URL from fonts.googleapis.com to GDPRVIOLATION-GOOGLE-FONTSAPI this way it will fail loading in the Browser thus its GDPR compliant and in the future when there is a knock-off google fonts server available in Europe we can just direct the URL to that one instead.

On the filesystem

Since “CMS Made Simple” is caching the template CSS on disk. We need to remove it there as well so the CMS can refresh our modified CSS text.

Caching is done in the directory tmp.

Delete every file in tmp/templates_c and tmp/cache DO NOT REMOVE THE DIRECTORIES.

Install Kali in 1&1 Cloud

Note

I wrote this article to help my future self to get this done faster next time. I make it public hoping it might be helpful for someone else as well.

Why would I do that?

To somehow find a way to make money with it – of course.

Installation

  • Setup a cloud server with the properties you want it to have
  • Insert the Kali ISO file into the virtual “DVD-Drive”
  • Start the Server
  • Open the KVM console
  • In the GRUB menu select graphical install
  • Select what you would normally but be carful at the following pints
    • Network
      • To access a network more manual configuration has to be made skip this for now
    • Mirrors
      • Since the network has not been configured yet validating the mirror will fail just skip this point for now
  • After installation shutdown, remove the ISO image and start the server

Configure Network (and internet access)

  • In the File /etc/resolv.conf we need to configure a DNS server. Add a line with “nameserver 8.8.8.8” (or change the IP for a different name server)
  • In the File /etc/network/interfaces add the following lines:
    auto eth0
    iface eth0 net static
    address YOUSERVERPUBLICIP
    gateway 10.255.255.1
    pointopoint 10.255.255.1
    
  • Restart the eth0 interface by typing “ifconfig eth0 down && ifconfig eth0 up” into a shell

Configure Mirrors (so updates will work)

  • In the File /etc/apt/sources.list add the following lines
        deb http://http.kali.org/kali kali-rolling main non-free contrib
        deb-src http://http.kali.org/kali kali-rolling main non-free contrib
    
  • Now type “apt-get update” to fetch the packages form the newly added repositories

Finally

Have fun & make money!

Making Servers And Websites Stand Hacker Attacks

Introduction

I recently got a coment from someone asking how to defend against hacker attacks. So here is the post with some of my thoughts on that matter.

General Information

First of all, its important to note that on some articles the autor makes a difference if he says Hacker or Cracker. The difference would be that a hacker is hacking stuff like servers, phones, websites and so on to show the weekness and help both the owner and society to be more conceus of the problems assosiated with modern tecnology and how to protect against those. Whilest the clracker is also hacking system he is more focust on the criminal aspect like stealing account passwords or even moey from your bank account. For simplicity I will not make such a distinguishment in this article.

In order to know how we can protect against hacker attacks we must first understand two things.

  • Why would anyone want to hack a system
  • How can a system be hacked

The why question is a rather simple one. The answer to that is very similar if not equal as to that in the real, physical world. Its one or a combination of those: for funn, for profit (stealing money), and probably many more.

The how question involves a little knowledge of the system. The holywood style where no hacks seems to be impolible is of course bullshit. The are prettty good mecanisms in todays tecnology that prevent hacking attacks. A notable exceptions are industrie automation and CCTV those are verry verry easy to hack for someone with even moderate skill (If you want to know more on that just visit the DEFCON youtube chanel).

Making systems hacker proof

Well, forget about hacker proof you can oly make it harder but not imposible.

Your Website

  • Use an encrypted connection to your website. If you dont everyone can just sniff your network traffic and just read the password. Those connections are usualy indicated by the browser with a lock symbol next to the website adress. In order to encrypt your website you will have to get a TLS certificate which can cost quite some money. A free alternative is Lets Encrypt I suggest you check that out.
  • Use strong passwords. Well that one is obviouse, the more charactes in a password the more time it would take to find a password by trying all posible variations. Also if your password can be found in a dictionarry it will be found. You should also avoid very common passwords like “love” or “12345” and so on. Also it is recomended that you use one password for one service or website. You could even go to the extreme and change a password every X month. However that is not practical. My personal opinoion is that its ok to have multible passwords for one kind of service for example one for all social media one for all online banking and so on provided those passwords are changed regularly and combined with One Time Passwords.
  • Use One Time Passwords when ever posible. You remember the last time you did some online banking and Im not speaking of PayPal I mean the old feshioned one. You moast likely got a unique number send to your phone by SMS. Well, you can install a OTP Pluin in your CMS two. The advantage here is, that even if someone gets ahold of your password he still needs to know a unique number which is genereated by an app on your phone so only you can know. Google Authenticator is one such app.
  • Also you should update your website frequently to get the moast recent security fixes. Now here some CMS have a auto update feature. The advantage here clearly is that you dont have to do anything to get the newest version…..except if the auto update fails. So my suggestion would be to not use this feature instead update manualy.
  • Defenetly automatic backups are a great idea as freqent as posible. Manualy does not work because you cant do a backup by hand every day.

Your Linux Server

Wen it comes to your linux server theres an overwhelming mass on options you have. I do however suggest not to overdo those because the more security layers you add the harder overall managament will get. Usability usualy suffers from security so wheight that out very carefully you dont want to get hacked yet you want a system thas usable.

Here are some thoughts you could start with:

  • Bruteforce protection (Also read: Fail2Ban)
  • Disable network services you dont need
  • Regular automated backup
  • Get the file permissions right
  • Do only install software form trusted sources. Every linux distribution has its own repository its like the AppStore for servers. It usualy has everything you need.
  • When installing new software search for spesific security considerations.

If youre more advanced and wnat to have even better security you could also do those things:

  • Install a sandbox like AppArmor
  • Run regular integrity tests (Make and compare checksums of files to see what a hacker might have changed)
  • If you run regular server integrity tests with cron and get the results via email. Those emails would be send in plain text for everyone to read – this includes the hacker who wnats to hack your server. So my suggestion here would be to use either GPG or S/MIME to encrypt those confidential emails. (Also read: Encrypt cron emails with S/Mime or Encrypt cron emails with GPG

Remember: Linux server security is way to large of a subject to fit in on one website. I encourage you to continue researching the entire internet on this topic.

Your Windows Server

Dont use a windows server if security is an issue. A Linux server might seem very complicated to maintain at the beginning and I promise you – that wont change with time. But its defenitly the secure version of both.

Go fore windows if you dont know linux and dont want to spend time on that. Windows is way easier to maintain and the licence cost isnt so bad if compared with the time you spend on linux servers.

Encrypting cron emails with S/MIME

Introduction

You might have your server setup in such a way that it runs a few tasks with cron so you don’t have to worry about them. Except.. you should. That is if the scheduled tasks send mission critical information over the internet. Now assume you have some kind of security audit software running like say lynis. You sure don’t want that report in the wrong hands since an attacker could really use that information to break into your server way easier than otherwise.
Assumptions

  • You have a S/MIME Certificate
  • You have root access to your linux web server
  • Your server runs on a recent Ubuntu

Encrypting

There are basically two ways of encrypting emails one is GPG and the other S/MIME. Refer to Encrypting cron emails with GPG if you prefer GPG. If you don’t know GPG I highly recommend checking that out as well since I personally consider it way more secure.

  1. Upload your S/MIME certificate to /home/smime.pem
  2. Create a file /home/smimecron.sh with following content
    emailTo=example@example.com
    emailFrom=example@example.com
    ifne /usr/bin/openssl smime -encrypt -text -from $emailFrom -to $emailTo -subject cronlog /home/smime.pem | sendmail $emailTo
    
  3. Make the script executable chmod a+x /home/smimecron.sh
  4. For this script to work we need the program ifne installed. Usually if a command has no output to /dev/stdout or /dev/stderr gpg would encrypt an empty string and you would receive an encrypted email that has no content once decrypted. This would be annoying ifne prevents this. To install it run.
    apt-get install moreutils
    
  5. Add the line SMIME_CMD = /home/smimecron.sh somewhere at the top of your /etc/crontab
  6. Now you can use it by adding | $SMIME_CMD after a command something like this:
    * * * * * root echo "test" | $SMIME_CMD
    

Fail2Ban Report

Introduction

See where the Attacks against your server come from.

Report Layout

The Report will look something like this:

------------------------------------------------------
Server attack statistics for the SSH service

Count, IP, Country
37   121.18.238.104  CN, China
42   221.194.44.231  CN, China
37   221.194.47.208  CN, China
42   221.194.44.195  CN, China
9    180.140.162.115 CN, China
38   121.18.238.98   CN, China
44   221.194.47.224  CN, China
11   180.140.161.30  CN, China
35   121.18.238.114  CN, China
42   121.18.238.109  CN, China
31   119.249.54.71   CN, China
38   221.194.47.249  CN, China
8    91.197.232.109  RU, Russian Federation
36   221.194.44.224  CN, China
14   59.63.166.83    CN, China
16   222.47.26.17    CN, China
------------------------------------------------------

Report Script

https://gist.github.com/philippmayrth/9f5b140e3f9dfe56eeaabe09d3e59a3b

Encrypting cron emails with GPG

Introduction

You might have your server setup in such a way that it runs a few tasks with cron so you don’t have to worry about them. Except.. you should. That is if the scheduled tasks send mission critical information over the internet. Now assume you have some kind of security audit software running like say lynis. You sure don’t want that report in the wrong hands since an attacker could really use that information to break into your server way easier than otherwise.

Assumptions

  • You are familiar with GPG
  • You have root access to your linux web server
  • Your server runs on a recent Ubuntu
  • Cron is already configured to send emails

Encrypting

There are basically two ways of encrypting emails one is GPG and the other S/MIME. We will be using GPG. Further this article assumes you are familiar with GPG.

  1. Upload your public key (ending in .asc) to your server /home is a good place.
  2. that the key can actually be read by the command we will be using, it has to be slightly modified. To be precise the ASCII amor has to be removed we need the key in binary form. This is archived by the following command.
    gpg --dearmor < /home/YOURPUBLICKEY.asc > /home/YOURPUBLICKEY.asc.gpg
    
  3. Add this line at the top of your /etc/crontab just after MAILTO=you@example.de. You need to replace the email address and the public key path.
    GPG_CMD = "ifne /usr/bin/gpg --batch --armor --trust-model always --no-default-keyring --keyring /home/YOURPUBLICKEY.asc.gpg --recipient you@example.de --encrypt"
    
  4. For this command to work we need the program ifne installed. Usually if a command has no output to /dev/stdout or /dev/stderr gpg would encrypt an empty string and you would receive an encrypted email that has no content once decrypted. This would be annoying ifne prevents this. To install it run.
    apt-get install moreutils
    
  5. Now in /etc/crontab you can simply pipe the output to gpg and enjoy encrypted emails.
    * * * * * root /bin/echo "gpg test" | $GPG_CMD
    

I got the inspiration for this from this a site that is unfortunately offline for a few days now (checked April 2021).

Server Authentication With Client Certificate X.509

Introduction

Basics of setting up certificate based authentication on Apache.

Assumptions

Your Server is already configured to use SSL/TLS. This is required because the browser refuses to use its certificate for authentication on an insecure connection.

Creating all the files we need

Note: The key sizes and expiration dates must be adjusted to suite your need.

Create the CA

openssl genrsa -out CA.key 2048
openssl req -x509 -new -nodes -key CA.key -days 7300 -out CA.pem

Create a signing request and signing it with the CA private key

openssl genrsa -out alice.key 2028
openssl req -new -key alice.key -out alice.csr
openssl x509 -sha256 -req -in alice.csr -out alice.crt -CA CA.pem -CAkey CA.key -CAcreateserial -days 1095

Convert the alice.crt to alice.p12 so a browser knows what to do with it. (Note: On safari the .p12 file has to have a password for the import to work)

openssl pkcs12 -export -clcerts -in alice.crt -inkey alice.key -out alice.p12

Convert the .p12 to .pam so tools like curl can use it

openssl pkcs12 -in alice.p12 -out alice.pem -clcerts

Configuring Apache

copy your CA.pem in a file readable by apache. In my case it is /home/CA.pem but this might differ for your server.

in your virtual hosts configuration file add SSLCACertificateFile and SSLVerifyClient like shown below.

<IfModule mod_ssl.c>
<VirtualHost *:443>

    SSLCACertificateFile /home/CA.pem
    SSLVerifyClient require


# ..... your additional configuration here
# .....

</VirtualHost>
</IfModule>

Finally… we can use it

To use the certificate with curl

curl -E alice.pem https://restricted.example.de

To install in Safari on a Mac just double click the .p12 file and follow the instructions

To install on iOS the file can be send by email (messengers don’t work) and installed by tapping on it and following the instructions. If the file is considered a production file it should NOT be send over the internet instead plug in a usb cord and transfer via iTunes.