newspaint

Documenting Problems That Were Difficult To Find The Answer To

Category Archives: Mobile Phone

Android ICS Calendar Appointment Import – Unable to Launch Event

This error, “Unable to launch event”, is often encountered when attempting to open an .ics calendar appointment file from Firefox (e.g. from the “Your Downloads” screen).

Typically you would select an .ics file from the list of files you’ve downloaded:

Select .ics file to open and choose to "Open with Calendar"

Select .ics file to open and choose to “Open with Calendar”

and this would give you the option to “Open with Calendar” to which you might choose “JUST ONCE”.

This would result in the error “Unable to launch event” as per the following screenshot:

Firefox warns "Unable to launch event"

Firefox warns “Unable to launch event”

The Workaround

You can still import your .ics file into Calendar!

Go to your applications list, and choose “Files” (on LineageOS), “My Files” (on Samsung), or whatever your generic file explorer is on your phone. Navigate to your “Downloads” folder. Then open the .ics file from there.

Setting Up OpenVPN Server for Rooted LineageOS Phone

Installation Steps

Install OpenVPN Server

me@server:~$ sudo apt-get install openvpn
The following NEW packages will be installed:
  liblzo2-2 libpkcs11-helper1 openvpn
0 upgraded, 3 newly installed, 0 to remove and 0 not upgraded.
Need to get 513 kB of archives.
After this operation, 1,353 kB of additional disk space will be used.
me@server:~$ sudo apt-get install openssl
The following NEW packages will be installed:
  openssl
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 492 kB of archives.
After this operation, 956 kB of additional disk space will be used.

