Android Event Timer Application

Necessity is the mother of invention, and I need a way to time my classes that I teach, unit by unit. I want to be able to track how close I am to meeting the goal time for each unit. So, I've been developing an application to fill this need, and wanting it to be versatile, I added features that others may find useful. The application stores data about the following items: Events, Timers, and Timer Archives and you can find it in the Android market as TimeIt.

The way I use an Event is to use it to represent a course like "RHCE Rapid Track", or "RHCSA Rapid Track", so I set my Event unit to pages. Other people may find that an Event may represent something like "Trip to San Francisco" or "Five Mile Run", and may want to set their Event unit to miles. I had a wonderful idea to add dollars as an event unit as well, which could serve people who work for a fee, as the application would calculate dollars per time unit selected.

The heart of the application is the Timers. I wanted them to be more robust than what I need, so I enabled them to load any started timers at boot time and create notifications for when their goal is supposed to be reached. That way, if you have to reboot your phone for any reason, any running timers will still send goal notifications. I even had the thought tonight to allow timers to automatically start in the future, and send a start timer notification, but it is not yet implemented.

How I use Timers is to store information about each unit that I have to teach. I set the distance to the number of pages that I have to cover, and the goal time to how long I am supposed to spend on that unit. Once the timer is started within the Timer editing screen it creates a notification to be sent by the alarm service, just like timers loaded at boot time.

I imagine other people might use Timers for each leg of a trip, or maybe for each mile out of the five. Each timer has a name, distance, goal time, start time, stop time, and note that the user can set. As it is now, once the start time is set, then you can only stop the timer, or clear the start and stop times. Surveying the market for timer applications, I can also imagine people using the timer to track how long they spent on a task that for which they might be paid hourly. It makes sense to add a timer rate field in a standard time unit, and let the user interface select and convert whether that rate is per fee, day, hour, or minute. As it does not make sense to pause a timer with a set start time, and a recorded finish time, it makes sense to have a time adjustment which could be used to either increase or decrease the amount of time involved in the calculations.

The last type of record stored in the application is called a Timer Archive. I included them for the ability to be able to reuse a Timer at a later date. My use case is that after I have completed a course, then I can I've thought about adding restrictions like requiring the Timer to be started and/or stopped, as well as offering to archive a Timer that is about to be cleared. As of now, you can create a Timer Archive from any Timer, and if you don't before you clear the Timer, then you would lose any start or stop times. Carrying forward the concept of money being involved, perhaps the Timer Archives could be for paid Timers.

The way the application presents itself starts with a list of any Events that you have created. I want to add sorting options to this list view, as well as coding the colour differently for active and finished Events. At the top of the view is a button to add a new Event. If you tap an Event, it takes you to a list of Timers for that Event. If you press on an Event, then you can go to add an Event, delete the Event you pressed on, delete all Events, or edit that Event, or show Timers for that Event.

For a new Event, the only fields used are the name for the event, and the event unit. All other fields are for your own information. The event date defaults to the current date, but you can use the Date button to choose a date. The event date is not used in any calculations or notifications. I am considering changing the event date to an event start date, adding an event stop date, and having event notifications.

After defining a new Event, typically you would go to tap on that Event, where the application will then allow the you to add a new Timer for the Event. If tapping an existing Event, then a list of Timers will be presented.

If an item in the Timers list has a white background colour, then the item lacks any set goal, start, or stop time. If it's background colour is blue, then a goal time has been set. If it's background colour is green, then the timer is running with a start time set. If it's background colour is red, then a stop time has been set. Using the menu, you can archive all timers, clear the start and stop times of all timers, add a timer or go back to the Event list.

If you tap go to Edit a Timer or use the Add button to add a Timer, then you will be on the Timer editing screen. This is where the user can define a name, distance and goal for the Timer. Once you start the Timer, it is saved into the database, and a future notification is scheduled if a goal has been set for that goal time. Using the menu, you can specifically save your changes, archive the timer, delete the timer, or go to view the Timer Archives list.

Once you modify a Timer Archive, then it will be tainted automatically, and show a yellow background colour in the Timer Archive list. I developed a custom time setting dialog window that allows the user to edit the time in hours, minutes and seconds, since the standard TimePicker dialog does not allow for the setting of seconds. You can not only tap on the buttons to increase or decrease the values, but you can hold them down to move them quickly. I would like to add AM/PM settings, so you want have to set time in a 24 hour clock.

I'm sure I will have more ideas myself, but I'd love to hear how you'd like to use it!


iSCSI target and initiator

A couple of years ago, I took a class which covered how to setup an iSCSI server and client. I don't have the book from that class handy, but some quick searching of the Internet helped me to recall these things.

In Redhat based distributions, the following command should be run to ensure that the needed software packages are installed:

yum install iscsi-initiator-utils.i686 scsi-target-utils.i686

On the iSCSI server, the following commands will start the SCSI target daemon and enable it to start automatically in the future:

service tgtd start
chkconfig tgtd on

In the following example, a server with a hostname "server" has an already created partition named /dev/sda3 that will be made available to clients as a target with the full name: iqn.2001-04.com-server-red-target.

tgt-setup-lun -n red-target /dev/sda3

Since the tgt-setup-lun command above did not limit clients by specifying a list of clients at the end of the command, all clients should be able to do the following to connect:

service iscsi start
chkconfig iscsi on
service iscsid start
chkconfig iscsid on
iscsiadm -m discovery -t st -p ${IP_ADDR_SERVER}
iscsiadm -m node -T iqn.2001-04.com-server-red-target -p ${IP_ADDR_SERVER} -l

Now, the "blkid" command should show a new /dev/sd# on the client that can be mounted.
The following command will show that any established sessions:

iscsiadm -m session

To stop a session, first the device should be unmounted "umount /dev/sd#", and then the following command logs the client out of the session:

