Libpurple is an open source library that provides routines to access popular instant messaging services. It also provides basic operations associated with instant messaging clients such as storing passwords and conversation logging. Passwords however are stored in a human readable plain text format.
The primary purpose of this project is to create a multiplatform open source plugin framework that would use the user's operating system's security routines to provide secure password storage. Using the operating system's features is much more secure than leaving the passwords in plain text. Pidgin is our chosen application to demonstrate the usability of our plugin since Pidgin has a large user base and is the default messenger on many versions of Linux.
The Libpurple and Pidgin developers do not want to pester users to enter a password to decode their stored passwords. It would me more secure to just enter their password for the instant messaging service directly than to attempt to securely store passwords. This makes storing passwords a challenge since the encryption and decryption must happen seamlessly without user interaction. Many operating systems have built in security storage features that can be enabled when a user logs in to the machine. We intend to use these features to provide the seamless password storage and retrieval although third party applications could also be implemented.
Our plugin provides an interface that each operating system can use to securely encrypt and store passwords. The interface declares three functions that must be defined for each desired security service. Currently we are using KDE and Windows to demonstrate how this plugin can be implemented in multiple operating systems.
Pidgin users inform libpurple to store their passwords by enabling a checkbox in the account management menu. The "plugin_encrypt_passwords" function will encrypt all accounts stored in libpurple that are marked to have their password stored. The passwords will be stored by the implemented service and the plain text versions will be removed from libpurple's accounts.xml file.
After passwords are encrypted they can be retrieved and used in libpurple by calling "plugin_fetch_passwords". This function is automatically called when the libpurple application starts and will load all passwords into the application.
If the user no longer wants to have their passwords encrypted the plugin can be disabled by calling "plugin_decrypt_passwords".
Our plugin has been implemented in Windows and KDE environments to demonstrate its usability as well as to provide samples for other developers to expand upon.
Saving passwords securely on a Windows operating system can be achieved in multiple ways. Credentials Management is an API that developers can use to store user credentials and it provides a Management User Interface to obtain and manage credential information such as user names and passwords. This is handy for storing website authentication, but an instant messaging program must also store additional information about the account such as the protocol and status.
The Data Protection Application Programming Interface (DPAPI) provides a way to encrypt passwords, which can be saved with all the other account information. DPAPI provides encrypt and decrypt functions. By passing in a plain text password and saving the cipher text output, the next time the password is needed, the cipher text can be decrypted.
The Windows implementation of our libpurple plugin uses DPAPI and saves the password as an encrypted hex string to a XML file. The next time Pidgin is started, the file is read and the password is decrypted and the accounts are loaded.
KWallet is a credentials management application for the K Desktop Environment (KDE). Implementation of KWallet is the preferred method for saving passwords in KDE. Applications can save, update, retrieve and delete passwords (as well as other confidential information) from independent wallets inside of KWallet. The user protects the data using a master password and has the ability to easily manage the data inside the wallet through a special KWallet interface.
We hope that other applications that use Libpurple will adopt this plugin to provide a simple and secure option for password and account data storage. The source code and supporting documentation can be downloaded from http://kainaw.com/libpurple/.Should this be in the developer's documentation?
There are two methods for implementing KWallet. For direct access, the KWallet API provides complete access to the KWallet functions. An alternative to directly accessing KWallet is the application messenger services, DCOP in KDE3 and D-BUS in KDE4. Because KDE3 is still in heavy use, this plugin was developed to directly access KWallet. Therefore, the code is compatible with both KDE3 and KDE4.
There are six goals for this plugin, three user and three developer goals:
KWallet is not easily integrated into LibPurple. KWallet is a Qt/C++ application. LibPurple is a GTK+/C application. This led to many problems.
All LibPurple plugins must be written in C to ensure the plugin can be initialized and loaded. KWallet applications must be written in C++ to initialize and use the KWallet objects. This was accomplished by writing and compiling the plugin in C++ while wrapping the required C code in extern "C". The C callbacks were available to LibPurple while the objects were in native C++.
KWallet must be compiled using a C++ compiler, since it implements C++ code. One of the goals is to avoid altering the default LibPurple plugin Makefile. Therefore, the compiler and include paths were redefined in the make command as: make CC=g++ CFLAGS="-I/usr/include/kde -I/usr/lib/qt-3.3/include" ...
Because LibPurple is a GTK+ application and KWallet is a Qt application, they differ not only in implementation but down to the basic definition of common types. For example, a string is commonly defined as "char*" in either C or C++. In GTK+, a string is defined as "gchar*". In Qt, a string is defined as "QString". To transfer values between GTK+ and Qt, variables were translated first to the common C/C++ type and then to the required GTK+ or Qt type.
After converting all data types properly, wrapping the C callback functions in extern "C", and compiling with the C++ compiler, the plugin was ready to test. However, it immediately produced a segmentation fault that killed both the plugin and master LibPurple process.
Tracing the segmentation fault identified the need for a Qt application. KWallet attempts to attach a modal Qt dialog box to a Qt window. LibPurple only provides GTK+ windows. Therefore, a simple KApplication with no display or functionality was created before KWallet was initialized. Because all KDE applications are Qt, this provided a basic Qt interface. KWallet attached the modal dialog box to the dummy Kapplication and initialized without a problem.
After initializing KWallet was instructed to open the default user wallet. This caused another segmentation fault. Because this is the first true functionality requested of KWallet, it is rather apparent that this is related to failing to link the KWallet library when compiling the plugin. However, the library lkwallet was being linked on compilation. After extensive searching through online documentation, it was discovered in an example of compiling a KWallet application that the library for KWallet is not lkwallet. It is lkwalletclient. After switching libraries, the plugin was able to open the wallet without error.
When only one account was used in LibPurple, the plugin was able to encrypt the user's passwords in KWallet without issues. However, attempting to encrypt two or more accounts caused a segmentation fault. Through tracing the fault, it was readily apparent that the problem was caused by an attempt to simplify the code. The "implement KWallet" section of the code contained all functionality required to open and use KWallet, including creating a KApplication and opening KWallet. Once a KApplication is initialized, another cannot be initialized. Also, once KWallet is opened, the application remains attached to it. Therefore, a second attempt to initialize a KApplication and open KWallet caused problems. Both were moved into a global scope where they are only handled once when the plugin loads.
Beta testing began on a KDE3 and a KDE4 system. In each system, LibPurple had multiple accounts. The accounts were encrypted. It was verified that the passwords were removed from the accounts.xml file and placed in KWallet. Then, LibPurple was shut down and restarted. The plugin immediately retrieved the passwords from KWallet so the accounts could connect as necessary without searching for passwords in the accounts.xml file or requesting passwords from the user. Finally, the passwords were decrypted. It was verified that the passwords were removed from KWallet and saved in the accounts.xml file.
As mentioned previously, it is possible to access KWallet via DCOP in KDE3 and D-BUS in KDE4. DCOP is a Qt-based application messaging service. Implementing DCOP in a LibPurple plugin would be just as difficult as implementing KWallet directly. However, the LibPurple API implements D-BUS natively. As such, it is possible (and advisable) to implement this plugin using D-BUS for KDE4. It can be written and compiled in C without using the C++ compiler, without including extraneous libraries, and without initializing a dummy KApplication.
Passing beta testing, this plugin is ready to be released to the general KDE/LibPurple community.
Libpurple Information: http://developer.pidgin.im/wiki/WhatIsLibpurple Pidgin Information: http://pidgin.im/