Choose a routed VPN (rather than a bridged). Use username/password authentication (still requires server certificate authority (CA) and server certificate.

Edit /etc/default/openvpn and add:

# Ensure tunnel device is available
if [ ! -d /dev/net ]; then
  mkdir /dev/net
fi

if [ -d /dev/net ]; then
  if [ ! -e /dev/net/tun ]; then
    mknod /dev/net/tun c 10 200
    chmod 666 /dev/net/tun
  fi
fi

Create a tunnel device:

me@server:~# openvpn --mktun --dev tun0

Create Certificate Authority

me@server:~# mkdir /etc/openvpn/ssl
me@server:~# cd /etc/openvpn/ssl
me@server:/etc/openvpn/ssl# openssl genrsa -out ca.key 2048
Generating RSA private key, 2048 bit long modulus
............+++
................................................................................................+++
e is 65537 (0x10001)
me@server:/etc/openvpn/ssl# openssl req -new -x509 -key ca.key -out ca.crt

Now we have ca.crt (the certificate authority certificate) and ca.key (the key for the certificate authority).

You can get the text form of the certificate (used later for the client configuration) by issuing the command:

me@server:/etc/openvpn/ssl# openssl x509 -in ca.crt -text

… and extracting the portion between (and including) the BEGIN CERTIFICATE and END CERTIFICATE lines.

Create Server Certificate and Sign Using Certificate Authority

me@server:/etc/openvpn/ssl# openssl genrsa -out signing.key 2048
Generating RSA private key, 2048 bit long modulus
.....+++
............................................................+++
e is 65537 (0x10001)
me@server:/etc/openvpn/ssl# openssl rsa -in signing.key -pubout -out signing.pub
writing RSA key
me@server:/etc/openvpn/ssl# openssl req -new -key signing.key -out request.csr

me@server:/etc/openvpn/ssl# openssl x509 -req -days 1500 -in request.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt
Signature ok
Getting CA Private Key
me@server:/etc/openvpn/ssl# openssl x509 -in server.crt -noout -text

Now we have server.crt (the server certificate).

Create Difie-Hellman Key

me@server:/etc/openvpn/ssl# openssl dhparam -out dh1024.pem 1024

Create Static Shared Key

me@server:/etc/openvpn/ssl# openvpn --genkey --secret static.key

Create auth.pl

(taken from the example at /usr/share/doc/openvpn/examples/sample-scripts/auth-pam.pl)

#!/usr/bin/perl -w

use strict;

# Allowed username/password combinations
my %users = (
    'jim' => 'letmein',
    'mary' => 'password123',
);

# Get username/password from file

my $ARG;
if ($ARG = shift @ARGV) {
    if (!open (UPFILE, "<$ARG")) {
        print "Could not open username/password file: $ARG\n";
        exit 1;
    }
} else {
    print "No username/password file specified on command line\n";
    exit 1;
}

my $username = <UPFILE>;
my $password = <UPFILE>;

if (!$username || !$password) {
    print "Username/password not found in file: $ARG\n";
    exit 1;
}

chomp $username;
chomp $password;

close (UPFILE);

if ( $users{$username} && ( $password eq $users{$username} ) ) {
    exit 0;
} else {
    print "Auth '$username' failed.\n";
    exit 1;
}

Create server.conf

tls-server
port 1194
proto udp
dev tun
mssfix 576
cipher AES-256-CBC

ca /etc/openvpn/ssl/ca.crt
cert /etc/openvpn/ssl/server.crt
key /etc/openvpn/ssl/signing.key
dh /etc/openvpn/ssl/dh1024.pem

tls-auth /etc/openvpn/ssl/static.key 0

script-security 2 # necessary for auth-user-pass-verify
auth-user-pass-verify /etc/openvpn/auth.pl via-file
client-cert-not-required
username-as-common-name

server 10.44.12.0 255.255.255.0 # subnet for clients
keepalive 10 120
comp-lzo
persist-key
persist-tun
status /var/log/openvpn-status.log
log /var/log/openvpn.log
verb 3

push "redirect-gateway def1"
push "dhcp-option DNS 1.1.1.1" # cloudflare DNS

Enabling/Starting/Stopping OpenVPN

me@server:~# systemctl enable openvpn@server.service
me@server:~# systemctl start openvpn@server.service
me@server:~# systemctl stop openvpn@server.service

Create .ovpn Configuration File for OpenVPN Android Client

tls-client
remote 192.0.2.44 # the IP address of my OpenVPN server
port 1194
proto udp
comp-lzo
auth-user-pass
key-direction 1
mssfix 576
cipher AES-256-CBC

<ca>
-----BEGIN CERTIFICATE-----
...
...
...
-----END CERTIFICATE-----
</ca>

<tls-auth>
-----BEGIN OpenVPN Static key V1-----
...
...
...
-----END OpenVPN Static key V1-----
</tls-auth>

On The Phone

Install “OpenVPN Connect – Fast & Safe SSL VPN Client” by “OpenVPN”.

Then add .ovpn file created above.

Install iptables Scripts

me@server:~# apt-get install iptables-persistent
The following NEW packages will be installed:
  iptables iptables-persistent libnfnetlink0 netfilter-persistent
0 upgraded, 4 newly installed, 0 to remove and 0 not upgraded.
Need to get 292 kB of archives.
After this operation, 1,804 kB of additional disk space will be used.

Edit /etc/iptables/rules.v4:

###############################################################################
# iptables IPv4 rules for reload on start-up
#
# To Reload:
#   service netfilter-persistent restart
#
# To Test:
#   iptables-restore -t </etc/iptables/rules.v4
###############################################################################

*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT

*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]

-A POSTROUTING -s 10.44.12.0/24 -o eth0 -j MASQUERADE

COMMIT

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT

Issues

external program fork failed

If you see something like the following:

Wed Jun 20 03:33:31 2018 192.0.2.41:39523 WARNING: External program may not be called unless '--script-security 2' or higher is enabled. See --help text or man page for detailed info.
Wed Jun 20 03:33:31 2018 192.0.2.41:39523 WARNING: Failed running command (--auth-user-pass-verify): external program fork failed

… then you probably have a “script-security 1” parameter somewhere in your configuration (after any other script-security 2 directives). Grep for it and comment it out so that your “script-security 2” directive can take effect.

See Also