iscsiadm -m node -T iqn.2001-04.com-server-red-target -p ${IP_ADDR_SERVER} -u

To make a iSCSI device mounted persistently, add _netdev for mount options in /etc/fstab.


Using dumpsys commands in the Android adb shell

To begin using the following commands, first start a shell with a terminal application or use the adb shell command.

dumpsys gives a wealth of information about the applications on the phone, and the current state of the phone. Without any subcommand, it gives you everything.

dumpsys meminfo displays memory usage

dumpsys cpuinfo displays processor usage

dumpsys account displays information on all accounts

dumpsys activity displays information about activities

dumpsys window displays information about keyboards, windows and their z order

dumpsys wifi shows information about available access points and current connection

I just realized that the quick way to see all of the "subcommands" of dumpsys is to do:

dumpsys | grep DUMP

Note: After running this command on my HTC Droid Incredible the following output was produced. I have added a 0 by those commands which produced no output:

DUMP OF SERVICE SurfaceFlinger:
DUMP OF SERVICE accessibility:0
DUMP OF SERVICE appwidget:
DUMP OF SERVICE batteryinfo:
DUMP OF SERVICE bluetooth:
DUMP OF SERVICE bluetooth_a2dp:0
DUMP OF SERVICE bluetooth_dg_service:0
DUMP OF SERVICE bluetooth_fm_receiver_service:0
DUMP OF SERVICE clipboard:0
DUMP OF SERVICE connectivity:
DUMP OF SERVICE device_policy:
DUMP OF SERVICE devicestoragemonitor:0
DUMP OF SERVICE diskstats:
DUMP OF SERVICE hardware:0
DUMP OF SERVICE htc_checkin:0
DUMP OF SERVICE htchardware:0
DUMP OF SERVICE input_method:
DUMP OF SERVICE iphonesubinfo:
DUMP OF SERVICE media.audio_flinger:
DUMP OF SERVICE media.audio_policy:
DUMP OF SERVICE media.camera:
DUMP OF SERVICE media.player:
DUMP OF SERVICE network_management:0
DUMP OF SERVICE notification:
(garbage snipped)
DUMP OF SERVICE permission:0
DUMP OF SERVICE simphonebook:0
DUMP OF SERVICE statusbar:
DUMP OF SERVICE telephony.registry:
DUMP OF SERVICE usagestats:
DUMP OF SERVICE vibrator:0
DUMP OF SERVICE wallpaper:


LG Ally ROM Update

I'm starting an update to my girlfriend's LG Ally tonight. My goal is to install a faster and more functional ROM. Apparently, there are other things to update, as well, kernels and a radio. Thanks to http://savoxis.com/ally/ I've got all the information I need in one place! Awesomeness at my fingertips, yeah!

Before beginning, I'm doing a Titanium backup of all the applications. I also used ROM Manager backup the current stock rooted ROM.

To gauge performance, I ran Quadrant Standard several times with these results: 409, 410, and 380. I also ran Linpack for Android several times with the results: 3.587, 4.172, and 4.016 MFLOPS. It took more than 30 seconds to run each time!

I don't know why, I never ran into the problem on my Droid Incredible, but her browser does not want to download the zip files. So, I searched and found out about Astro, which allows for Android to download unknown file types, and works great as a file manager. That's what I have on my phone!

Using ROM Manager, I chose to Install from SD Card, and selected the downloaded Velocity 0.3 ROM. I prompted me to backup my current ROM (which I already did), and to wipe the phone. To be safe, I chose to do both. After only about few minutes the install was done, and it took several minutes than longer to boot, but success! Since she trusts me so much, she gave me her password and I got her phone back on Google and back to normal by using Titanium Backup to restore the missing applications back to the phone.

Now, the testing begins. I'm going to first of all take the stock kernel out for a spin again. Quadrant scrores: 404, 393, 394. Not too impressive, or just about the same. And for the Linpack scores: 3.938, 4.045, and 4.039 MFLOPS. Again, about the same, so what's next?

Next, I am going to take the big risk of upgrading the radio. She has had reception problems, especially in our house, so this might help fix that, and maybe even improve texting functionality as well. Let's see, it looks official and a few build numbers ahead, yeah, I'm going to do it.

So, using Clockwork Recovery, started from ROM Manager, reboot into recovery, I will now install the zip file for the radio update. I need to remember to navigate up and down the menu with the up and down volume buttons, and to use the call button to select. When the back button is "activated", then I need to use the end call button to go back.

Whew! After rebooting, text message sent and received, call made and rang! Radio update doesn't look too bad.

Now, for a kernel update. First, I'm trying what is best, and will give up, if it is better. So, the runs on Quadrant I got 444, 453, and 460. The Linpack results were 6.869, 6.892, and 6.928 MFLOPS. Wow, both of these benchmarks show an impressive improvement!

I'm going to restore some of her settings for Browser Bookmarks, User Dictionary, and Alarms. Look for green things to restore in Titanium Backup for user files like this. Beware, it can break these applications, but just remove and restore the app without the user file if it happens.

Cool! All is good, so time to back it up all again! Repeat Titanium Backup and ROM Backup and I'm done. Oops, ROM Manager isn't doing the backup now after its update! So, doing a manual backup in recovery, and have to go back to see if I can restore an earlier version of ROM Manager...

Not good. Market is not working. All downloads fail. Time to troubleshoot. Uh oh, the "adb devices" shows ?????????????. lsusb command shows, 1004:618e next to the LG devices, or what vendor and model code to use in my udev rule. New rule in /etc/udev/rules.d/51-android.rules:

SUBSYSTEMS=="usb", ATTRS{idVendor}=="1004", ATTRS{idProduct}=="618e", MODE="0666" SYMLINK+="android_adb".

Which I already had the rule for my Droid Incredible:

SUBSYSTEMS=="usb", ATTRS{idVendor}=="0bb4", ATTRS{idProduct}=="0c9e", MODE="0666" SYMLINK+="android_adb"

