Tuesday, September 20, 2016

Controlling Arduino with DX-Forth

Forth is a very powerful programming language. It can scale from very low level, near-assembly code, which you can run on Arduino Uno with 2 kilobytes of RAM, to very high level, domain-specific language, suitable for modern home computers (you can even implement object-oriented Forth in the Forth itself).

Due to its inherently low-level nature, Forth is not very popular among contemporary programmers. It is often considered a high level assembly - it stores and manipulates data using anonymous data stack (and optional floating point stack), and variables are nothing more than labelled memory cells. But at the same time Forth provides a set of tools to create building blocks, which can be used to make even the most sophisticated software (like satellite antenna controllers). Developers who understand how a CPU works and are not afraid to juggle with bytes, usually have no fear of Forth and find it a very smart and productive tool.

There are many implementations of Forth for almost all existing operating systems (many of them are self-contained and can run without an operating system at all, like amForth or Jupiter ACE's Forth). Among them there is excellent, and still actively maintained, DX-Forth for CP/M. Thanks to amazing work of Marcelo Dantas and his fantastic CP/M emulator for Arduino Due, and my humble contribution in the form of CP/M Arduino Interface, you can now enjoy writing software for Arduino using DX-Forth.

RunCPM emulator contains an example Forth application, PHOTOLED.4TH. It begins with a couple of Forth words, which define the Arduino interface. The first one is pinmode:
: pinmode ( val pin -- ) 8 lshift + 220 bdos drop ;
From its declaration, pinmode expects two bytes on a stack, the first one being a value to assign to the pin, and the pin number. It uses a word bdos, which DX-Forth defines as follows:
BDOS ( DE u -- A )
Perform CP/M BDOS call number u. DE is the value passed to the DE register. Return the contents of the A register.
So first we need to put on the stack some value, which will then be passed to CPU register DE, and then a BDOS function number. Question is, what should be passed as DE and the call number? The answer can be found in the Arduino interface description:
BDOS function 220 (0xDC) - PinMode:
LD C, 220
LD D, pin_number
LD E, mode (0 = INPUT, 1 = OUTPUT, 2 = INPUT_PULLUP)
By convention, you pass BDOS function number in CPU register C, and arguments in registers D and E. All those registers are 8-bit, but can be combined in 16-bit pairs: BC, DE and HL. So for the Forth word bdos we need two numbers to be put on the stack:
- First, a 16-bit number with pin number in high 8-bits and mode (0, 1 or 2) in low 8-bits. This number will be passed to CP/M through CPU register pair DE.
- Second, number 220 as the function call.
For example, to set pin 13 into output mode, we need the following command in Forth:
3329 220 bdos
3329 is a product of 13 * 256 + 1. Multiplication by 256 is the same as shifting 8 bits left. The pinmode does exactly that: it takes the pin number from the stack, shifts it 8 bits left, add the next value from the stack (val) and calls BDOS function 220:
: pinmode ( val pin -- ) 8 lshift + 220 bdos drop ;
The result of the call can be ignored, so the return value is simply dropped.

All the next Arduino interface words follow the same schema:
: dout ( val pin -- ) 8 lshift + 222 bdos drop ;
: aout ( val pin -- ) 8 lshift + 224 bdos drop ;
With din we want to preserve the result of bdos call on the stack, so we don't drop it:
: din ( pin -- n ) 8 lshift 221 bdos ;
Additionally, with word ain, we use fdos instead of bdos:
: ain ( pin -- n ) 8 lshift 223 fdos drop ;
It's because function number 223 makes a call to AnalogRead, which returns a 10-bit value and needs more than one 8-bit register to pass the result back to Forth. The value of AnalogRead is returned by the Arduino interface in register pair HL, and fdos returns this pair along with register A, unlike bdos, which returns only A:
FDOS ( DE u -- HL A )
Perform CP/M BDOS call number u. DE is the value passed to the DE register. Return the contents of the HL and A registers.
Since we need HL only, we can drop what has been returned in A, and leave only HL on the stack.

Now we can define words which use pinmode, din, dout, ain and aout. For example to turn a led on and off we can define the following words:
: ledon ( pin -- ) 1 over pinmode 1 swap dout ;
: ledoff ( pin -- ) 1 over pinmode 0 swap dout ;
Both words require the pin number to be on the stack. They both put the pin to output using pinmode and then set its state to HIGH (1) or LOW (0) respectively.

A more complicated example requires a simple circuit to be built. It should consist of a LED and a LDR (photoresistor) according to the following diagram:
The LED is connected to pin D9 (it can't be any digital pin, it must be PWM capable) through a 68 ohm resistor (unlike Uno, Arduino Due outputs 3.3V), and the LDR is connected to pin A8 and uses a 10k ohm pull-down resistor. We want a LED to light up when it gets darker, and get dim when it's not. Because, as you remember, analog input can return values with 10-bit resolution, and digital output accepts only 8-bit values, we need to calculate the LED intensity according to the following formula:
LED = 255 - (LDR / 4)
This can be achieved through a new word fade (it uses shifting 2 bits to the right to do a division by 4):
: fade ( led ldr -- ) ain 2 rshift 255 swap - swap aout ;
Now when you run the following command in DX-Forth:
9 8 fade
the LED intensity gets adjusted according to the current value returned by the LDR.

Of course it is tedious to run it by hand. We can define a new word, which will run fade in a loop:
: run begin 9 8 fade 100 ms key? until ;
It runs 9 8 fade with 100 millisecond delay until any key gets pressed. The final result looks like this:



If the LED responds too slow, or flickers, you should try tuning the delay. You can also get rid of it completely:
: run begin 9 8 fade key? until ;

Wednesday, September 14, 2016

The first operating system for Arduino

RunCPM, a CP/M emulator for Arduino Due, can now use Arduino's analog and digital pins thanks to five additional BDOS calls, which virtually makes it the first (and so far the only one) fully fledged, professional operating system for Arduino. You can write brand new, or modify any existing, CP/M software, using any programming language available for CP/M platform, to interface Arduino devices. The only requirement is that it should allow you to call arbitrarily chosen BDOS functions (natively or via inline assembly code), because RunCPM uses newly defined routines (220 - 224), unused by standard CP/M implementations.

RunCPM includes a few sample programs in Assembly, Microsoft Basic, Hi-Tech C, Turbo Pascal and DX-Forth to get you started. I also prepared a short video tutorial showing the Turbo Pascal example in action:



A few tips:

Because analogRead returns values that won't fit in a single byte, when calling function 223 in Turbo Pascal you should use BdosHL instead of Bdos to get the value returned in HL register pair, like this:
writeln(BdosHL(223, pin shl 8);
The same applies to Hi-Tech C - see PHOTO.C and PHOTO.PAS examples.

Also, since MBasic does not allow direct BDOS calls, I used USR functions to call small assembly procedures encoded in DATA lines.

Happy coding on Arduino!

Saturday, July 16, 2016

CP/M on a stick

CP/M, created by Gary Kildall, was for early computers what Android is for today's smartphones and tablets. It was an operating system that could be easily customized to run on any machine with Intel 8080 or Zilog Z80 processor, and was de-facto standard during 1970s and 1980s, running on hundreds of computers coming from different manufacturers, from Altair 8800 to early IBM PCs. Unfortunately, computers that can still run CP/M are very rare and expensive, and their modern counterparts, made by hobbyists, are either also quite expensive (like Altair 8800 clone) or require some more skills and effort than just simple soldering to build (like Grant Searle's Multikomp).

Luckily for all who want to have their own CP/M computer, there is an Arduino based solution, which is quite cheap and very simple to build. All you need is Arduino Due or its clone and an SD shield (like this one), which you have to fit on top of your Arduino board.
Now you need to download Marcelo Dantas' RunCPM, which is a multiplatform CP/M emulator, and upload it to the board with Arduino IDE. I managed to build RunCPM without problems on Ubuntu 12.04 using version 1.6.7 for Linux 64bits, just remember to install support for Arduino Due with Boards Manager under Tools menu. Next, connect the board to your computer with a micro USB cable inserted into the programming port of Arduino, and then select "Arduino Due (Programming Port)" for the Board and the Port (remember: Arduino must be connected to the computer). Open RunCPM.ino project, select "Verify/Compile" under the Sketch menu to produce the binary image, and then select "Upload" to flash the board with it.

Now, when you have a fully fledged Z80 board, all you need is the CP/M operating system. RunCPM comes with the most popular version 2.2 of CP/M. To run it, format an SD card as FAT32, and put the CPM22.BIN from RunCPM repository in the main folder of the card. Also create folders "A" and "B" - these will be your disk drives, everything you put in there will appear to the system as located on disks "A:" and "B:" respectively. You can create folders from A up to P (as this is the limit of CP/M itself). Now turn off the Arduino, put the card into the SD card shield, and connect it back. You now have the smallest CP/M computer in the world up and running.

Ok, the system has started, but how do you talk to it? Well, you need a terminal, just like for a real CP/M machine! Depending on your operating system, you will need a terminal software. For Windows I recommend PuTTY, in Linux you can install minicom package. Set serial transmission parameters to 8N1, speed to 9600 bauds, and select a serial port to which your CP/M machine is connected. In Ubuntu it's:
minicom -b 9600 -o -D /dev/ttyACM0
With MacOSX it's even simpler, just start typing "screen /dev/tty.usb" from the terminal and press TAB to unfold the device full name. In my case the full command looks as follows:
screen /dev/tty.usbmodem1421
If you configured the connection correctly, you will now be able to work on your Arduino board like on a real CP/M computer.
Just remember to disconnect when leaving the terminal session (ctrl+a and then z in minicom or ctrl+a and then ctrl+\ in OSX) otherwise you may get some strange errors when trying to reconnect.

I did some speed tests with prime sieve Basic benchmark by John Metcalf in Microsoft Basic-80 and Z80 Instruction Exerciser and compared them with results achieved by z80pack simulations at different CPU clocks. As far as I can tell Arduino Due with RunCPM runs very close to a 5MHz Z80 computer, which makes it even more realistic.

RunCPM allows you to have your own, modern, inexpensive CP/M computer, running at the speed of original Z80 based hardware, and use all the huge library of CP/M software with it. At the same time, you can connect to it with USB instead of a serial cable, you can easily exchange software with an SD card, it takes very little power, and last but not least - it easily fits in a pocket.

Thursday, April 21, 2016

NetUSBee configuration for Atari ST

NetUSBee is a network card for 16-bit Atari computers, which is compatible with modern ethernet devices. To make it work under plain TOS you need Sting drivers; you can find those drivers, as well as the installation manual, here.
Unfortunately, the manual covers only peer to peer connection, and it's not enough when you want to connect your computer to the Internet. Two importand pieces missing are gateway and DNS configuration.

Gateway, as the name suggests, is a network device which passes traffic from your host to the Internet, and vice versa. If you configure an Atari and a PC as specified in the manual, the Atari will have an IP address 192.168.255.1, and the PC's IP address will be 192.168.255.2. If you enable Internet connection sharing in the PC, it will become a gateway for the Atari, and the Sting drivers must be properly configured for it.
To do this, run a text editor (I strongly recommend Everest for this purpose), open file C:\STING\ROUTE.TAB and scroll to the end. You will see the following lines:
192.168.255.2   255.255.255.0   EtherNet        192.168.255.1
0.0.0.0         0.0.0.0         Modem 1         0.0.0.0
This is so called routing table; it tells the host which gateway it should use when communicating with a specific network. Because the entries above make no sense for NetUSBee configuration described in the manual, you should remove them. Instead, replace them with the following entry:
0.0.0.0 0.0.0.0 EtherNet 192.168.255.2
This defines so called "default gateway". What it says is that for any IP address ("0.0.0.0" means "any") in any subnetwork (again: "0.0.0.0") the traffic should be passed through the computer connected to the ethernet interface, with IP address "192.168.255.2" (it's the PC's address).
Now very important note: you should use tabs to separate the column entries, so the line would be typed in like this:
0.0.0.0<TAB>0.0.0.0<TAB>EtherNet<TAB>192.168.255.2
If you use spaces, it will not work, and some editors silently replace tabs with spaces - this is why I recommend Everest (but QED will work as well).

Second thing you need to set up is a Domain Name Server configuration. DNS is a service used to translate human readable names into IP addresses - when you type in "blogspot.com" in your browser, it will contact a DNS server first, to ask what IP number hides behind it.
To configure DNS in Sting, open C:\STING\DEFAULT.CFG in text editor, find the line which says:
NAMESERVER  =
and enter your Internet provider's DNS addresses. If you don't know what they are, you can use Google's:
NAMESERVER  = 8.8.8.8, 8.8.4.4
Save modified DEFAULT.TAB and ROUTER.TAB files and restart the computer. If you configured Internet Connection Sharing properly in the PC, you will be able to use various Internet applications on your Atari.

Monday, February 29, 2016

Protecting privacy with personal VPN

There are more and more examples of privacy violation in the Internet. Even in supposedly democratic countries, the governments want to know what the citizens are up to, "just in case". For example, in my country the police have recently been given the power to eavesdrop phone calls and intercept any forms of electronic transmission, without prior permission from the court.

Thinking that you have nothing to worry about if you do nothing wrong is naive. Any information gathered about you can be sooner or later used against you. It can also leak, be stolen, or even sold by a corrupted police officer. Remember, that your home network consists of many devices, not only your personal computer (or computers). Your phones, tablets, TV boxes, and sometimes even your refrigerator as well as other home appliances, constantly transmit various data over the network. Many of them use RESTful APIs over unsecured HTTP channels, because it's simpler and helps keeping the costs low. But this is only part of the problem. Even if you make sure you use only encrypted HTTPS protocol, your software still needs to perform unencrypted DNS queries to translate domain names to IP addresses. This way anyone eavesdropping your network traffic can gather information about the sites you visted, how often and for how long. This so called "metadata" can reveal much more information about you than the actual content you view with your Internet browser. Metadata can tell a lot about your interests, habits, in which banks you keep your money (because you visit their sites often), what you buy and where you do your shopping, even where you plan to spend next weekend (because you just checked weather forecast for this place with your mobile phone). It can even be used to check if you are at home and whether it can be safely robbed. You can be profiled quickly and without much effort, just by intercepting transmission from you home router. Moreover, your traffic can be redirected (through DNS spoofing) to false web servers, to make you reveal some sensitive data, like logins and passwords. Also, your devices automatically synchronizing time over the Internet can be tricked into using a particular timestamp. The timestamp is a crucial element of digital cryptography: controlling the clock of your computer will make it generate predictable cryptographic keys, which then can be easily broken.

So, how can you protect yourself? My solution was to built a personal Virtual Private Network. I have a VPN server hosted in the cloud, and a home router configured as VPN client, passing all my Internet traffic through that server over an encrypted "tunnel". Of course it makes my Internet connection a little slower, because every data packet, including metadata queries (like DNS and NTP), must be encrypted and transferred to the cloud, where it "jumps out" and begins its regular way through the network, but this way my network traffic cannot be eavesdropped. The server is hosted in another country, so the government can no longer watch me "just in case", because they need a court permission to claim my data from a foreign cloud provider.

How is this better than TOR, or any other peer-to-peer network? - you may ask. With TOR, the idea is that your data travels around the world through other people's computers, but also other people's data travels through yours, and you have no control over it. Frankly speaking, I don't feel comfortable knowing that my computer can be indirectly used by criminal offenders for their illegal activities.

I used tinc to build the VPN. It's fairly easy to configure and available for many operating systems. I used Ubuntu for the server, and OpenWRT router for the client, but you can use a different configuration (for example an old PC with Linux as a router).

1. Server configuration.

First, you need to set up a server. Tinc has very minimal hardware requirements (a few megabytes of disk space and memory), and I use it successfully with Ubuntu 14.04 installed on a virtual server with 512MB RAM. First, you need to be root to perform all necessary tasks. Swith to user root with:
sudo bash
Then install the tinc package:
apt-get install tinc
Next, create a proper directory tree and configuration files using the following commands:
mkdir -p /etc/tinc/vpn/hosts
echo 'vpn' > /etc/tinc/nets.boot
echo 'ifconfig $INTERFACE 10.8.0.1 netmask 255.255.255.0' > /etc/tinc/vpn/tinc-up
chmod +x /etc/tinc/vpn/tinc-up
echo 'ifconfig $INTERFACE down' > /etc/tinc/vpn/tinc-down
chmod +x /etc/tinc/vpn/tinc-down
echo 'Name=server' > /etc/tinc/vpn/tinc.conf
echo -e 'Subnet=10.8.0.0/24\nMode=switch' > /etc/tinc/vpn/hosts/server
This makes the basic scaffolding of your VPN server configuration. Now you must add the server's public IP address to the /etc/tinc/vpn/hosts/server configuration file (replace "xxx.xxx.xxx.xxx" with the public IP address of the server):
echo 'Address=xxx.xxx.xxx.xxx' >> /etc/tinc/vpn/hosts/server
Notice ">>" instead of ">" when using this command!
The file /etc/tinc/vpn/hosts/server should now have the following content:
Subnet=10.8.0.0/24
Mode=switch
Address=xxx.xxx.xxx.xxx
Where, again, "Address=" field contains the public IP address of your server.
Now you need to generate an encryption key used to protected data transmission over the VPN tunnel:
tincd -n vpn -K
Confirm the defaults pressing Enter. After this operation you will see a new file /etc/tinc/vpn/rsa_key.priv containing the private key, and a new section in /etc/tinc/vpn/hosts/server file containing the public key. As their names state, the public key can be visible to anyone, and the private key must remain secret and cannot be revealed.

You can now start tinc server (as user root) with:
tinc -n vpn
Now you should be able to list the new network interface with:
ifconfig vpn
And it sould have a section saying "inet addr:10.8.0.1". You can turn it off for now with:
tincd -n vpn -k
Notice lower case "-k", not uppercase "-K", which was used to generate the key.

2. Client configuration.

Now for the router (client) configuration, you also need to install tinc package. With OpenWRT you can do it either through the web interface or via the command line with the following command:
opkg update && opkg install tinc
With Ubuntu as the client the procedure is the same as with the server:
sudo apt-get install tinc
Now you need to configure the client. On the router (or the computer acting as a router) switch to user root with:
sudo bash
Then run the following set of commands:
mkdir -p /etc/tinc/vpn/hosts
echo 'vpn' > /etc/tinc/nets.boot
echo 'ifconfig $INTERFACE 10.8.0.2 netmask 255.255.255.0' > /etc/tinc/vpn/tinc-up
chmod +x /etc/tinc/vpn/tinc-up
echo 'ifconfig $INTERFACE down' > /etc/tinc/vpn/tinc-down
chmod +x /etc/tinc/vpn/tinc-down
echo -e 'Name=client\nConnectTo=server' > /etc/tinc/vpn/tinc.conf
echo -e 'Subnet=10.8.0.0/24\nMode=switch' > /etc/tinc/vpn/hosts/client
tincd -n vpn -K
You are almost done. Your router is now the client of the VPN network, and you need to make sure that the server and the client know about each other, so they can communicate. To achieve this, you need to copy /etc/tinc/vpn/hosts/server file to the client, and /etc/tinc/vpn/hosts/client to the server, so that the contents of the /etc/tinc/vpn/hosts directory is the same on both hosts and contains both client and server files.
Now start tinc both on the client and the server (again, as user root) with:
tincd -n vpn
After a short while the connection should be established and you should be able to ping the server (10.8.0.1) from the client (10.8.0.2) and vice versa. If something goes wrong, you can start tinc with debugger to see what's going on:
tincd -n vpn -d -D
The messages are elaborate enough to allow you quickly locate the source of the problem.

3. Routing setup.

You are almost done here. The client and the server can see each other, but you want to pass all your traffic through this connection, right? So there are two more things to be done.

First, you need to configure the server to forward the traffic between the VPN and the outside world:
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -A FORWARD -s 10.8.0.0/24 -j ACCEPT
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -j MASQUERADE
The above commands should be run every time you start the server, so you can add them to /etc.rc.local startup script (along with the command to start tinc).

Second, on the client side, you need to modify the routing table to make the VPN server a default gateway for all the internet traffic passing through the client (i.e. your router), except the VPN server itself. So, check the routing table on your VPN client with:
route -n
You should see something similar to this:
Destination  Gateway   Genmask       Flags Metric Iface
192.168.1.0  0.0.0.0   255.255.255.0 U     0      br-lan
5.10.64.0    0.0.0.0   255.255.192.0 U     0      eth0.1
0.0.0.0      5.10.64.1 0.0.0.0       UG    0      eth0.1
Look at the Gateway column in the line where the Destination says 0.0.0.0 (meaning: any address) - it's the default gateway. In this case it's 5.10.64.1 and it's the address of you nearest outside world neighbour, probably your Internet provider's modem or router. You need to make sure that you leave this route open for the connection between your client and your server to work.
Do the following magic commands (replacing 5.10.64.1 with your own default gateway, and xxx.xxx.xxx.xxx with the public IP of your VPN server):
route add xxx.xxx.xxx.xxx gw 5.10.64.1
route del default gw 5.10.64.1
route add default gw 10.8.0.1
What happens here is that you leave the traffic to your VPN server via the old route, and replace the gateway for all other traffic with the encrypted VPN. If you did it properly, you should now be able to ping any Internet address from your client. Also, the traceroute (or any other similar utility) should show your traffic going first through the tunnel:
root@OpenWrt:~# traceroute google.com
traceroute to google.com (173.194.204.113), 30 hops max, 38 byte packets
 1  10.8.0.1 (10.8.0.1)  107.456 ms  106.969 ms  114.178 ms
 2  ...
If you don't want to modify the routing table by hand every time you start the router, you can add the commands to /etc/tinc/vpn/tinc-up script. Don't add them to /etc/rc.local, because that script is executed early on startup, when 10.8.0.1 address may not yet be available, and the commands will fail.

Now the last step. You need to allow traffic between your local network and the VPN, similar to what you did on the server side. Assuming your router's (the VPN client's) LAN address is 192.168.1.1 (it's a common default for most routers), you need to run the following commands:
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -A FORWARD -s 192.168.1.0/24 -j ACCEPT
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j MASQUERADE
You can safely add them to /etc/rc.local startup sequence.

Now connect to your router and go to any address from https://www.google.pl/search?q=what+is+my+ip. You should see the public IP of your VPN server, not your home router. It indicates that all your Internet traffic now goes through the VPN.

And finally, one more thing. If you haven't done it yet, change the primary DNS server on your router to 8.8.8.8 and secondary to 8.8.4.4 (they are Google DNS servers). Otherwise all your DNS queries will go through the VPN server back to your Internet provider, and you don't want that to happen, do you?

Saturday, January 23, 2016

Using Raspberry Pi with operating system installed on pendrive

You cannot boot current versions of Raspberry Pi from mediums other than an SD card, which means that for some space consuming operating systems, like Raspbian, you need at least a 4GB or 8GB card. But it doesn't mean that if you have a 1GB or 2GB SD you cannot use a larger system on Pi. You just need a memory stick with sufficiently high capacity.

The trick is simple. Write the operating system image on a pendrive instead of an SD card. Format the card just like you do for everyday use with a camera or smartphone, i.e. just create a single partition with regular FAT file system on it. Now mount the memory stick and you will notice that the first partition is also a FAT parition with a couple of different files - they are required to boot the operating system. Copy all files and folders from the stick to the card. Now edit cmdline.txt file located on the SD card (this is important, remove the pendrive before editing to make sure you modify the right file). The file contents will be similar to this:
dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1
elevator=deadline root=/dev/mmcblk0p2 rootfstype=ext4 fsck.repair=yes rootwait
It's the arguments passed to the kernel on boot up. The root parameter tells the kernel where the main file system is located. Change it from root=/dev/mmcblk0p2 to root=/dev/sda2 and save the file on card. Connect the card and the pendrive to the Pi and turn on the power. It will load the kernel from the card, but will mount as root folder the second partition of the memory stick, containing the actual operating system (and recognized by Linux on boot up as /dev/sda2).

I used this trick to run Minibian, having a few memory sticks and just one small 128MB SD card at my disposal. If the Pi doesn't boot from /dev/sda2 make sure you don't have any other usb storages connected, otherwise try a different device instead of /dev/sda2, like /dev/sdb2, /dev/sdc2, etc.

Monday, December 7, 2015

Authenticating apps with Google using OAuth 2.0

OAuth 2.0 is an open standard protocol for authentication and authorization, which is used by Google to provide users and applications with access to its APIs. If you own a Google account you have probably noticed that you can grant and revoke access to your account for desktop and mobile applications. To grant access, you have to log in to your account from within the application and confirm that it can access some (or all) of your data. To revoke access, you can go to your account's settings, select "Connected apps and sites" and remove the application from the list.

But sometimes things become complicated. Calendar-Indicator is an application for Ubuntu written in Python, which integrates nicely with Unity and allows you to access Google calendar directly from your desktop. It also provides you with very nice OSD notifications, so you don't need any extra software (like Evolution or Thunderird) to remind you about incoming events. Unfortunately, being a fantastic application, it has some issues when it comes to authenticating with corporate Google accounts using additional authentication mechanisms, like Active Directory. It's because such mechanisms can use some extra redirections and pop-up windows, which are not handled well by the application's built-in HTML login widget.

To work around this problem, you can authenticate Calendar-Indicator using Google OAuth2 API directly. In order to do this, you need to know the Client Id and Client Secret, which can be considered as application's username and password. When you look into the source code you will find them in share/calendar-indicator/googlecalendarapi.py file:
CLIENT_ID='906536899599-93lne5t3cb0keptl8fh0o8ghpmt447ls.apps.googleusercontent.com'
CLIENT_SECRET='x_QgZkRfUJ_08lWvCw4EIK3U'
They are written in plain text, but it doesn't matter. OAuth protocol is designed in such a way, that learning application's credentials only cannot be used to compromise it.
Having obtained the credentials, you need to use them to ask Google for a permission to access your calendar. To do this, open a web browser and paste the following url into the address bar (the whole text below is one line):
https://accounts.google.com/o/oauth2/auth?response_type=code&access_type=offline
&client_id=906536899599-93lne5t3cb0keptl8fh0o8ghpmt447ls.apps.googleusercontent.com
&redirect_uri=urn:ietf:wg:oauth:2.0:oob&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar
You will be asked to log in to your account and then to grant permission to your calendar. When you agree, you will receive a one-time code, which you need to use to confirm that the application received the permission. The code is placed inside a small input field and is usually a little bit longer than it's size, so make sure you don't miss any characters when copying it into the clipboard.
Now open a terminal window and enter the following command, replacing the string CODE_RECEIVED_FROM_GOOGLE with the actual code (again, the whole text below is one line):
curl -X POST -d "code=CODE_RECEIVED_FROM_GOOGLE
&client_id=906536899599-93lne5t3cb0keptl8fh0o8ghpmt447ls.apps.googleusercontent.com
&client_secret=x_QgZkRfUJ_08lWvCw4EIK3U&redirect_uri=urn:ietf:wg:oauth:2.0:oob
&grant_type=authorization_code" https://accounts.google.com/o/oauth2/token > ~/.config/calendar-indicator/token
When you open ~/.config/calendar-indicator/token file you will notice that it's a JSON object. There are two fields that are important from the application's point of view: access_token and refresh_token. The access_token, combined with Client Id and Client Secret, identifies the application and is valid only for one session only. The refresh_token, also combined with Client Id and Client Secret is used to receive new access_token every time application is run. This way, even when an attacker breaks current access_token, he or she will not be able to create a new application session and compromise the application as a whole.

As you can see, with just two simple steps your application is now securely authorized. When you revoke access to the application or delete the token configuration, you can use aforementioned procedure again to regain access to your calendar.