Changing Encrypted Partition Password on LineageOS 14.1

This was done on a ZTE Axon 7 running Android 7.1.2 (LineageOS 14.1).

I booted into the LineageOS 14.1 operating system, connected using ADB.

WARNING: the encryption password can only be changed in LineageOS itself, not TWRP, so if you get this wrong you will have an irrecoverable encrypted data partition. To protect yourself ensure you verify the new password before rebooting.

NOTE: this does not change the screen lock code, it only changes the password for decrypting the phone on boot (the first password you’re required to enter after a cold boot).

~$ adb root
~$ adb shell
axon7:/ # vdc cryptfs verifypw 1234 # wrong password
200 8421 -1
axon7:/ # vdc cryptfs verifypw 1111 # wrong password
200 8543 -1
axon7:/ # vdc cryptfs verifypw 4444 # correct password
200 8558 0
axon7:/ # vdc cryptfs changepw help
Usage: cryptfs changepw default|password|pin|pattern [[currentpasswd] newpasswd]

axon7:/ # vdc cryptfs changepw pin 4444 912541324 # change password
200 8703 0

axon7:/ # vdc cryptfs verifypw 4444 # no longer correct password
200 8761 -1
axon7:/ # vdc cryptfs verifypw 912541324 # new correct password
200 8770 0

Thanks to the information in this forum post for assistance in how to do this.

BASH /usr/bin/adb No Such File or Directory

Using Xubuntu (Ubuntu) 16.04.3 I encountered a strange problem. I’d removed the Android debugging tools using the command:

my@myhost:~$ sudo apt-get remove android-tools-adb

I did this because I installed the latest platform tools manually from Google directly.

So next time I went to run adb I didn’t expect to see the following:

my@myhost:~$ adb
bash: /usr/bin/adb: No such file or directory

The answer was found in this forum post. I did not realise this but BASH actually caches executables found in the $PATH to avoid having to perform future searches.

The type command can reveal whether an executable has been stored in the cache (or “hashed”):

my@myhost:~$ type adb
adb is hashed (/usr/bin/adb)

To clear the entire cache the following command can be run:

my@myhost:~$ hash -r

.. but it might be preferable to only clear that command that has been removed from the cache:

my@myhost:~$ hash -d adb

How to Migrate WhatsApp From One Rooted Android Phone to Another Rooted Android Phone

If you are using CyanogenMod or LineageOS or similar and want to copy WhatsApp from one phone to the other here are the steps that may do what you want.

Firstly decide where you’re going to back your WhatsApp data to, in my case I wanted to write to the /storage/sdcard1/ folder on my old phone in which was inserted a MicroSD card.

Start off by backing up the app, data, and media files from the existing (old) phone:

me@server:~$ adb root
me@server:~$ adb shell
root@oldphone:/ # tar -cvpJf /storage/sdcard1/data-whatsapp.tar.xz /data/data/com.whatsapp
root@oldphone:/ # tar -cvpJf /storage/sdcard1/app-whatsapp.tar.xz /data/app/com.whatsapp-3
root@oldphone:/ # tar -cvpJf /storage/sdcard1/media-whatsapp.tar.xz /data/media/0/WhatsApp
root@oldphone:/ # exit

me@server:~$ adb pull /storage/sdcard1/data-whatsapp.tar.xz
me@server:~$ adb pull /storage/sdcard1/app-whatsapp.tar.xz
me@server:~$ adb pull /storage/sdcard1/media-whatsapp.tar.xz

An alternate method to avoid storing on the device’s flash is the following:

me@server:~$ adb root
me@server:~$ adb exec-out "tar -cvpJf - /data/data/com.whatsapp 2>/dev/null" >/tmp/data-whatsapp.tar.xz
me@server:~$ adb exec-out "tar -cvpJf - /data/app/com.whatsapp-3 2>/dev/null" >/tmp/app-whatsapp.tar.xz
me@server:~$ adb exec-out "tar -cvpJf - /data/media/0/WhatsApp 2>/dev/null" >/tmp/media-whatsapp.tar.xz

