
/* MODULE							HTAuth.c
**			USER AUTHENTICATION
**
** AUTHORS:
**	AL	Ari Luotonen	luotonen@dxcern.cern.ch
**
** HISTORY:
**
**
** BUGS:
**
**
*/
#include "../config.h"
#include <string.h>

#include "HTUtils.h"
#include "HTPasswd.h"	/* Password file routines	*/
#include "HTAssoc.h"
#include "HTAuth.h"	/* Implemented here		*/
#include "HTUU.h"	/* Uuencoding and uudecoding	*/

#ifndef DISABLE_TRACE
extern int www2Trace;
#endif

/* PRIVATE					    decompose_auth_string()
**		DECOMPOSE AUTHENTICATION STRING
**		FOR BASIC SCHEME (Perhaps add Digest scheme support?)
** ON ENTRY:
**	authstring	is the authorization string received
**			from browser.
**
** ON EXIT:
**	returns		a node representing the user information
**			(as always, this is automatically freed
**			by AA package).
*/
PRIVATE HTAAUser *decompose_auth_string ARGS2(char *,		authstring,
					      HTAAScheme,	scheme)
{
    static HTAAUser *user = NULL;
    static char *cleartext = NULL;
    char *username;
    char *password;
    char *inet_addr = NULL;
    char *timestamp = NULL;
    char *browsers_key = NULL;
    char *extras = NULL;

    if (!user && !(user = (HTAAUser *)malloc(sizeof(HTAAUser)))) /* Allocated */
	outofmem(__FILE__, "decompose_auth_string");		 /* only once */

    user->scheme = scheme;
    user->username = NULL;	/* Not freed, because freeing */
    user->password = NULL;	/* cleartext also frees these */
    user->inet_addr = NULL;	/* See below: ||              */
    user->timestamp = NULL;	/*            ||              */
    user->secret_key = NULL;	/*            ||              */
                                /*            \/              */
    FREE(cleartext);	/* From previous call.				*/
                        /* NOTE: parts of this memory are pointed to by	*/
                        /* pointers in HTAAUser structure. Therefore,	*/
                        /* this also frees all the strings pointed to	*/
			/* by the static 'user'.			*/

    if (!authstring || !*authstring || scheme != HTAA_BASIC)
	return NULL;

    if (scheme == HTAA_BASIC) {  	/* Just uudecode */
	int bytes_decoded;
	int len = strlen(authstring) + 1;
	
	if (!(cleartext = (char *)malloc(len)))
	    outofmem(__FILE__, "decompose_auth_string");
	bytes_decoded = HTUU_decode(authstring, cleartext, len);
	cleartext[bytes_decoded] = (char)0;
    }

    /*
    ** Extract username and password (for both schemes)
    */
    username = cleartext;
    if (!(password = strchr(cleartext, ':'))) {
#ifndef DISABLE_TRACE
	if (www2Trace)
	    fprintf(stderr, "%s %s\n",
		    "decompose_auth_string: password field",
		    "missing in authentication string.\n");
#endif
	return NULL;
    }
    *(password++) = '\0';

   /*
   ** Extract rest of the fields
   */
    if (scheme == HTAA_BASIC) 
        extras = strchr(password, ':');

    if (extras) {
	*(extras++) = '\0';
#ifndef DISABLE_TRACE
	if (www2Trace)
	    fprintf(stderr, "%s `%s' %s `%s'\n",
	            "decompose_auth_string: extra field(s) in",
		    (scheme == HTAA_BASIC ? "Basic" : "Other"),
		    "authorization string ignored:", extras);
#endif
    }

/*
** Set the fields into the result
*/
    user->username   = username;
    user->password   = password;
    user->inet_addr  = inet_addr;
    user->timestamp  = timestamp;
    user->secret_key = browsers_key;

#ifndef DISABLE_TRACE
    if (www2Trace) {
	if (scheme == HTAA_BASIC) {
	    fprintf(stderr, "decompose_auth_string: %s (%s,%s)\n",
		    "Basic scheme authentication string:",
		    username, password);
	} else {
	    fprintf(stderr, "decompose_auth_string: %s (%s,%s,%s,%s,%s)\n",
		    "Other scheme authentication string:",
		    username, password, inet_addr, timestamp, browsers_key);
	}
    }
#endif
    
    return user;
}



PRIVATE BOOL HTAA_checkTimeStamp ARGS1(WWW_CONST char *, timestamp)
{
    return NO;		/* This is just a stub */
}


PRIVATE BOOL HTAA_checkInetAddress ARGS1(WWW_CONST char *, inet_addr)
{
    return NO;		/* This is just a stub */
}


/* SERVER PUBLIC					HTAA_authenticate()
**			AUTHENTICATE USER
** ON ENTRY:
**	scheme		used authentication scheme.
**	scheme_specifics the scheme specific parameters
**			(authentication string for Basic scheme)
**	prot		is the protection information structure
**			for the file.
**
** ON EXIT:
**	returns		NULL, if authentication failed.
**			Otherwise a pointer to a structure
**			representing authenticated user,
**			which should not be freed.
*/
PUBLIC HTAAUser *HTAA_authenticate ARGS3(HTAAScheme,	scheme,
					 char *,	scheme_specifics,
					 HTAAProt *,	prot)
{
    if (HTAA_UNKNOWN == scheme || !prot ||
	-1 == HTList_indexOf(prot->valid_schemes, (void*)scheme))
	return NULL;

    switch (scheme) {
      case HTAA_BASIC:
	{
	    HTAAUser *user = decompose_auth_string(scheme_specifics, scheme);
            /* Remember, user is auto-freed */

	    if (user &&
		HTAA_checkPassword(user->username,
				   user->password,
				   HTAssocList_lookup(prot->values, "passw")) &&
		(HTAA_BASIC == scheme ||
		 (HTAA_checkTimeStamp(user->timestamp) &&
		  HTAA_checkInetAddress(user->inet_addr)))) {
		return user;
	    } else {
		return NULL;
	    }
	}
      default:
	/* Other authentication routines go here */
	return NULL;
    }
}

