HTTP_SERVLET_COOKIEAUTH(3)

NAME
http_servlet_cookieauth - HTTP secure cookie authentication servlet

LIBRARY
PDEL Library (libpdel, -lpdel)

SYNOPSIS
#include <sys/types.h>
#include <stdio.h>
#include <netinet/in.h>
#include <openssl/ssl.h>
#include <pdel/http/http_defs.h>
#include <pdel/http/http_server.h>
#include <pdel/http/servlet/cookieauth.h>
struct http_servlet *
http_servlet_cookieauth_create(const char *redirect, int append, http_servlet_cookieauth_reqd_t *authreqd, void *arg, void (*destroy)(void *), const char *privkey, const void *id, size_t idlen, const char *cookiename);
int
http_servlet_cookieauth_login(struct http_response *resp, const char *privkey, const char *username, u_int max_linger, time_t expire, int session_only, const u_char *id, size_t idlen, const char *cookiename, const char *path, const char *domain, int secure);
int
http_servlet_cookieauth_logout(const char *cookiename, const char *path, const char *domain, struct http_response *resp);
char *
http_servlet_cookieauth_user(const char *privkey, const void *id, size_t idlen, const char *cookiename, struct http_request *req, const char *mtype);

DESCRIPTION
http_servlet_cookieauth_create() creates a new servlet that enforces client authentication using public key cryptography and HTTP cookies. Any requests that fail to present a valid cookie are redirected to a login page. The servlet should be registered with a lower order than the other servlets that it protects, so that it executes first.

redirect and append are used when redirecting a request, and are the same as the arguments to http_servlet_redirect_create(3).

authreqd is invoked for every request and is a pointer to a function of this type:

    typedef int http_servlet_cookieauth_reqd_t(void *arg,
                  struct http_request *req);

The arg is the same value supplied to http_servlet_cookieauth_create(). authreqd() should return a non-zero value if the request requires a valid login cookie to proceed. If authreqd() returns zero, no authentication will be required. Typically this is used to make an exception for the login page, etc.

privkey is a pointer to a PEM-encoded RSA private key. If the HTTP server supports SSL, the server private key may be used for convenience (though this slightly weakens overall security).

id points to arbitrary binary data having length idlen that uniquely identifies the authenticated resource. Only cookies generated with the same identity and signed with the same RSA private key will satisfy this servlet (see http_servlet_cookieauth_login() below). The identity information should not be too long, to avoid overflowing the client's 4K cookie buffer.

The cookiename specifies the name to use for the cookie; multiple cookies with different names may be used simultaneously.

When the servlet is destroyed, if destroy is not NULL, it will be invoked with arg as its parameter.

http_servlet_cookieauth_login() causes a cookie to be generated and passed to the client via resp. When the client includes this cookie in a subsequent HTTP request, the servlet will allow the request to proceed. The privkey, id, and idlen arguments must match the same arguments to http_servlet_cookieauth_create().

username is an arbirary string that may be retrieved in a subsequent request by http_servlet_cookieauth_user() (see below).

max_linger, if non-zero, specifies a maximum time in seconds between requests before the cookie becomes invalid. This means each request will cause a new cookie to be generated. If an otherwise valid cookie is received but it was generated more than max_linger seconds ago, it is rejected.

expire specifies an absolute time at which the cookie should expire. Cookies presented beyond their expiration time (which should only be sent if the client is broken, malicious, or not synchronized) will be rejected.

session_only specifies that the client should be instructed to discard the cookie when the client's session terminates. Implementation of this feature is client-dependent.

path and domain may be NULL to use the default, which means the client should send the cookie with all requests to this web server. Otherwise, see http://www.netscape.com/newsref/std/cookie_spec.html for a description.

The secure flag indicates to the client that this cookie should only be sent over an HTTPS (i.e., encrypted) connection. Implementation of this feature is client-dependent.

http_servlet_cookieauth_logout() invalidates the client cookie by sending the client an invalid cookie which should overwrite the valid one. Correct implementation of this feature is client-dependent. Note also that it's possible (though unlikely) that this function may return an error, in which case the invalid cookie was not sent.

http_servlet_cookieauth_user() retrieves the username argument previously passed to http_servlet_cookieauth_login() from a valid cookie included with the HTTP request req. The string is dynamically allocated with typed_mem(3) type mtype and must be eventually freed by the caller. The identity specified by id and idlen must be the same as when the cookie was created. If req does not contain a valid cookie, NULL is returned.

Note that it is not necessary to create a servlet in order to use the http_servlet_cookieauth_login(), http_servlet_cookieauth_logout(), and http_servlet_cookieauth_user() functions.

SECURITY NOTES
Because public key cryptography is used, as long as the RSA private key is kept secret then there is no known way for an attacker to create a new cookie that appears valid to this servlet. However, if an attacker somehow acquires an existing cookie before its expiration time, it can be presented by the hacker and will fool this servlet into believing that the attacker had previously authenticated.

Also, while the information in the cookie includes a secure digital signature that is used to validate the cookie, the cookie itself is not encrypted. In particular, the username will travel across the HTTP connection (and be stored on the browser's computer) unprotected.

For these reasons, this servlet should only be used with SSL web servers.

Creation of the identity must be done carefully to avoid security holes. The important point is to avoid using the same identity and private key to secure two things that should be considered different from an authentication point of view. Therefore, any information which makes the identity unique to the particular resource being protected is good.

A common pitfall is creating an identity by concatenating strings without inserting a separator character that does not appear in the strings. E.g., the concatenation of “abc” and “def” is the same as the concatenation of “ab” and “cdef.” However, “abc:def” is different from “ab:cdef”.

Hashing the identity components together is a good way to limit idlen and therefore the size of the cookie. However, if hashing is done a secure hash function such as MD5 or SHA-1 should be used.

RETURN VALUES
http_servlet_cookieauth_create(), http_servlet_cookieauth_login(), http_servlet_cookieauth_logout(), and http_servlet_cookieauth_user() return NULL or -1 and set errno to an appropriate value to indicate failure.

The errno value EACCES is used to indicate that no valid cookie was found.

SEE ALSO
http_request(3), http_response(3), http_server(3), http_servlet(3), http_servlet_basicauth(3), http_servlet_redirect(3), libpdel(3), md5(3), sha(3), typed_mem(3) Persistent Client State HTTP Cookies, http://www.netscape.com/newsref/std/cookie_spec.html. D. Kristol, L. Montulli, HTTP State Management Mechanism, RFC 2109.

HISTORY
The PDEL library was developed at Packet Design, LLC. http://www.packetdesign.com/

AUTHORS
Archie Cobbs <archie@freebsd.org>

BUGS
The client must support HTTP cookies for any of this to work.

Only the original Netscape cookie spec is supported; RFC 2109 support should be added.