FreeWRT Web Interface in PHP

WE NEED SOME HELP HERE, DO YOU LIKE THE IDEA? PLEASE GET IN CONTACT WITH: wbx at freewrt dot org.

Missing name

Because the web interface has no name yet, it is called wi in this document. This name can be replaced when a better name is found.

Dependencies

  • lighttpd
  • lighttpd-mod-fastcgi
  • lighttpd-mod-auth
  • php4-fastcgi
  • php4-mod-sockets
  • php4-mod-pcre
  • php4-mod-session

Installation

wi uses it's own configuration files for lighttpd and php because the config files shipped with lighttpd and php are very generic and it's too complicated to "embed" the wi configurations inside the standard config files which might have been modified by the user. So the wi package installs the following new configuration files:

  • /etc/init.d/S60wi
  • /etc/wi/lighttpd.conf
  • /etc/wi/php.ini
  • /etc/wi/user.conf

It also adds the following lines to the /etc/rc.conf file:

wi=YES
wi_flags="-f /etc/wi/lighttpd.conf"

The web root directory of wi is /usr/lib/wi.

Security

  • The web server runs under a unpriviliged user so the PHP scripts have no root permissions.
  • A special "configuration daemon" runs on a unix domain socket and provides an interface for reading and writing configuration files and checking and setting the status of services. Only this configuration daemon has root permissions.
  • The web interface is password-protected. Authentication is done by the web server to make sure that a programming error in the PHP scripts does not let bad guys bypass the login.

Configuration Daemon

The configuration daemon is also written in PHP and is started and stopped as a daemon by standard init.d scripts. It listens on a unix domain socket for commands from the web interface. Only the web interface user should have access to the unix domain socket.

Writing the daemon in PHP has several advantages:

  • When people write modules for wi they only need to learn (or already know) one programming language. In this language they can write the frontend code (Web Interface) and the backend code (Configuration Daemon)
  • Using the same language in the frontend and the backend allows for easy transfering data between them by using PHP's serialization format with which complex PHP data types can be converted to ASCII presentation and from this back into a complex PHP data type.
  • Writing the daemon in an other scripting language like perl would need more flash space for the additional scripting engine. Writing it in a native language like C would be way too complicated.

The configuration daemon is protected by the same password as the web interface. Communication with the daemon is done via a simple ASCII protocol. For debugging purposes the daemon can also listen on a TCP socket so it can be easily tested with a telnet client. These are the allowed commands:

  • login USER PASSWORD: Performs a login and returns a session id. With this session id the web interface can access the configuration daemon without logging in again. Login timeout is the same as for the web interface (because the same php.ini is used).
  • login SESSIONID: Reconnect to an existing login with the provided session id.
  • get KEY: Returns the configuration value for the specified key. Structure of keys is explained later.
  • set KEY VALUE: Sets the configuration value for the specified key.
  • quit: Closes the connection without closing the session
  • logout: Closes the connection and the session

Configuration Keys

Configurations keys are domain-like strings. Key parts are separated with a single dot. Example: "wireless.ssid". The first part of a key is always the module name. This is needed so the configuation daemon knows to which module the command should be forwarded. The wireless module then sees that the rest of the key is "ssid" and knows what to do with it.

Configuration Values

Configuration values are PHP-serialized data (With escaped line breaks). It can be a simple serialized string but it also can be a serialized array or object or whatever. This is module-specific and the transferred data just need to match on both sides: The web interface and the configuration daemon. Modules can also set configuration values in different ways. For example the wireless module could allow setting a single value "wireless.ssid" but it also could allow setting all values at once (which would be faster because it's not necessary to write the configuration file for each single configuration value) by setting the key "wireless" with a value containing a map or object containing all the data needed to configure the wireless interface.

Configuration Daemon Answers

when the web interface sends a command to the configuration daemon then the daemon will answer each command with a status code (like HTTP status codes) and (depending on the command) with the requested data. Answers (like commands) are always a single line. There are no multiline commands or answers.

Example communication

Here is an example communication with comments:

get wireless.ssid                     # Requests the SSID
403                                   # Request denied because login needed
login admin secret                    # Performs login
200 0c0b4ba845b76ad7d003d76900bdb44a  # Returns a session id
get wireless.ssid                     # Requests the SSID again
200 s:9:"Torchwood";                  # Returns the serialized SSID
get wireless                          # Requests all wireless data
200 O:8:"Wireless":2:{s:4:"ssid";s:9:"Torchwood";s:7:"channel";s:1:"6";}
                                      # Returns the serialized wireless data
                                      # (In this example just SSID and channel)
get wireless.foobar                   # Requests a non-existant key
404                                   # Key not found
set wireless.ssid s:11:"Torchwood 3"; # Sets a new SSID
200                                   # Confirm successful setting of SSID

Optimizing PHP sources

To minimize needed flash space on the router all PHP scripts are "size-optimized" by running "php -w". This means that comments and some unneeded white-spaces are removed. There are lots of more uneeded white-spaces left (for whatever reason php -w keeps them...). Maybe some day a cool AWK script will optimize it better.