Now unplug the existing (old) phone. Plug in the new phone. Choose where you want to upload the backups to for extraction later (I chose /storage/0000-0000 as that was my MicroSD card on the new phone).

me@server:~$ adb root
me@server:~$ adb push data-whatsapp.tar.xz /storage/0000-0000/
me@server:~$ adb push app-whatsapp.tar.xz /storage/0000-0000/
me@server:~$ adb push media-whatsapp.tar.xz /storage/0000-0000/

me@server:~$ adb shell
root@newphone:/ # cd /
root@newphone:/ # tar -xvpJf /storage/0000-0000/data-whatsapp.tar.xz
root@newphone:/ # tar -xvpJf /storage/0000-0000/app-whatsapp.tar.xz
root@newphone:/ # tar -xvpJf /storage/0000-0000/media-whatsapp.tar.xz

At this point everything is where it needs to be. However there’s a big problem. Every app has a unique userid/groupid (uid/gid) – but uid=gid for each application. The application we just copied won’t be able to access its own data and user files because the files it needs will have a different uid/gid on the other phone.

First, soft restart the phone so the newly copied application can be found by Android.

If you fail to change the uid/gid of the data files for the application you will see messages like the following in logcat:

me@server:~$ adb root
me@server:~$ adb shell
root@newphone:/ # logcat |grep -i whatsapp
03-14 15:38:26.368 22689 22689 W pool-6-thread-1: type=1400 audit(0.0:1111): avc: denied { getattr } for path="/data/data/com.whatsapp/databases/_jobqueue-WhatsAppJobManager" dev="dm-0" ino=134223 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:system_data_file:s0 tclass=file permissive=0

03-14 15:38:26.371 22689 22689 W pool-6-thread-1: type=1400 audit(0.0:1112): avc: denied { read } for name="_jobqueue-WhatsAppJobManager" dev="dm-0" ino=134223 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:system_data_file:s0 tclass=file permissive=0

This article illustrates how to find the uid/gid of an app.

me@server:~$ adb root
me@server:~$ adb shell
root@newphone:/ # cat /data/system/packages.xml |grep '<package' |grep whatsapp
    <package name="com.whatsapp" ... userId="10053" ...

Armed with knowing what the new uid/gid should be we can go change the data from the existing uid/gid.

me@server:~$ adb root
me@server:~$ adb shell
root@newphone:/ # ls -alnd /data/data/com.whatsapp/
drwxr-x--x 10 10065 10065 4096 2018-03-14 16:11 /data/data/com.whatsapp/

root@newphone:/ # find /data/data/com.whatsapp -user 10065 -exec chown -h 10053 {} \;
root@newphone:/ # find /data/data/com.whatsapp -group 10065 -exec chgrp -h 10053 {} \;

An alternative which is much, much faster and will change all files (including those that were previously only owned by root):

root@newphone:/ # cd /data/data/com.whatsapp
root@newphone:/data/data/com.whatsapp # chown -Rh 10053 .
root@newphone:/data/data/com.whatsapp # chgrp -Rh 10053 .

After this you should always restore SELinux tags using:

root@newphone:/ # cd /data/data/com.whatsapp
root@newphone:/data/data/com.whatsapp # restorecon -Rv .

If you’re using LineageOS 14.1 (“Nougat”) then you will also have to explicitly give your app permission to read storage (for the media that has been stored). Otherwise you might get messages like the following in logcat if you try and open a picture:

03-18 15:10:09.137 xxxxx xxxxx E BitmapFactory: Unable to decode stream: java.io.FileNotFoundException: /storage/emulated/0/WhatsApp/Media/WhatsApp Images/Sent/IMG-20180122-WA0000.jpg (Permission denied)

To do this on your phone:

  • open Settings
  • find and open Apps
  • navigate to your app (e.g. “WhatsApp”) and open
  • open Permissions
  • enable Storage permission
  • (you may want to enable other permissions, too, depending on what you want your app to be able to do)

