Tuesday, July 22, 2014

Etherape as root

This has popped up as an occasional question in the forums.
If you monitor network activity using Etherape, it's worthless as a user level application. It must be run as root. But running as root requires opening a terminal and entering a password.

Here's how to change the settings in Ubuntu 14.04 to create an Etherape (as root) launcher in Unity that won't require a password. It has only been tested with 14.04. Unity development moves fast - this method may not work for a different version of Ubuntu.

It requires a minor edit to the /etc/sudoers file, and minor edits to two .desktop files. It's easy to undo if you change your mind.


1) I like to document my changes. I have three changes to keep track of, in case I change my mind. So I'm adding a new subdirectory to keep track of this change.

mkdir my_customizations/etherape_launcher




2) Edit the sudoers file. This is the dangerous part. Pay close attention.

You need to know your login account name (fred, Jane, dog, etc.)
You need to know your hostname as shown in /etc/hostname.

$ sudo visudo


At the bottom of the file, add one line. Spacing, spelling, and CAPS are important.

account_name hostname = NOPASSWD: /usr/bin/etherape


Use your account_name and hostname, of course.

Do a CTRL+X to exit, and hit Y to confirm the exit.
Now look carefully at the screen.

If visudo is happy with your changes, it will print no output, but simply return you to a command prompt.

If the screen shows an error, type 'edit' and go right back in to fix the error. If you don't know how to fix the error, delete your added line and save. You MUST NOT exit with a broken sudoers file - a broken sudoers file is 100% guaranteed to break your system! It's very important that you pay close attention to any error messages visudo prints when you try to exit.



3) Test: Open a NEW terminal window, and try 'sudo etherape'.
It should no longer ask for a password.

If you get sudo errors instead, you have broken your system! Stop! Save all your data! Reboot into a recovery console (since you cannot use sudo) and edit /etc/sudoers to undo your changes. Go to an Ubuntu help channel and ask for help on how to do this!



4) Now that we know the sudo change works, move the sudoers line to a separate file

We used visudo to ensure the correct syntax and a working sudoers file. But it's not a great idea to leave undocumented system changes laying around in system-installed (and system-rewritable) files. So let's move the customization to a separate file so we can keep track of it.

$ sudo nano /etc/sudoers.d/etherape

File contents:

# Allows 'sudo etherape' to be run, including from a launcher, wthout password

my_account my_hostname = NOPASSWD: /usr/bin/etherape


Remember to change my_account and my_hostname to the proper values!

Test your change using 'sudo etherape'. It should work without a password, and without an error message.

Go back into visudo and delete the etherape line at the bottom.

Test your change once more using 'sudo etherape'. It should work without a password, and without an error message.


Now /etc/sudoers is back to it's original state, and our change is safely in a separate file. If we want to delete the change, we simply delete /etc/sudoers.d/etherape.



5) Let's link this new sudoers file to our documentation so we can find it again.

$ sudo ln /etc/sudoers.d/etherape \
          my_customizations/etherape_launcher/




6) Edit the etherape-root .desktop file

$ sudo nano /usr/share/applications/etherape-root.desktop


File contents:

[Desktop Entry]
Name=EtherApe (as root)
Type=Application
Categories=GNOME;System;Network;
Comment=Graphical Network Monitor
Comment[es]=Monitor Gráfico de Red
#TryExec=su-to-root                            <-- Comment out
#Exec=su-to-root -X -c /usr/bin/etherape        <-- Comment out
Exec=/usr/bin/sudo /usr/bin/etherape -i wlan0     <-- Add line
Icon=etherape
Terminal=false




7) Edit the etherape (user) .desktop file to hide it. We don't want to delete it; the package manager will expect it to be there.

$ sudo nano /usr/share/applications/etherape.desktop


#[Desktop Entry]           <-- Comment out
Version=1.0
Encoding=UTF-8
Name=EtherApe
GenericName=EtherApe
Comment=Graphical Network Monitor
Comment[es]=Monitor Gráfico de Red
Exec=etherape
Terminal=false
Type=Application
Icon=etherape
Categories=GNOME;System;Network;




8) Let's save links to the changed desktop files so I can find them again someday:

$ sudo ln /usr/share/applications/etherape-root.desktop \
          my_customizations/etherape_launcher/
$ sudo ln /usr/share/applications/etherape.desktop \
          my_customizations/etherape_launcher/




9) Test the new .desktop file.

Open Unity's Dash.
Close any existing search.
Open a new search for Etherape. There should be only one option now: Etherape (as root).
Open it. It should show all interfaces without requiring a password or prompting an error.
Lock it to the Launcher (right-click).
Close etherape. The launcher icon should remain.
Open it again from the launcher. It should work

How to recover from a broken sudo

You cannot fix a broken sudoers file while logged in. You would need access to sudo for that...and it's broken. You can't get to the root account because it's locked in normal use.

So you need to reboot into a condition where root is unlocked and available.

1) Save all your work and then reboot.

2) Hold down the left SHIFT button to get to the GRUB prompt.
If you get a pretty splash screen, reboot and hold down the button earlier.

3) At the Grub prompt, select Advanced Options

4) At the Advanced Options prompt, select any Recovery Console

5) Watch the boot technobabble run across your screen.

6) At the Recovery Console prompt, select Drop To A Root Shell

7) You should see a warning about a read-only filesystem.
The prompt should look like '#'

8) Remount the root filesystem as read-write instead of read-only. We want to make changes that stick.

# mount -o remount /


9) Try a test write. It should not cause an error:

# date > /tmp/test


10) Okay, now go into visudo and fix your mistake.

11) When complete, reboot into normal Ubuntu.

# shutdown -r now

Tuesday, July 8, 2014

Simple geolocation in Ubuntu 14.04

Geolocation means 'figuring out where a spot on the Earth is'.

Usually, it's the even more limited question 'where am I?'


GeoClue


The default install of Ubuntu includes GeoClue, a dbus service that checks IP address and GPS data. Since 2012, when I last looked at GeoClue, it's changed a bit, and it has more backends available in the Ubuntu Repositories.

 

Privacy

Some commenters on the interwebs have claimed that GeoClue is privacy-intrusive. It's not. It merely tries to figure out your location, which can be handy for various services on your system. It doesn't share or send your location to anybody else.

dbus introspection and d-feet

You would expect that a dbus application like GeoClue would be visible using a dbus introspection tool like d-feet (provided by the d-feet package).

But there's a small twist: D-feet can only see dbus applications that are running. It can only see dbus applications that active, or are inactive daemons.

It's possible (and indeed preferable in many circumstances) to write a dbus application that is not a daemon - it starts at first connection, terminates when complete, and restarts at the next connection. D-feet cannot see these when they are not running.

Back in 2012, GeoClue was an always-on daemon, and always visible to d-feet.
But in 2014 GeoClue is (properly) no longer a daemon, and d-feet won't see GeoClue if it's not active.

This simply means we must trigger a connection to GeoClue to make it visible.
Below are two ways to do so: The geoclue-test-gui application, and a Python3 example.




geoclue-test-gui


One easy way to see GeoClue in action, and to make it visible to d-feet, is to use the geoclue-test-gui application (included in the geoclue-examples package)

$ sudo apt-get install geoclue-examples
$ geoclue-test-gui





GeoClue Python3 example


Once GeoClue is visible in d-feet (look in the 'session' tab), you can see the interfaces and try them out.

Here's an example of the GetAddress() and GetLocation() methods using Python3:

>>> import dbus

>>> dest           = "org.freedesktop.Geoclue.Master"
>>> path           = "/org/freedesktop/Geoclue/Master/client0"
>>> addr_interface = "org.freedesktop.Geoclue.Address"
>>> posn_interface = "org.freedesktop.Geoclue.Position"

>>> bus        = dbus.SessionBus()
>>> obj        = bus.get_object(dest, path)
>>> addr_iface = dbus.Interface(obj, addr_interface)
>>> posn_iface = dbus.Interface(obj, posn_interface)