Now, adb logcat works. Trying to install from the Market shows insufficient internal storage as the error. Ok, so I removed several apps that were unnecessary (like my two benchmark apps, and NFL Mobile), and I try again with the same result. Checking about the phone in the settings shows over 50mb internal available, so something doesn't seem right.

Bright idea! Reboot into recovery mode, and wipe the cache. Sigh of relief! Apps are now installing from the market, and my girlfriend is almost home. Just time enough to backup this new ROM. The phone is noticeably faster, and everything works, so we are both happy!


GPSMap Pro Android Monkey

Every night this week, and finally this weekend with the help of the Android Monkey, I feel like I squashed all the bugs in my application GPSMap, and put out a professional version: GPSMap Pro. I have added validation to all of the preferences, creating new placemarks, and updating placemarks.

If you get the Pro version, you get no advertising, an import from csv file feature, and highlighting the last selected placemark.

The Android Monkey helped me to make sure my application ran smooth. It allows you to exercise your application for a number of "events". I can be started to run 5000 events with a command like:

adb shell monkey -p com.appspot.wrightrocket.GPSMap -v 5000


I am an Android Developer! I can kill my Activity if I want!

This week I finally committed myself to publishing my GPSMap application on the Android Market, so I obtained my Android Developer's license. If you are interested in an application that will let you create Placemarks that you can save on a map, edit, or navigate to easily, then you might want to check out my website for it: http://wrightrocket.appspot.com/gpsmap.

I'm giving my applicaton away for free right now, but plan to add mobile advertising to the free version in the future. I'm also looking at adding the ability to plot your contacts on the map alongside of the Placemarks, as well as how to add proximity alerts in a paid version. Right now, I'm getting the motivation by having it public to work out all of the bugs, and to make it run more efficiently.

The nugget of knowledge that motivated me to make this post right now is that I finally found out how to really kill my Android Activity! Calling the finish() method was not doing the job, but I stumbled upon this extra addition after the call to the super in the onDestroy() method of the activity:

protected void onDestroy() {


Mobile Twitter 40404

I can't believe I just found out about sending tweets to 40404 on my phone!
Wait there's more! Here's all you can do once you get your phone verified on twitter:

Twitter commands

Do more than Tweet! Send these commands to Twitter:

FOLLOW username
Start following a user
UNFOLLOW username
Stop following a user
Turn all Tweet notifications on or off
ON/OFF username
Set Tweet notifications for a user on or off (you'll still be following them even if you set it to off)
GET username
Shows you the latest tweet from any user
RT username
Retweet a user's latest tweet
FAV username
Favorite a user's latest tweet
D username your-message
Send a direct message to a user


Java Alternatives

Last night I decided to try to get App Inventor for Android to run on Fedora 14. Although Google only officially supports running App Inventor on Windows, OSX and Ubuntu, I wanted to give it a try.

The blocks editor was horribly slow using the IcedTea java that was installed by default, so I downloaded Java from Oracle and installed it. Then, I had to configure Fedora to use it with alternatives.

Here's how I installed it as an alternative to the IcedTea java:
alternatives --install /usr/bin/java java /usr/java/jre1.6.0_20/bin/java 120 \
--slave /usr/bin/keytool keytool /usr/java/jre1.6.0_20/bin/keytool \
--slave /usr/bin/rmiregistry rmiregistry /usr/java/jre1.6.0_20/bin/rmiregistry

Then, I configured Fedora to use it by selecting it using the command:
alternatives --config java

Wow, what a difference. Oracle's java was much faster and App Inventor for Android runs great on Fedora.


App Inventor for Android from Google

Earlier this week, I received my invitation to App Inventor for Android from Google. This web based tool makes it easy for anyone to create Android applications without having to know how to write in a programming language. Instead of writing code, you design the application visually. If you would like to have an invitation, or would like to learn more about this tool, then complete the form at http://appinventor.googlelabs.com/about/.


Postfix Generic

While it is certainly possible to masquerade messages from your Postfix server using the "myorigin" parameter, it may have some undesirable side effects like you needing to also set up Postfix to receive email for the masqueraded domain using the "mydestination" parameter. In addition, using this approach is an all or nothing choice (except for the root user who remains exposed from the real origin).

Instead, if you want to be able to just masquerade a few user accounts, so that it appears that emails from these accounts are masqueraded and not all, then the Postfix "generic" option may be for you.

When I send email from the command line in Linux (Fedora 14) from my keith account (to an address not on my machine), I want it to appear that the email originated from my wright.keith@gmail account. Otherwise, most likely my email will get bounced because it will appear to have come from keith@nv53a.fedora.test.

Here's what I did to achieve this:

1. I added these two lines to the /etc/postfix/generic file:
keith@localhost wright.keith@gmail.com
keith@nv53a.fedora.test wright.keith@gmail.com

2. I added this line to /etc/postfix/main.cf:
smtp_generic_maps = hash:/etc/postfix/generic

3. I executed this command as root to hash the generic file into generic.db:
postmap /etc/postfix/generic

4. I restarted postfix to make the changes effective:
service postfix restart

Thanks to this wonderful tip from nixcraft.com (not sure why the url is cyberciti.biz):


Rawhide Reflections

As an earlier post indicated, I'm running Fedora 14 Alpha. When you use non-released versions of Fedora, you might be said to be running Rawhide. I won't say that I wasn't warned that things would break occasionally, but this morning it BAD! When glibc broke, then the system became unbootable.

Lucky for me, I've got a USB key with Fedora 14 Live on it. Also fortunate, the Fedora Project already had an update that fixed the problem. All I had to do was boot up the Live USB, and do a few simple commands to fix it:

# vgscan
# vgchange -a y
# mount /dev/mapper/vg_host-lv_root /mnt
# yum -y --installroot /mnt update glibc

The first command searched my internal hard drive for LVM Volume Groups.
The second command activated the volume group (vg_host) that it found.
The third command mounted the logical volume (lv_root) for my root filesystem under /mnt.
The fourth command actually fixed the problem: it told yum to update the broken package, but to install the update under /mnt, where my real root filesystem is located.


Android Applications To Pay For

I've only bought a few Android applications, but I've not been disappointed.

I love the new Swiftkey Keyboard. Never seen a keyboard predict text so well.

Titatium Backup is awesome, the free version works, but can become tedious since it doesn't automate the restore process.

I would pay for SetCPU, but being a member over at xda-developers.com, I got it for free!

Winds of Steel is still one of my favorite games.

Minisquadron has a very cool interface and is lots of fun.

When Angry Birds comes out with a full version, I'll probably buy it too!


Android Terminology

AOSPAndroid Open Source Project
bootloaderThe first program that is executed when starting a phone which might then boot the operating system, or take the user to a recovery mode.
deodexedA ROM that has been repackaged with all applications no longer using optimized dex files, so they can be more easily modified.
recoveryA special mode that allows the user to install official updates or to reset the phone. It is often modified to allow for installing unsigned updates or ROMs.
ROMRead Only Memory when I went to school, but to a phone, this is like an Operating System and the pre-installed programs that come along with it.
rootThe superuser who can override normal access controls present on the phone.
rootingThe process of enabling the root user to be able to execute programs on the phone.

I was just going to write some others, and then I found this nice wiki with Terminology from one of the most renowned modders: http://wiki.cyanogenmod.com/index.php?title=Terminology

Apache Access Control Order, Allow, Deny Confusion Ended!

Sometimes I go weeks, or even months between teaching how to control access to directories using an Apache web server. When the time comes to teach it again, I sometimes find that even I am confused about how the Order statement affects Allow and Deny from statements. Today, I worked out a couple of examples to help end this confusion permanently!

First of all, I will assume your web server is already up and running, and that there is a directory block that will permit the use of a .htaccess file to control access to that directory or its subdirectories.

In the default configuration file, I have enabled user home directories with the statement:
UserDir public_html
and not disabled by adding a #, so the other UserDir line looks like this:
# UserDir disabled

Just below this, I have also uncommented the Directory block for user home directories like this:

AllowOverride FileInfo AuthConfig Limit
# Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
# Order allow,deny
# Allow from all

# Order deny,allow
# Deny from all

The important thing in this block is that AllowOverride permits Limit,
which lets us use .htaccess files with Order, Allow from and Deny from statements.

To allow just the web server access to my home directory, I have executed:

setfacl -m u:apache:x /home/keith/
mkdir /home/keith/public_html
restorecon -v /home/keith/public_html

To create a directory that would be mostly open:

mkdir /home/keith/public_html/denyremote
echo 'Deny from 192.168.1. network' > /home/keith/public_html/denyremote/index.html

In a file /home/keith/public_html/denyremote/.htaccess

Order Deny,Allow
# Deny is processed first
Deny from 192.168.1.
# Allow is processed second
Allow from
# If matched by both then allowed
# If matched by neither then allowed

To create a directory that would be mostly closed:

mkdir /home/keith/public_html/localsonly
echo 'Allow from only' > /home/keith/public_html/localsonly/index.html

In a file /home/keith/public_html/localsonly/.htaccess

Order Allow,Deny
# Allow is processed first
Allow from
# Deny is processed second
Deny from
# If matched by both, then denied
# If matched by neither, then denied

Udev Rule for Android SDK

Either because I have wanted to use adb commands, or actually use the Android SDK, I find that I not only need to install the SDK from: http://developer.android.com/index.html, but also I need to write a udev rule.

One sign that you need a udev rule is when you execute the command, adb devices, you see output something like:

List of devices attached
???????????? device

First, you need to attach the Android phone with the USB cord, and have the Settings, Applications, Development, USB debugging enabled on the phone. Next execute the command, lsusb. In my case, the line I'm interested in shows my phone like this:

Bus 001 Device 005: ID 0bb4:0c9e High Tech Computer Corp.

Notice the hexadecimal digits that I have bolded from this line. They need to be modified to match the digits of the attached phone in a rule file such as /etc/udev/rules.d/51-android.rules:

SUBSYSTEMS=="usb", ATTRS{idVendor}=="0bb4", ATTRS{idProduct}=="0c9e", MODE="0666" SYMLINK+="android_adb"

The location and name of this file is very important!

By the way, I found a great blog entry on how to write udev rules today:


Android 2.2 APPS2SD

You can usually override the default Froyo install location on the system, by doing:

pm setInstallLocation 1

The different values are:
0 [auto]: Let system decide the best location
1 [internal]: Install on internal device storage
2 [external]: Install on external media

The default value is "0".


Fedora 14 Alpha

Downloading Fedora 14 Alpha, and a major change for default runlevel.
(forget init, and even upstart)
Look at what you have now, systemd.

From https://fedoraproject.org/wiki/Common_F14_bugs#systemd-update

cd /etc/systemd/system
# Then ONE of the following...
# * For runlevel 5:
ln -sf /lib/systemd/system/graphical.target default.target
# * For runlevel 3:
ln -sf /lib/systemd/system/multi-user.target default.target


Incredible Android

Huge news for me! I've finally made the leap into a smartphone. I've been waiting for a Droid phone that could compete with the iPhone. At last, the HTC Droid Incredible has arrived. With it's 1Ghz Qualcomm Snapdragon processor, 8 Megapixel camera/camcorder, and the open Android 2.1 operating system, this phone is at the top of market of smartphones.

I've already installed these amazing droid only applications from Google such as Googles, Earth, Translator, Maps/GPS Navigator and Sky Maps. There's other applications like YouTube, NFL Mobile, and Shazam that are cool too. Then, there's some 50,000 other applications out there...

If that is not enough, well, then you can create your own applications in Java. Or, you can install the Advanced Scripting Environment(ASE) from code.google.com along with your choice of the following interpeters: bash, beanshell, lua, perl, python, rhino, and tcl. There's samples to help you get started, as well tutorials.

Using just a few lines of Python, I was able to get a barcode scanning application running that would google the barcode. Also, I was able to run a webserver from my phone with just a couple of Python statements.

Android is totally awesome, and on my Droid Incredible!


The Cost of Owning a Sony Playstation 3 (PS3) with Linux

Since Sony introduced their latest update on April 1, 2010, I have refused to update my PS3 since it will no longer allow me to run Linux on the system. As a result, I have to sacrifice the following:

* no access to play games with other users online
* the inability to play online games only
* no video downloads
* no access to demos
* no access to install games online
* no ability to update any of the games that I own online
* the ability to benefit from future updates to the Playstation
* the ability to send messages to other Playstation Network accounts
* the ability to access my Playstation Network account
* the ability to access Playstation Network exclusive content
* the capability to be able to install or play games to be sold in the future
(note: one of the most recently released games requires you to sign into your Playstation Network account to be even able to play the game)

On the other hand, if I update now, then I'll lose these capabilities that I enjoy:

* using the system as part of my Blender 3D render farm for which I developed software
* using the system with HDMI output to view and/or listen to multimedia content in many more formats and with many more options than the Playstation allows
* using the system to access the Internet protocols beyond what the Playstation OS allows
* using the system as part of a network of the computers in my home
* using the system to test out numerous distributions of Linux
* to incorporate Cell Broadband optimized libraries in Linux
* to sharpen my Linux booting/installing/rescuing skills
* to sharpen my Linux kernel building/compiling/optimizing capabilities
* to learn parallel programming using the Cell Broadband Engine
* to learn how Linux works on the PowerPC platform

Do you blame me for not updating?


Backing Up / Restoring Moodle

I've been maintaining a moodle server for some time now, and have backed up and restored my data a few times. Since I've not blogged about it before, I've not a got a reference on how to do it, until now!

Uploaded images and other files are stored under /var/ftp/pub. They are backed up with:

tar cvzPf moodle.ftp.tar.gz /var/ftp/pub

and restored with:

tar xvP moodle.ftp.tar.gz

The other data for moodle resides in a mysql database. I know I used this reference page from http://dev.mysql.com/doc/refman/5.1/en/backup-and-recovery.html.

To backup the database use:

mysqldump moodle -u root -p > moodle.mysqldump

After installing mysql and setting a root password for it, I login to mysql as root and create the moodle database and user, then restore the file.

# mysql -u root -p
> create database moodle;
> grant all on moodle.* to dbuser@localhost identified by 'password';
> quit
# mysql moodle -u root -p < moodle.mysqldump
Password: ******

TCP Wrapper that ALWAYS logs denials

During teaching of a class this week, one of my students noticed that the vsftpd service was being denied by his TCP Wrapper rules in /etc/hosts.allow and /etc/hosts.deny, but that nothing was being logged into /var/log/messages. He then asked me if there was still a way for the TCP Wrapper to start a process as an option. I told him about both the spawn and twist options, and referred him the to the hosts_access and hosts_options man pages. After both of us experimenting a little bit, we came up with the solution that all allow rules should be in /etc/hosts.allow and that /etc/hosts.deny should look something like this:

ALL:ALL:spawn (logger TCP wrapper in /etc/hosts.deny denied %c access to %d)

With this rule, anything that gets denied will be logged by spawn starting the logger process in a subshell (thus the parentheses) and that it would report the client (%c) who was attempting to connect to the daemon (%d). Now, anytime a denial is suspected, the /var/log/messages file can be checked for a 'TCP Wrapper' message.


Windows 7 Administrator Account

One way to improve security while using Windows 7 is to not use the Administrator account all of the time. By default, the first account that Windows 7 sets up is the Administrator. This leads to most users logging in as the Administrator without even being aware of it.

If you want to make the normal Administrator account active and your own account just a standard account, then follow these steps.

1. Login with the account that was first created.
2. Start, All Programs, Accessories, right-click the Command Prompt item.
3. Choose Run As Administrator, and click the Yes button in the dialog box.
4. Enable the Administrator account by typing:

net user administrator /active:yes

5. Set the Administrator account password by typing the following and the new password twice:

net user administrator password *

6. Log off the account, and now login using the Administrator account.
7. Start, Control panel, User Accounts and Family User Accounts, and Manage Another Account.
8. Select the account you first created when installed Windows 7.
9. Click Change Account Type, make sure Standard is selected, and click the Change Account Type button.
10. Now you can logoff the Administrator account, and login using a standard account for safety.


Skipfish Web Application Security Tool

Last week, Slashdot had a link (http://code.google.com/p/skipfish/) to a Google project named skipfish, so I decided to download it. Today, I'm finally getting a chance to try it out. To stay out of trouble, I'm running a scan against my own web server.

Once it has completed its scan, I'll have an interactive site map, as web as a report to help me assess vulnerabilities of my web server. As it completed, it almost brought my system to a halt. It ended up causing hundreds of httpd processes to spawn on my system. This caused almost every bit of RAM and swap to get used up, and almost every application that I was running to be shut down. I have never seen such a high load average on my system, as it was over 80 on just a dual core!

In reading through the skipfish documentation, I came across some interesting links. First, http://code.google.com/p/browsersec/wiki/Part1, which is a document about web browser security. Second is this link to the Open Web Application Security Project (OWASP) http://www.owasp.org/index.php.

What is in an URI?


LDAP for Postfix Canonical Maps

I was very pleasantly surprised how easy it was to configure canonical maps for Postfix to use an LDAP server. Using the same OpenLDAP configuration that I just recently posted for aliases, I was able to add canonical maps in a matter of minutes. The benefit was that now if an email was sent from the command line, the map would rewrite the sending address to one that could be sent over the Internet and not just to other local users. I realized the need for this when I noticed that my girlfriend was trying to use Evolution to send mail (without configuring it) and it was being rejected by Internet mail servers because it appeared to originate from an invalid fedora.test domain.

First, I did it the traditional flat file way. I added this entry to /etc/postfix/canonical:

patricia cmtricia@gmail.com

Then, I added an entry into /etc/postfix/main.cf:

canonical_maps = hash:/etc/postfix/canonical

Now, I hashed the file using the command postmap /etc/postfix/canonical and reloaded the postfix service using the command service postfix reload.

Finally, I tested this by sending a mail from the command line while logged into the patricia account. This worked great! This would be the solution for the problem of my girlfriend trying to send mail without configuring a mail server.

However, I wanted to be able to extend this solution using my LDAP server for maps as well, so I changed my entry in /etc/postfix/main.cf to use LDAP for canonical lookups as well:

canonical_maps = hash:/etc/postfix/canonical, ldap:/etc/postfix/ldap-canonical.cf

Of course, I also needed an entry into my LDAP server, which I made with this:

[root@earth postfix]# ldapadd -x -D cn=Manager,dc=fedora,dc=test -W
Enter LDAP Password:
dn: cn=keith,ou=People,dc=fedora,dc=test
cn: keith
objectclass: nismailalias
objectclass: top
rfc822Mailmember: wright.keith@gmail.com

adding new entry "cn=keith,ou=People,dc=fedora,dc=test"

To create the /etc/postfix/ldap-canonical.cf, I copied the /etc/postfix/ldap-aliases-cf, which I blogged about an earlier post. Surprisingly, nothing in this file needed to change, but here it is for reference:

[root@earth postfix]# grep -v '^$' ldap-canonical.cf | grep -v '^#'
server_host = localhost.localdomain
server_port = 389
timeout = 10
bind = no
search_base = ou=People,dc=fedora,dc=test
result_attribute = rfc822MailMember
query_filter = (& (cn=%s)(objectClass=nisMailAlias))
debug_level = 4

Starting to test it, I executed:
[root@earth postfix]# service postfix reload
Reloading postfix: [ OK ]
[root@earth postfix]# postmap -q keith ldap:/etc/postfix/ldap-canonical.cf

Finally, I did the acid test. I logged into the keith account and sent and email out to one of my Internet email addresses. When I received the email, it indeed did appear to originate from wright.keith@gmail.com.

After further experimenting, I noticed that not just was the address rewritten outbound, but also inbound. This lead me to discover two other canonical maps. There is sender_canonical_maps and recipient_canonical_maps, as well as canonical_maps which applies to all mail in or out bound.

Ultimately, I changed the entry in the /etc/postfix/main.cf to just rewrite the address for outbound mail by using:

sender_canonical_maps = hash:/etc/postfix/canonical, ldap:/etc/postfix/ldap-canonical.cf

Now, I can still receive local mail as the user keith to my local mailbox, but when I send mail for the user keith, it always appear to come from wright.keith@gmail.com.


LDAP and Apache Integration

To integrate authentication to a specific location on my Apache web server with my OpenLDAP server, I used the following configuration in /etc/httpd/conf.d/ldapauth.conf:

LDAPTrustedGlobalCert CA_BASE64 /etc/pki/tls/certs/ca-bundle.crt
LDAPTrustedClientCert CERT_BASE64 /etc/pki/tls/certs/localhost.pem

Options Indexes FollowSymLinks
AuthType Basic
AuthName "LDAP Authentication"
AuthBasicAuthoritative off
AuthBasicProvider ldap
AuthzLDAPAuthoritative off
AuthLDAPURL "ldap://localhost.localdomain/dc=fedora,dc=test?uid??"
AuthLDAPBindDN uid=Patricia,ou=People,dc=fedora,dc=test
AuthLDAPBindPassword supersecret
require valid-user

I did use the Makefile in /etc/pki/tls/certs to "make localhost.pem" and copy it to the /etc/pki/tls/private directory as well. Here was what was in my slapd.conf (before it got slurped into the /etc/openldap/slapd.d directory).

[root@earth openldap]# grep -v '^$' slapd.conf | grep -v '^#'
include /etc/openldap/schema/corba.schema
include /etc/openldap/schema/core.schema
include /etc/openldap/schema/cosine.schema
include /etc/openldap/schema/duaconf.schema
include /etc/openldap/schema/dyngroup.schema
include /etc/openldap/schema/inetorgperson.schema
include /etc/openldap/schema/java.schema
include /etc/openldap/schema/misc.schema
include /etc/openldap/schema/nis.schema
include /etc/openldap/schema/openldap.schema
include /etc/openldap/schema/ppolicy.schema
include /etc/openldap/schema/collective.schema
allow bind_v2
pidfile /var/run/openldap/slapd.pid
argsfile /var/run/openldap/slapd.args
TLSCACertificateFile /etc/pki/tls/certs/ca-bundle.crt
TLSCertificateFile /etc/pki/tls/certs/localhost.pem
TLSCertificateKeyFile /etc/pki/tls/private/localhost.pem
database bdb
suffix "dc=fedora,dc=test"
checkpoint 1024 15
rootdn "cn=Manager,dc=fedora,dc=test"
rootpw simple
directory /var/lib/ldap
index objectClass eq,pres
index ou,cn,mail,surname,givenname eq,pres,sub
index uidNumber,gidNumber,loginShell eq,pres
index uid,memberUid eq,pres,sub
index nisMapName,nisMapEntry eq,pres,sub
database monitor
access to *
by dn.exact="cn=Manager,dc=fedora,dc=test" read
by * none

LDAP and Postfix Integration

After struggling a little while to make it happen, I finally asked the guy who was the speaker at SCALE 8x about LDAP integration about why my LDAP server wasn't working with my Postfix mail server to look up aliases. In just a few minutes, I got my response, and he was right. It can be good to ask for help!

Here was the setup:
I'm using Fedora 12. (postfix-2.6.5-2.fc12.i686 and

My account entry in LDAP:

[root@earth postfix]# ldapsearch -LLL -x uid=keith
>> dn: uid=keith,ou=People,dc=fedora,dc=test
>> uid: keith
>> cn: Keith Wright
>> objectClass: account
>> objectClass: posixAccount
>> objectClass: top
>> objectClass: shadowAccount
>> shadowLastChange: 13363
>> shadowMax: 99999
>> shadowWarning: 7
>> loginShell: /bin/bash
>> uidNumber: 500
>> gidNumber: 500
>> homeDirectory: /home/keith
>> userPassword:: bXXXXXXXXXXXE=
>> An entry for an alias:
>> [root@earth postfix]# ldapsearch -LLL -x '(&
>> (cn=wrightrocket)(objectclass=nismailalias))' rfc822MailMember
>> dn: cn=wrightrocket,ou=People,dc=fedora,dc=test
>> rfc822MailMember: keith
>> From reading the LDAP_README, I have this parameter set in my main.cf:
>> [root@earth postfix]# postconf alias_maps
>> alias_maps = hash:/etc/aliases, ldap:/etc/postfix/ldap-aliases.cf
>> Here is my /etc/postfix/ldap-aliases.cf:
>> server_host = localhost.localdomain
>> # defaults to localhost
>> server_port = 389
>> # default
>> timeout = 10
>> # default
>> bind = no
>> # default
>> search_base = ou=People,dc=fedora,dc=test
>> # location where aliases are stored in tree
>> ldapalias_result_attribute = rfc822MailMember
>> query_filter = (& (cn=%s)(objectClass=nisMailAlias))
>> debug_level = 4

As you can see, I pasted this from my email. What was the one change that made it work? Instead of ldapalias_result_attribute (several lines up), the proper parameter to set was result_attribute, and everything worked!


Kerberos Quick Setup

I used notes that I had from writing a course on Directory Services and Authentication to do this quick Kerberos setup. For a better install guide you may want to reference http://web.mit.edu/kerberos/www/krb5-1.7/krb5-1.7.1/doc/krb5-install.html.

Kerberos Packages from Fedora
Having gotten my LDAP working to provide user information, I wanted to go further to have Kerberos provide authentication. Here's the list of the packages I installed to get going:


The package krb5-libs was already on my system, but is a dependency of the other three. The pam_krb5 package wasn't a dependency, but without it, the ability to use authentication using Kerberos was disabled.

Configuring the Kerberos Library (Client and Server)
First, for either a client or a server, the krb5-libs need to be configured for the realm, which is sort of like a domain. Since I'm in the domain called fedora.test. here was my configuration in /etc/krb5.conf:

default = FILE:/var/log/krb5libs.log
kdc = FILE:/var/log/krb5kdc.log
admin_server = FILE:/var/log/kadmind.log

default_realm = FEDORA.TEST
dns_lookup_realm = false
dns_lookup_kdc = false
ticket_lifetime = 24h
renew_lifetime = 7d
forwardable = yes

kdc = krb5.fedora.test:88
admin_server = krb5.fedora.test:749

.fedora.test = FEDORA.TEST
fedora.test = FEDORA.TEST

I made only a few changes to this file. Under the [realms] section, I changed the realm name from EXAMPLE.COM to FEDORA.TEST. Also, I changed the hostnames for the kdc and admin_server entries to the CNAME hostname of the machine that will be running the Kerberos service.

Beneath the [domain_realm] section, I changed all the example.com and EXAMPLE.COM entries to fedora.test and FEDORA.TEST. Don't forget to configure this file for all clients and servers that will be a part of your realm.

Configuring Access (Server)
If you want different users or principals to have different levels of access then the /var/kerberbos/krb5kdc/kadm5.acl can be used to do that. By default, it permits all admin users to have full access. The only change needed is to make sure that the realm name configured in the previous file /etc/krb5.conf is also configured in this file. So here's what I have in /var/kerberbos/krb5kdc/kadm5.acl:

*/admin@FEDORA.TEST *

Configuring the KDC (Server)

In configuring the /var/kerberos/krb5kdc/kdc.conf file, again you need to make sure that it agrees with the realm name and ports listed in the /etc/krb5.conf. If you are satisfied with the other settings, like the encryption to be used, this usually means a simple search and replace of the realm names (one more time!):

v4_mode = nopreauth
kdc_ports = 88,750
kdc_tcp_ports = 88

#master_key_type = aes256-cts
acl_file = /var/kerberos/krb5kdc/kadm5.acl
dict_file = /usr/share/dict/words
admin_keytab = /var/kerberos/krb5kdc/kadm5.keytab
supported_enctypes = aes256-cts:normal aes128-cts:normal des3-hmac-sha1:normal arcfour-hmac:normal des-hmac-sha1:normal des-cbc-md5:normal des-cbc-crc:normal des-cbc-crc:v4 des-cbc-crc:afs3

Creating the Principal Database (Server)
If all the files are properly configured, then on the server create the database to store the principal accounts:

kdb5_util create -s

Configure root/admin Principal
The first principal that you should create will be one that you will be able to authenticate as in order to do administration of the Kerberos server. Use this command to do that:

kadmin.local -q "addprinc root/admin"

Configure Startup and Start Services
Kerberos runs as two separate services that need to be configured to start up at boot time, and you probably want to start them immediately to use them without rebooting:

# chkconfig krb5kdc on

# chkconfig kadmin on

# service krb5kdc start

# service kadmin start

Using either kadmin or kadmin.local you can then add additional principals for user and server accounts to authenticate. Servers are added as principals just like users, except the ktadd command is used to add to a keytab file (/etc/krb5.keytab) their secret credentials. This file will then need to be copied and included in the configuration of the Kerberized services:
kadmin.local: addprinc ldap/earth.fedora.test
WARNING: no policy specified for ldap/earth.fedora.test@FEDORA.TEST; defaulting to no policy
Enter password for principal "ldap/earth.fedora.test@FEDORA.TEST":
Re-enter password for principal "ldap/earth.fedora.test@FEDORA.TEST":
add_principal: Principal or policy already exists while creating "ldap/earth.fedora.test@FEDORA.TEST".
kadmin.local: ktadd ldap/earth.fedora.test
Entry for principal ldap/earth.fedora.test with kvno 2, encryption type DES cbc mode with RSA-MD5 added to keytab WRFILE:/etc/krb5.keytab.

LDAP with 389 Project and OpenLDAP

The last couple of days, I've been working with LDAP again. Yesterday, I worked with the 389 Project LDAP server from Fedora. It was easy to set up, and easy to integrate with my system authentication. I got it to work with my Apache web server, too. Unfortunately, either it is not supported or Apache doesn't like the self-signed certificate that I used, but I could not get LDAP over SSL to work.

Yet, LDAP over SSL works fine for authentication. In the past, I had trouble even getting that to work with the self-signed certificates, and had to resort to setting up a Certificate Authority on a separate machine to sign the certificate for the LDAP server. The key to making it work now, appears to be the TLS_REQCERT setting. Here's the contents of my /etc/openldap/ldap.conf

URI ldap://localhost.localdomain
BASE dc=fedora,dc=test
TLS_CACERTDIR /etc/openldap/cacerts
HOST localhost.localdomain

Today, I'm attempting to use the openldap-servers package for Fedora. The configuration appears to have changed significantly from what I've used in the past. The /etc/openldap/slapd.conf did not even exist after installation. Instead, there appear to be some auto-generated LDIF files in the /etc/openldap/slapd.d directory. There was a /etc/openldap/slapd.conf.bak file that contained the typical configuration items.

Copyin gthe /etc/openldap/slapd.conf.bak to /etc/openldap/slapd.conf, I searched and replaced the distinguished name for my domain in the suffix and rootdn entries. I used slappasswd to generate an encrypted password like this:

suffix "dc=fedora,dc=test"
rootdn "cn=Manager,dc=fedora,dc=test"
rootpw {SSHA}SqpHzAMFefEQIu4Saw5vZWwTqEZQMkiq

Likewise, I updated the database monitoring section:

# enable monitoring
database monitor

# allow onlu rootdn to read the monitor
access to *
by dn.exact="cn=Manager,dc=fedora,dc=test" read
by * none

Restarting slapd seemed to have no effect! I was attempting to verify unsuccessfully that I could authenticate as Manager using the following command:

[keith@earth fedora.test]$ ldapwhoami -x -D \ cn=Manager,dc=fedora,dc=test -W
Enter LDAP Password:
ldap_bind: Invalid credentials (49)

Reading the man page on slapd, it seems that if you invoke the daemon as follows, then it will convert your configuration file to LDIF in the /etc/openldap/slapd.d directory.

slapd -f /etc/openldap/slapd.conf -F /etc/openldap/slapd.d

Now, at last I could verify my ability to authenticate:

[keith@earth fedora.test]$ ldapwhoami -x -D \ cn=Manager,dc=fedora,dc=test -W
Enter LDAP Password:

While there are many GUI and WBI tools available for LDAP, I wanted to review and practice my CLI tools. Since it's been three years since I took the Redhat Directory Services and Authentication course RH423 and exam EX423, I've been reviewing the Directory Services course that I wrote following that experience to refresh my memory. To begin with, a root entry for the domain was needed in the Directory Information Tree (DIT).

[keith@earth fedora.test]$ ldapadd -x -D \
cn=Manager,dc=fedora,dc=test -W

Enter LDAP Password:
# root entry for Directory Information Tree
dn: dc=fedora,dc=test
objectclass: domain
dc: fedora

adding new entry "dc=fedora,dc=test"

Before adding entries for users or computers, I prepared a file for the needed organizational units and created them like this:

[keith@earth fedora.test]$ cat ou.ldif
# add entries for organizational units
dn: ou=People,dc=fedora,dc=test
objectclass: organizationalUnit
ou: People

dn: ou=Hosts,dc=fedora,dc=test
objectclass: organizationalUnit
ou: Hosts
[keith@earth fedora.test]$ ldapadd -x -D \
cn=Manager,dc=fedora,dc=test -W -f ou.ldif
Enter LDAP Password:
adding new entry "ou=People,dc=fedora,dc=test"

adding new entry "ou=Hosts,dc=fedora,dc=test"

Finally, we can begin to add leaf, or end node, entries to the tree:

[keith@earth fedora.test]$ cat keith.ldif
dn: uid=keith,ou=People,dc=fedora,dc=test
uid: keith
cn: Keith Wright
objectClass: account
objectClass: posixAccount
objectClass: top
objectClass: shadowAccount
userPassword: {crypt}$1$2OTQS7Fs$EFizXUzsCFISt9BANTDje/
shadowLastChange: 13363
shadowMax: 99999
shadowWarning: 7
loginShell: /bin/bash
uidNumber: 500
gidNumber: 500
homeDirectory: /home/keith

[keith@earth fedora.test]$ ldapadd -x -D cn=Manager,dc=fedora,dc=test -W -f keith.ldif
Enter LDAP Password:
adding new entry "uid=keith,ou=People,dc=fedora,dc=test"

About Me - WrightRocket

My photo

I've worked with computers for over 30 years, programming, administering, using and building them from scratch.

I'm an instructor for technical computer courses, an editor and developer of training manuals, and an Android developer.