This should largely do it. Maybe you’ll need to soft reboot your phone. If WhatsApp works after this then you may want to consider going to Google Play and attempting to install WhatsApp – it should recognise that the app is already installed and offer to upgrade – so upgrade.

ZTE Axon 7 LineageOS 14.1 Terminal Permission Denied

You’ve rooted your A2017G ZTE Axon 7 and put LineageOS 14.1 on. You’ve also installed, through TWRP, the addonsu-14.1-arm64-signed.zip package from LineageOS 14.1 extras (because the device is of arm64 architecture).

So when you install Terminal Emulator (jackpal.androidterm) from Google Play and start it up you’re puzzled when you get the message “Permission denied” when you try and do anything:

axon7:/ $ ls
ls: .: Permission denied
1|axon7:/ $

The solution is to run /system/bin/su from the command line – then allow Terminal Emulator su (super user) privileges when a dialog pops up as a result.

axon7:/ $ /system/bin/su
axon7:/ #

From now on, when you start a Terminal Emulator session, you need to just type su at the beginning of each session.

axon7:/ $ su
axon7:/ #

USB Tethering From CyanogenMod Android to Ubuntu Trusty 14.04

My laptop could not connect to the hotel’s WiFi but my mobile phone could. So I went into my phone settings, selected “…More”, selected “Tethering & portable hotspot”, and enabled “USB tethering”. This was while my phone was configured to be in “charge only” mode on USB.

My phone was attached to my Ubuntu computer by USB cable. And if I clicked on the Network Manager applet on my start bar (using Xubuntu) it showed me the option of “Ethernet Network (my phone model)” but it was greyed out. So Ubuntu had detected the phone had tethering turned on but wasn’t able to connect to it.

Automatic Option

Click on the Network Manager applet. At the bottom of the menu choose “Edit”.

Press “Add” to add a network connection.

Choose a connection type of “Ethernet” from the drop-down and press the “Create…” button.

Give the connection a name, e.g. “Tethering My Phone USB”. Select your USB interface from the drop down list of “Device MAC address” on the “Ethernet” tab (which is opened by default).

Choose “Save…” and the tethered network should automatically begin to work.

Manual Option (if all else fails)

The solution was to open a terminal and run:

$ sudo ifconfig usb0 up
$ sudo dhclient usb0

Now I had an IP address assigned to my usb0 interface and a default route.

Restoring SELinux Labels After Restoring From Data Backup To Android

So I made a major error of judgement and tried to put Marshmallow CyanogenMod 13 onto my LG G3 (d855). Sure, for a while it raced along nice and fast, but in the end turned into an utter disaster when, overnight, it decided to go into an endless CPU loop resulting in rebooting every 10 minutes or so back into another CPU loop. Making the phone very hot and essentially useless. Well enough of that long story. I tried to downgrade using a backup I made earlier back into Lollypop CyanogenMod 12.1.

But K-9 mail was not starting.

I ran:

# adb root
# adb shell
root@d855:/ # logcat |grep com.fsck.k9
W/com.fsck.k9(13997): type=1400 audit(0.0:2058): avc: denied { write } for name="preferences_storage" dev="mmcblk0p43" ino=530653 scontext=u:r:untrusted_app:s0 tcontext=u:object_r:system_data_file:s0 tclass=file
E/SQLiteDatabase(13997): Failed to open database '/data/data/com.fsck.k9/databases/preferences_storage'.
E/SQLiteDatabase(13997): 	at com.fsck.k9.preferences.Storage.openDB(Storage.java:47)
E/SQLiteDatabase(13997): 	at com.fsck.k9.preferences.Storage.loadValues(Storage.java:180)
E/SQLiteDatabase(13997): 	at com.fsck.k9.preferences.Storage.(Storage.java:203)
E/SQLiteDatabase(13997): 	at com.fsck.k9.preferences.Storage.getStorage(Storage.java:158)
E/SQLiteDatabase(13997): 	at com.fsck.k9.Preferences.(Preferences.java:40)
E/SQLiteDatabase(13997): 	at com.fsck.k9.Preferences.getPreferences(Preferences.java:27)
E/SQLiteDatabase(13997): 	at com.fsck.k9.K9.onCreate(K9.java:578)
E/AndroidRuntime(13997): Process: com.fsck.k9, PID: 13997
E/AndroidRuntime(13997): java.lang.RuntimeException: Unable to create application com.fsck.k9.K9: android.database.sqlite.SQLiteException: not an error (code 0): Could not open the database in read/write mode.