>>> addr_iface.GetAddress()
(dbus.Int32(1404823176),          # Timestamp
 dbus.Dictionary({
     dbus.String('locality')   : dbus.String('Milwaukee'),
     dbus.String('country')    : dbus.String('United States'),
     dbus.String('countrycode'): dbus.String('US'),
     dbus.String('region')     : dbus.String('Wisconsin'), 
     dbus.String('timezone')   : dbus.String('America/Chicago')}, 
     signature=dbus.Signature('ss')),
 dbus.Struct(                 # Accuracy
     (dbus.Int32(3),
      dbus.Double(0.0),
      dbus.Double(0.0)),
      signature=None)
)

>>> posn_iface.GetPosition()
(dbus.Int32(3),               # Num of fields
 dbus.Int32(1404823176),      # Timestamp
 dbus.Double(43.0389),        # Latitude
 dbus.Double(-87.9065),       # Longitude
 dbus.Double(0.0),            # Altitude
 dbus.Struct((dbus.Int32(3),  # Accuracy
              dbus.Double(0.0),
              dbus.Double(0.0)),
              signature=None))

>>> addr_dict = addr_iface.GetAddress()[1]
>>> str(addr_dict['locality'])
'Milwaukee'

>>> posn_iface.GetPosition()[2]
dbus.Double(43.0389)
>>> posn_iface.GetPosition()[3]
dbus.Double(-87.9065)
>>> lat = float(posn_iface.GetPosition()[2])
>>> lon = float(posn_iface.GetPosition()[3])
>>> lat,lon
(43.0389, -87.9065)

Note: Geoclue's accuracy codes



Ubuntu GeoIP Service


When you run geoclue-test-gui, you discover that only one backend service is installed with the default install of Ubuntu - the Ubuntu GeoIP service.

The Ubuntu GeoIP service is provided by the geoclue-ubuntu-geoip package, and is included with the default install of Ubuntu 14.04. It simply queries an ubuntu.com server, and parses the XML response.

You can do it yourself, too:

$ wget -q -O - http://geoip.ubuntu.com/lookup

<?xml version="1.0" encoding="UTF-8"?>
<Response>
  <Ip>76.142.123.22</Ip>
  <Status>OK</Status>
  <CountryCode>US</CountryCode>
  <CountryCode3>USA</CountryCode3>
  <CountryName>United States</CountryName>
  <RegionCode>WI</RegionCode>
  <RegionName>Wisconsin</RegionName>
  <City>Milwaukee</City>
  <ZipPostalCode></ZipPostalCode>
  <Latitude>43.0389</Latitude>
  <Longitude>-87.9065</Longitude>
  <AreaCode>414</AreaCode>
  <TimeZone>America/Chicago</TimeZone>
</Response>




GeoIP


The default install of Ubuntu 14.04 also includes (the confusingly-named) GeoIP. While it has the prefix 'Geo', it's not a geolocator. It's completely unrelated to the Ubuntu GeoIP service. Instead, GeoIP is a database the IP addresses assigned to each country, provided by the geoip-database package. Knowing the country of origin of a packet or server or connection can be handy.

geoip-database has many bindings, including Python 2.7 (but sadly not Python 3). Easiest is the command line, provided by the additional geoip-bin package.

$ sudo apt-get install geoip-bin
$ geoiplookup 76.45.203.45
GeoIP Country Edition: US, United States




GeocodeGlib


Back in 2012, I compared the two methods of geolocation in Ubuntu: GeoClue and GeocodeGlib. GeocodeGlib was originally intended as a smaller, easier to maintain replacement for GeoClue. But as we have already seen, GeoClue has thrived instead of withering. The only two packages that seem to require GeocodeGlib in 14.04 are gnome-core-devel and gnome-clocks
GeocodeGlib, provided by the libgeocode-glib0 package, is no longer included with a default Ubuntu installation anymore, but it is easily available in the Software Center.

sudo apt-get install gir1.2-geocodeglib-1.0


That is the GTK introspection package for geocodeglib, and it pulls in libgeocode-glib0 as a dependency. The introspection package is necessary.

Useful documentation and code examples are non-existent. My python code sample from 2012 no longer works. It's easy to create a GeocodeGlib.Place() object, and to assign various values to it (town name, postal code, state), but I can't figure out how to get GeocoddeGlib to automatically determine and fill in other properties. So even though it seems maintained, I'm not recommending it as a useful geolocation service.