Turns out that first line from the log there is SELinux denying write access to the file.

I discovered I needed to run the restorecon command which would apply the necessary labellings for the files in /data/data using the rules in /file_contexts.

# adb root
# adb shell
root@d855:/ # restorecon -Rv /data/data/com.fsck.k9

But there is another reason why an application may be unable to access its database. Wrong user. What user does an application run as? That is found in /data/system/packages.list:

root@d855:/ # grep com.fsck.k9 /data/system/packages.list
com.fsck.k9 10076 0 /data/data/com.fsck.k9 default 3003,1028,1015

So with that information I could set the owner of the data files to that required by the application:

root@d855:/ # chown -R 10076 /data/data/com.fsck.k9

Manually Changing Weather Location on CyanogenMod Clock Widget

So you’re travelling but your CyanogenMod (Android) clock widget isn’t automatically changing the weather information to suit your new location? You can change it manually.

First tap on your clock widget over the displayed time on your home screen.

Tap on the current time on the clock widget

Tap on the current time on the clock widget

Next touch the icon with three dots arranged vertically (at the bottom right of the display).

Touch the icon with 3 vertical dots

Touch the icon with 3 vertical dots

From the pop-up menu choose “Widget settings”.

Choose “Widget settings”

Now select the “Weather panel” settings.

Select the “Weather panel” settings

Now turn on “Custom location”.

Enable “Use custom location”

Tap the “Location” field to edit it.

Tap the “Location” field to change it

Enter the new location using the keyboard.

Type in the desired location

Type in the desired location

Finally select which specific location was found from a list.

Choose specific location from the presented list

Choose specific location from the presented list

That’s it!

Adding TLS/SRTP Account to CSipSimple on Android

I signed up for a new VoIP SIP account with Australian Phone Company. They offered secure VoIP accounts using TLS/SRTP and local DID numbers which made them an excellent choice.

The question was how to set up TLS/SRTP in CSipSimple? I followed the advice in this forum post which forms the basis of this tutorial.

First click on the account list button in CSipSimple as circled in red in the following image.

Select the account list button in CSipSimple

Select the account list button in CSipSimple

Then choose to add a new account.

Add a new account in CSipSimple

Add a new account in CSipSimple

Scroll down the selection of account creation wizards until you find “Expert” and select this.

Find and select the Expert wizard in CSipSimple

Find and select the Expert wizard in CSipSimple

Enter your account name, account ID, registration URI (you can use a full domain name here but I put in an IP address for speedy connect that avoids the domain lookup), username and password.

Enter standard registration details into CSipSimple

Enter standard registration details into CSipSimple

Then scroll down the items you can configure in this wizard until you find “Transport”. Choose this.

Find transport in the wizard and select it in CSipSimple

Find transport in the wizard and select it in CSipSimple

Next select “TLS” as your transport. This can only be done in the Expert wizard which is why we choose it.

Select TLS as your transport in CSipSimple

Select TLS as your transport in CSipSimple

Finally scroll further down the wizard and find the SRTP option and choose it to be mandatory for this connection.

Set SRTP to be mandatory for this connection in CSipSimple

Set SRTP to be mandatory for this connection in CSipSimple

And you’re done, you can save the connection!

You may have to go into the generic settings for CSipSimple and turn “TLS” to enabled, and SRTP to “optional” in order for this to work.

This is what I did and I have a secure connection to Australian Phone Company and a local Australian phone number.