1354 lines
37 KiB
C
1354 lines
37 KiB
C
/*
|
|
* $LynxId: HTAABrow.c,v 1.43 2018/05/11 22:54:19 tom Exp $
|
|
*
|
|
* MODULE HTAABrow.c
|
|
* BROWSER SIDE ACCESS AUTHORIZATION MODULE
|
|
*
|
|
* Contains the code for keeping track on server hostnames,
|
|
* port numbers, scheme names, usernames, passwords
|
|
* (and servers' public keys).
|
|
*
|
|
* IMPORTANT:
|
|
* Routines in this module use dynamic allocation, but free
|
|
* automatically all the memory reserved by them.
|
|
*
|
|
* Therefore the caller never has to (and never should)
|
|
* free() any object returned by these functions.
|
|
*
|
|
* Therefore also all the strings returned by this package
|
|
* are only valid until the next call to the same function
|
|
* is made. This approach is selected, because of the nature
|
|
* of access authorization: no string returned by the package
|
|
* needs to be valid longer than until the next call.
|
|
*
|
|
* This also makes it easy to plug the AA package in:
|
|
* you don't have to ponder whether to free() something
|
|
* here or is it done somewhere else (because it is always
|
|
* done somewhere else).
|
|
*
|
|
* The strings that the package needs to store are copied
|
|
* so the original strings given as parameters to AA
|
|
* functions may be freed or modified with no side effects.
|
|
*
|
|
* The AA package does not free() anything else than what
|
|
* it has itself allocated.
|
|
*
|
|
* AUTHORS:
|
|
* AL Ari Luotonen luotonen@dxcern.cern.ch
|
|
*
|
|
* HISTORY:
|
|
* Oct 17 AL Made corrections suggested by marca:
|
|
* Added if (!realm->username) return NULL;
|
|
* Changed some ""s to NULLs.
|
|
* Now doing calloc() to init uuencode source;
|
|
* otherwise HTUU_encode() reads uninitialized memory
|
|
* every now and then (not a real bug but not pretty).
|
|
* Corrected the formula for uuencode destination size.
|
|
*
|
|
* 28 Apr 1997 AJL Do Proxy Authorisation.
|
|
*
|
|
* BUGS:
|
|
*
|
|
*
|
|
*/
|
|
|
|
#include <HTUtils.h>
|
|
#include <HTString.h>
|
|
#include <HTParse.h> /* URL parsing function */
|
|
#include <HTList.h> /* HTList object */
|
|
#include <HTAlert.h> /* HTConfirm(), HTPrompt() */
|
|
#include <HTAAUtil.h> /* AA common to both sides */
|
|
#include <HTAssoc.h> /* Assoc list */
|
|
#include <HTAccess.h> /* Are we using an HTTP gateway? */
|
|
#include <HTAABrow.h> /* Implemented here */
|
|
#include <HTUU.h> /* Uuencoding and uudecoding */
|
|
|
|
#include <LYLeaks.h>
|
|
|
|
/*
|
|
* Local datatype definitions
|
|
*
|
|
* HTAAServer contains all the information about one server.
|
|
*/
|
|
typedef struct {
|
|
|
|
char *hostname; /* Host's name */
|
|
int portnumber; /* Port number */
|
|
BOOL IsProxy; /* Is it a proxy? */
|
|
HTList *setups; /* List of protection setups
|
|
on this server; i.e., valid
|
|
authentication schemes and
|
|
templates when to use them.
|
|
This is actually a list of
|
|
HTAASetup objects. */
|
|
HTList *realms; /* Information about passwords */
|
|
} HTAAServer;
|
|
|
|
/*
|
|
* HTAASetup contains information about one server's one
|
|
* protected tree of documents.
|
|
*/
|
|
typedef struct {
|
|
HTAAServer *server; /* Which server serves this tree */
|
|
char *ctemplate; /* Template for this tree */
|
|
HTList *valid_schemes; /* Valid authentic.schemes */
|
|
HTAssocList **scheme_specifics; /* Scheme specific params */
|
|
BOOL retry; /* Failed last time -- reprompt (or whatever) */
|
|
} HTAASetup;
|
|
|
|
/*
|
|
* Information about usernames and passwords in
|
|
* Basic and Pubkey authentication schemes;
|
|
*/
|
|
typedef struct {
|
|
char *realmname; /* Password domain name */
|
|
char *username; /* Username in that domain */
|
|
char *password; /* Corresponding password */
|
|
} HTAARealm;
|
|
|
|
/*
|
|
* To free off all globals. - FM
|
|
*/
|
|
static void free_HTAAGlobals(void);
|
|
static BOOL free_HTAAGlobalsSet = FALSE;
|
|
static char *HTAA_composeAuthResult = NULL;
|
|
static char *compose_auth_stringResult = NULL; /* Uuencoded presentation */
|
|
|
|
/*
|
|
* Module-wide global variables
|
|
*/
|
|
static HTList *server_table = NULL; /* Browser's info about servers */
|
|
static char *secret_key = NULL; /* Browser's latest secret key */
|
|
static HTAASetup *current_setup = NULL; /* The server setup we are currently */
|
|
|
|
/* talking to */
|
|
static char *current_hostname = NULL; /* The server's name and portnumber */
|
|
static int current_portnumber = 80; /* where we are currently trying to */
|
|
|
|
/* connect. */
|
|
static char *current_docname = NULL; /* The document's name we are */
|
|
|
|
/* trying to access. */
|
|
static char *HTAAForwardAuth = NULL; /* Authorization: line to forward */
|
|
|
|
/* (used by gateway httpds) */
|
|
static HTAASetup *proxy_setup = NULL; /* Same as above, but for Proxy -AJL */
|
|
static char *proxy_hostname = NULL;
|
|
static char *proxy_docname = NULL;
|
|
static int proxy_portnumber = 80;
|
|
|
|
/*** HTAAForwardAuth for enabling gateway-httpds to forward Authorization ***/
|
|
|
|
void HTAAForwardAuth_set(const char *scheme_name,
|
|
const char *scheme_specifics)
|
|
{
|
|
size_t len = (20
|
|
+ (scheme_name ? strlen(scheme_name) : 0)
|
|
+ (scheme_specifics ? strlen(scheme_specifics) : 0));
|
|
|
|
FREE(HTAAForwardAuth);
|
|
if ((HTAAForwardAuth = typecallocn(char, len)) == 0)
|
|
outofmem(__FILE__, "HTAAForwardAuth_set");
|
|
|
|
strcpy(HTAAForwardAuth, "Authorization: ");
|
|
if (scheme_name) {
|
|
strcat(HTAAForwardAuth, scheme_name);
|
|
strcat(HTAAForwardAuth, " ");
|
|
if (scheme_specifics) {
|
|
strcat(HTAAForwardAuth, scheme_specifics);
|
|
}
|
|
}
|
|
}
|
|
|
|
void HTAAForwardAuth_reset(void)
|
|
{
|
|
FREE(HTAAForwardAuth);
|
|
}
|
|
|
|
/**************************** HTAAServer ***********************************/
|
|
|
|
static void HTAASetup_delete(HTAASetup * killme); /* Forward */
|
|
|
|
/* static HTAAServer_new()
|
|
* ALLOCATE A NEW NODE TO HOLD SERVER INFO
|
|
* AND ADD IT TO THE LIST OF SERVERS
|
|
* ON ENTRY:
|
|
* hostname is the name of the host that the server
|
|
* is running in.
|
|
* portnumber is the portnumber which the server listens.
|
|
* IsProxy should be TRUE if this is a proxy.
|
|
*
|
|
* ON EXIT:
|
|
* returns the newly-allocated node with all the strings
|
|
* duplicated.
|
|
* Strings will be automatically freed by
|
|
* the function HTAAServer_delete(), which also
|
|
* frees the node itself.
|
|
*/
|
|
static HTAAServer *HTAAServer_new(const char *hostname,
|
|
int portnumber,
|
|
int IsProxy)
|
|
{
|
|
HTAAServer *server;
|
|
|
|
if ((server = typecalloc(HTAAServer)) == 0)
|
|
outofmem(__FILE__, "HTAAServer_new");
|
|
|
|
server->hostname = NULL;
|
|
server->portnumber = (portnumber > 0 ? portnumber : 80);
|
|
server->IsProxy = (BOOLEAN) IsProxy;
|
|
server->setups = HTList_new();
|
|
server->realms = HTList_new();
|
|
|
|
if (hostname)
|
|
StrAllocCopy(server->hostname, hostname);
|
|
|
|
if (!server_table)
|
|
server_table = HTList_new();
|
|
|
|
HTList_addObject(server_table, (void *) server);
|
|
|
|
return server;
|
|
}
|
|
|
|
/* static HTAAServer_delete()
|
|
*
|
|
* DELETE THE ENTRY FOR THE SERVER FROM THE HOST TABLE,
|
|
* AND FREE THE MEMORY USED BY IT.
|
|
*
|
|
* ON ENTRY:
|
|
* killme points to the HTAAServer to be freed.
|
|
*
|
|
* ON EXIT:
|
|
* returns nothing.
|
|
*/
|
|
static void HTAAServer_delete(HTAAServer *killme)
|
|
{
|
|
int n, i;
|
|
HTAASetup *setup;
|
|
HTAARealm *realm;
|
|
HTList *cur;
|
|
|
|
if (killme) {
|
|
if (killme->setups != NULL) {
|
|
n = HTList_count(killme->setups);
|
|
for (i = (n - 1); i >= 0; i--) {
|
|
if ((setup = (HTAASetup *) HTList_objectAt(killme->setups,
|
|
i)) != NULL) {
|
|
HTAASetup_delete(setup);
|
|
setup = NULL;
|
|
}
|
|
}
|
|
HTList_delete(killme->setups);
|
|
killme->setups = NULL;
|
|
}
|
|
|
|
cur = killme->realms;
|
|
while (NULL != (realm = (HTAARealm *) HTList_nextObject(cur))) {
|
|
FREE(realm->realmname);
|
|
FREE(realm->username);
|
|
FREE(realm->password);
|
|
FREE(realm);
|
|
}
|
|
HTList_delete(killme->realms);
|
|
killme->realms = NULL;
|
|
|
|
FREE(killme->hostname);
|
|
|
|
HTList_removeObject(server_table, (void *) killme);
|
|
FREE(killme);
|
|
}
|
|
}
|
|
|
|
/* static HTAAServer_lookup()
|
|
* LOOK UP SERVER BY HOSTNAME AND PORTNUMBER
|
|
* ON ENTRY:
|
|
* hostname obvious.
|
|
* portnumber if non-positive defaults to 80.
|
|
* IsProxy should be TRUE if this is a proxy.
|
|
*
|
|
* Looks up the server in the module-global server_table.
|
|
*
|
|
* ON EXIT:
|
|
* returns pointer to a HTAAServer structure
|
|
* representing the looked-up server.
|
|
* NULL, if not found.
|
|
*/
|
|
static HTAAServer *HTAAServer_lookup(const char *hostname,
|
|
int portnumber,
|
|
int IsProxy)
|
|
{
|
|
if (hostname) {
|
|
HTList *cur = server_table;
|
|
HTAAServer *server;
|
|
|
|
if (portnumber <= 0)
|
|
portnumber = 80;
|
|
|
|
while (NULL != (server = (HTAAServer *) HTList_nextObject(cur))) {
|
|
if (server->portnumber == portnumber &&
|
|
0 == strcmp(server->hostname, hostname) &&
|
|
server->IsProxy == IsProxy)
|
|
return server;
|
|
}
|
|
}
|
|
return NULL; /* NULL parameter, or not found */
|
|
}
|
|
|
|
/*************************** HTAASetup *******************************/
|
|
|
|
/* static HTAASetup_lookup()
|
|
* FIGURE OUT WHICH AUTHENTICATION SETUP THE SERVER
|
|
* IS USING FOR A GIVEN FILE ON A GIVEN HOST AND PORT
|
|
*
|
|
* ON ENTRY:
|
|
* hostname is the name of the server host machine.
|
|
* portnumber is the port that the server is running in.
|
|
* docname is the (URL-)pathname of the document we
|
|
* are trying to access.
|
|
* IsProxy should be TRUE if this is a proxy.
|
|
*
|
|
* This function goes through the information known about
|
|
* all the setups of the server, and finds out if the given
|
|
* filename resides in one of the protected directories.
|
|
*
|
|
* ON EXIT:
|
|
* returns NULL if no match.
|
|
* Otherwise, a HTAASetup structure representing
|
|
* the protected server setup on the corresponding
|
|
* document tree.
|
|
*
|
|
*/
|
|
static HTAASetup *HTAASetup_lookup(const char *hostname,
|
|
int portnumber,
|
|
const char *docname,
|
|
int IsProxy)
|
|
{
|
|
HTAAServer *server;
|
|
HTAASetup *setup;
|
|
|
|
if (portnumber <= 0)
|
|
portnumber = 80;
|
|
|
|
if (hostname && docname && *hostname && *docname &&
|
|
NULL != (server = HTAAServer_lookup(hostname,
|
|
portnumber,
|
|
IsProxy))) {
|
|
|
|
HTList *cur = server->setups;
|
|
|
|
CTRACE((tfp, "%s %s (%s:%d:%s)\n",
|
|
"HTAASetup_lookup: resolving setup for",
|
|
(IsProxy ? "proxy" : "server"),
|
|
hostname, portnumber, docname));
|
|
|
|
while (NULL != (setup = (HTAASetup *) HTList_nextObject(cur))) {
|
|
if (HTAA_templateMatch(setup->ctemplate, docname)) {
|
|
CTRACE((tfp, "%s `%s' %s `%s'\n",
|
|
"HTAASetup_lookup:", docname,
|
|
"matched template", setup->ctemplate));
|
|
return setup;
|
|
} else {
|
|
CTRACE((tfp, "%s `%s' %s `%s'\n",
|
|
"HTAASetup_lookup:", docname,
|
|
"did NOT match template", setup->ctemplate));
|
|
}
|
|
} /* while setups remain */
|
|
}
|
|
/* if valid parameters and server found */
|
|
CTRACE((tfp, "%s `%s' %s\n",
|
|
"HTAASetup_lookup: No template matched",
|
|
NONNULL(docname),
|
|
"(so probably not protected)"));
|
|
|
|
return NULL; /* NULL in parameters, or not found */
|
|
}
|
|
|
|
/* static HTAASetup_new()
|
|
* CREATE A NEW SETUP NODE
|
|
* ON ENTRY:
|
|
* server is a pointer to a HTAAServer structure
|
|
* to which this setup belongs.
|
|
* ctemplate documents matching this template
|
|
* are protected according to this setup.
|
|
* valid_schemes a list containing all valid authentication
|
|
* schemes for this setup.
|
|
* If NULL, all schemes are disallowed.
|
|
* scheme_specifics is an array of assoc lists, which
|
|
* contain scheme specific parameters given
|
|
* by server in Authenticate: fields.
|
|
* If NULL, all scheme specifics are
|
|
* set to NULL.
|
|
* ON EXIT:
|
|
* returns a new HTAASetup node, and also adds it as
|
|
* part of the HTAAServer given as parameter.
|
|
*/
|
|
static HTAASetup *HTAASetup_new(HTAAServer *server, char *ctemplate,
|
|
HTList *valid_schemes,
|
|
HTAssocList **scheme_specifics)
|
|
{
|
|
HTAASetup *setup;
|
|
|
|
if (!server || isEmpty(ctemplate))
|
|
return NULL;
|
|
|
|
if ((setup = typecalloc(HTAASetup)) == 0)
|
|
outofmem(__FILE__, "HTAASetup_new");
|
|
|
|
setup->retry = NO;
|
|
setup->server = server;
|
|
setup->ctemplate = NULL;
|
|
if (ctemplate)
|
|
StrAllocCopy(setup->ctemplate, ctemplate);
|
|
setup->valid_schemes = valid_schemes;
|
|
setup->scheme_specifics = scheme_specifics;
|
|
|
|
HTList_addObject(server->setups, (void *) setup);
|
|
|
|
return setup;
|
|
}
|
|
|
|
/* static HTAASetup_delete()
|
|
* FREE A HTAASetup STRUCTURE
|
|
* ON ENTRY:
|
|
* killme is a pointer to the structure to free().
|
|
*
|
|
* ON EXIT:
|
|
* returns nothing.
|
|
*/
|
|
static void HTAASetup_delete(HTAASetup * killme)
|
|
{
|
|
int scheme;
|
|
|
|
if (killme) {
|
|
FREE(killme->ctemplate);
|
|
if (killme->valid_schemes) {
|
|
HTList_delete(killme->valid_schemes);
|
|
killme->valid_schemes = NULL;
|
|
}
|
|
for (scheme = 0; scheme < HTAA_MAX_SCHEMES; scheme++)
|
|
if (killme->scheme_specifics[scheme])
|
|
HTAssocList_delete(killme->scheme_specifics[scheme]);
|
|
FREE(killme->scheme_specifics);
|
|
FREE(killme);
|
|
}
|
|
}
|
|
|
|
/* static HTAASetup_updateSpecifics()
|
|
* COPY SCHEME SPECIFIC PARAMETERS
|
|
* TO HTAASetup STRUCTURE
|
|
* ON ENTRY:
|
|
* setup destination setup structure.
|
|
* specifics string array containing scheme
|
|
* specific parameters for each scheme.
|
|
* If NULL, all the scheme specific
|
|
* parameters are set to NULL.
|
|
*
|
|
* ON EXIT:
|
|
* returns nothing.
|
|
*/
|
|
static void HTAASetup_updateSpecifics(HTAASetup * setup, HTAssocList **specifics)
|
|
{
|
|
int scheme;
|
|
|
|
if (setup) {
|
|
if (setup->scheme_specifics) {
|
|
for (scheme = 0; scheme < HTAA_MAX_SCHEMES; scheme++) {
|
|
if (setup->scheme_specifics[scheme])
|
|
HTAssocList_delete(setup->scheme_specifics[scheme]);
|
|
}
|
|
FREE(setup->scheme_specifics);
|
|
}
|
|
setup->scheme_specifics = specifics;
|
|
}
|
|
}
|
|
|
|
/*************************** HTAARealm **********************************/
|
|
|
|
/* static HTAARealm_lookup()
|
|
* LOOKUP HTAARealm STRUCTURE BY REALM NAME
|
|
* ON ENTRY:
|
|
* realm_table a list of realm objects.
|
|
* realmname is the name of realm to look for.
|
|
*
|
|
* ON EXIT:
|
|
* returns the realm. NULL, if not found.
|
|
*/
|
|
static HTAARealm *HTAARealm_lookup(HTList *realm_table,
|
|
const char *realmname)
|
|
{
|
|
if (realm_table && realmname) {
|
|
HTList *cur = realm_table;
|
|
HTAARealm *realm;
|
|
|
|
while (NULL != (realm = (HTAARealm *) HTList_nextObject(cur))) {
|
|
if (0 == strcmp(realm->realmname, realmname))
|
|
return realm;
|
|
}
|
|
}
|
|
return NULL; /* No table, NULL param, or not found */
|
|
}
|
|
|
|
/* static HTAARealm_new()
|
|
* CREATE A NODE CONTAINING USERNAME AND
|
|
* PASSWORD USED FOR THE GIVEN REALM.
|
|
* IF REALM ALREADY EXISTS, CHANGE
|
|
* USERNAME/PASSWORD.
|
|
* ON ENTRY:
|
|
* realm_table a list of realms to where to add
|
|
* the new one, too.
|
|
* realmname is the name of the password domain.
|
|
* username and
|
|
* password are what you can expect them to be.
|
|
*
|
|
* ON EXIT:
|
|
* returns the created realm.
|
|
*/
|
|
static HTAARealm *HTAARealm_new(HTList *realm_table,
|
|
const char *realmname,
|
|
const char *username,
|
|
const char *password)
|
|
{
|
|
HTAARealm *realm;
|
|
|
|
realm = HTAARealm_lookup(realm_table, realmname);
|
|
|
|
if (!realm) {
|
|
if ((realm = typecalloc(HTAARealm)) == 0)
|
|
outofmem(__FILE__, "HTAARealm_new");
|
|
|
|
realm->realmname = NULL;
|
|
realm->username = NULL;
|
|
realm->password = NULL;
|
|
StrAllocCopy(realm->realmname, realmname);
|
|
if (realm_table)
|
|
HTList_addObject(realm_table, (void *) realm);
|
|
}
|
|
if (username)
|
|
StrAllocCopy(realm->username, username);
|
|
if (password)
|
|
StrAllocCopy(realm->password, password);
|
|
|
|
return realm;
|
|
}
|
|
|
|
BOOL HTAA_HaveUserinfo(const char *hostname)
|
|
{
|
|
int gen_delims = 0;
|
|
BOOL result = FALSE;
|
|
char *my_info = NULL;
|
|
|
|
if (StrAllocCopy(my_info, hostname) != NULL) {
|
|
char *at_sign = HTSkipToAt(my_info, &gen_delims);
|
|
|
|
free(my_info);
|
|
if (at_sign != NULL && gen_delims == 0)
|
|
result = TRUE;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
* If there is userinfo in the hostname string, update the realm to use that
|
|
* information. The command-line "-auth" option will override this.
|
|
*/
|
|
static void fill_in_userinfo(HTAARealm *realm, const char *hostname)
|
|
{
|
|
int gen_delims = 0;
|
|
char *my_info = NULL;
|
|
char *at_sign = HTSkipToAt(StrAllocCopy(my_info, hostname), &gen_delims);
|
|
|
|
if (at_sign != NULL && gen_delims == 0) {
|
|
char *colon;
|
|
|
|
*at_sign = '\0';
|
|
if ((colon = StrChr(my_info, ':')) != 0) {
|
|
*colon++ = '\0';
|
|
}
|
|
if (non_empty(my_info)) {
|
|
char *msg;
|
|
BOOL prior = non_empty(realm->username);
|
|
|
|
if (prior && strcmp(realm->username, my_info)) {
|
|
msg = 0;
|
|
HTSprintf0(&msg,
|
|
gettext("username for realm %s changed from %s to %s"),
|
|
realm->realmname,
|
|
realm->username,
|
|
my_info);
|
|
HTAlert(msg);
|
|
free(msg);
|
|
FREE(realm->username);
|
|
StrAllocCopy(realm->username, my_info);
|
|
} else if (!prior) {
|
|
StrAllocCopy(realm->username, my_info);
|
|
}
|
|
if (non_empty(colon)) {
|
|
prior = non_empty(realm->password);
|
|
if (prior && strcmp(realm->password, colon)) {
|
|
msg = 0;
|
|
HTSprintf0(&msg,
|
|
gettext("password for realm %s user %s changed"),
|
|
realm->realmname,
|
|
realm->username);
|
|
HTAlert(msg);
|
|
free(msg);
|
|
FREE(realm->password);
|
|
StrAllocCopy(realm->password, colon);
|
|
} else if (!prior) {
|
|
StrAllocCopy(realm->password, colon);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
free(my_info);
|
|
}
|
|
|
|
/***************** Basic and Pubkey Authentication ************************/
|
|
|
|
/* static compose_auth_string()
|
|
*
|
|
* COMPOSE Basic OR Pubkey AUTHENTICATION STRING;
|
|
* PROMPTS FOR USERNAME AND PASSWORD IF NEEDED
|
|
*
|
|
* ON ENTRY:
|
|
* hostname may include user- and password information
|
|
* scheme is either HTAA_BASIC or HTAA_PUBKEY.
|
|
* setup is the current server setup.
|
|
* IsProxy should be TRUE if this is a proxy.
|
|
*
|
|
* ON EXIT:
|
|
* returns a newly composed authorization string,
|
|
* (with, of course, a newly generated secret
|
|
* key and fresh timestamp, if Pubkey-scheme
|
|
* is being used).
|
|
* NULL, if something fails.
|
|
* NOTE:
|
|
* Like throughout the entire AA package, no string or structure
|
|
* returned by AA package needs to (or should) be freed.
|
|
*
|
|
*/
|
|
static char *compose_auth_string(const char *hostname,
|
|
HTAAScheme scheme,
|
|
HTAASetup * setup,
|
|
int IsProxy)
|
|
{
|
|
char *cleartext = NULL; /* Cleartext presentation */
|
|
char *ciphertext = NULL; /* Encrypted presentation */
|
|
size_t len;
|
|
char *msg = NULL;
|
|
char *username = NULL;
|
|
char *password = NULL;
|
|
char *realmname = NULL;
|
|
char *theHost = NULL;
|
|
char *proxiedHost = NULL;
|
|
char *thePort = NULL;
|
|
HTAARealm *realm;
|
|
const char *i_net_addr = "0.0.0.0"; /* Change... @@@@ */
|
|
const char *timestamp = "42"; /* ... these @@@@ */
|
|
|
|
FREE(compose_auth_stringResult); /* From previous call */
|
|
|
|
if ((scheme != HTAA_BASIC && scheme != HTAA_PUBKEY) ||
|
|
!(setup &&
|
|
setup->scheme_specifics &&
|
|
setup->scheme_specifics[scheme] &&
|
|
setup->server &&
|
|
setup->server->realms))
|
|
return NULL;
|
|
|
|
realmname = HTAssocList_lookup(setup->scheme_specifics[scheme], "realm");
|
|
if (!realmname)
|
|
return NULL;
|
|
|
|
realm = HTAARealm_lookup(setup->server->realms, realmname);
|
|
setup->retry |= HTAA_HaveUserinfo(hostname);
|
|
|
|
if (!(realm &&
|
|
non_empty(realm->username) &&
|
|
non_empty(realm->password)) || setup->retry) {
|
|
if (!realm) {
|
|
CTRACE((tfp, "%s `%s' %s\n",
|
|
"compose_auth_string: realm:", realmname,
|
|
"not found -- creating"));
|
|
realm = HTAARealm_new(setup->server->realms,
|
|
realmname, NULL, NULL);
|
|
}
|
|
fill_in_userinfo(realm, hostname);
|
|
/*
|
|
* The template should be either the '*' global for everything on the
|
|
* server (always true for proxy authorization setups), or a path for
|
|
* the start of a protected limb, with no host field, but we'll check
|
|
* for a host anyway in case a WWW-Protection-Template header set an
|
|
* absolute URL instead of a path. If we do get a host from this, it
|
|
* will include the port. - FM
|
|
*/
|
|
if ((!IsProxy) && using_proxy && setup->ctemplate) {
|
|
proxiedHost = HTParse(setup->ctemplate, "", PARSE_HOST);
|
|
if (proxiedHost && *proxiedHost != '\0') {
|
|
theHost = proxiedHost;
|
|
}
|
|
}
|
|
/*
|
|
* If we didn't get a host field from the template, set up the host
|
|
* name and port from the setup->server elements. - FM
|
|
*/
|
|
if (!theHost)
|
|
theHost = setup->server->hostname;
|
|
if (setup->server->portnumber > 0 &&
|
|
setup->server->portnumber != 80) {
|
|
HTSprintf0(&thePort, ":%d", setup->server->portnumber);
|
|
}
|
|
|
|
HTSprintf0(&msg, gettext("Username for '%s' at %s '%s%s':"),
|
|
realm->realmname,
|
|
(IsProxy ? "proxy" : "server"),
|
|
(theHost ? theHost : "??"),
|
|
NonNull(thePort));
|
|
FREE(proxiedHost);
|
|
FREE(thePort);
|
|
if (non_empty(realm->username)) {
|
|
StrAllocCopy(username, realm->username);
|
|
}
|
|
if (non_empty(realm->password)) {
|
|
StrAllocCopy(password, realm->password);
|
|
}
|
|
HTPromptUsernameAndPassword(msg, &username, &password, IsProxy);
|
|
|
|
FREE(msg);
|
|
FREE(realm->username);
|
|
FREE(realm->password);
|
|
|
|
realm->username = username;
|
|
realm->password = password;
|
|
|
|
if (!realm->username || !realm->password) {
|
|
/*
|
|
* Signals to retry. - FM
|
|
*/
|
|
return NULL;
|
|
} else if (*realm->username == '\0') {
|
|
/*
|
|
* Signals to abort. - FM
|
|
*/
|
|
StrAllocCopy(compose_auth_stringResult, "");
|
|
return compose_auth_stringResult;
|
|
}
|
|
}
|
|
|
|
len = (strlen(NonNull(realm->username)) +
|
|
strlen(NonNull(realm->password)) + 3);
|
|
|
|
if (scheme == HTAA_PUBKEY) {
|
|
#ifdef PUBKEY
|
|
/* Generate new secret key */
|
|
StrAllocCopy(secret_key, HTAA_generateRandomKey());
|
|
#endif /* PUBKEY */
|
|
/* Room for secret key, timestamp and inet address */
|
|
len += strlen(NonNull(secret_key)) + 30;
|
|
} else {
|
|
FREE(secret_key);
|
|
}
|
|
|
|
if ((cleartext = typecallocn(char, len)) == 0)
|
|
outofmem(__FILE__, "compose_auth_string");
|
|
|
|
if (realm->username)
|
|
strcpy(cleartext, realm->username);
|
|
else
|
|
*cleartext = '\0';
|
|
|
|
strcat(cleartext, ":");
|
|
|
|
if (realm->password)
|
|
strcat(cleartext, realm->password);
|
|
|
|
if (scheme == HTAA_PUBKEY) {
|
|
strcat(cleartext, ":");
|
|
strcat(cleartext, i_net_addr);
|
|
strcat(cleartext, ":");
|
|
strcat(cleartext, timestamp);
|
|
strcat(cleartext, ":");
|
|
if (secret_key)
|
|
strcat(cleartext, secret_key);
|
|
|
|
if (!((ciphertext = typecallocn(char, 2 * len)) &&
|
|
(compose_auth_stringResult = typecallocn(char, 3 * len))))
|
|
outofmem(__FILE__, "compose_auth_string");
|
|
|
|
#ifdef PUBKEY
|
|
HTPK_encrypt(cleartext, ciphertext, server->public_key);
|
|
HTUU_encode((unsigned char *) ciphertext, strlen(ciphertext),
|
|
compose_auth_stringResult);
|
|
#endif /* PUBKEY */
|
|
FREE(cleartext);
|
|
FREE(ciphertext);
|
|
} else { /* scheme == HTAA_BASIC */
|
|
if (!(compose_auth_stringResult =
|
|
typecallocn(char, (4 * ((len + 2) / 3)) + 1)))
|
|
outofmem(__FILE__, "compose_auth_string");
|
|
|
|
HTUU_encode((unsigned char *) cleartext, strlen(cleartext),
|
|
compose_auth_stringResult);
|
|
FREE(cleartext);
|
|
}
|
|
return compose_auth_stringResult;
|
|
}
|
|
|
|
/* BROWSER static HTAA_selectScheme()
|
|
* SELECT THE AUTHENTICATION SCHEME TO USE
|
|
* ON ENTRY:
|
|
* setup is the server setup structure which can
|
|
* be used to make the decision about the
|
|
* used scheme.
|
|
*
|
|
* When new authentication methods are added to library
|
|
* this function makes the decision about which one to
|
|
* use at a given time. This can be done by inspecting
|
|
* environment variables etc.
|
|
*
|
|
* Currently only searches for the first valid scheme,
|
|
* and if nothing found suggests Basic scheme;
|
|
*
|
|
* ON EXIT:
|
|
* returns the authentication scheme to use.
|
|
*/
|
|
static HTAAScheme HTAA_selectScheme(HTAASetup * setup)
|
|
{
|
|
int scheme;
|
|
|
|
if (setup && setup->valid_schemes) {
|
|
for (scheme = HTAA_BASIC; scheme < HTAA_MAX_SCHEMES; scheme++) {
|
|
void *object = (void *) (intptr_t) scheme;
|
|
|
|
if (-1 < HTList_indexOf(setup->valid_schemes, object))
|
|
return (HTAAScheme) scheme;
|
|
}
|
|
}
|
|
return HTAA_BASIC;
|
|
}
|
|
|
|
/*
|
|
* Purpose: Free off all module globals.
|
|
* Arguments: void
|
|
* Return Value: void
|
|
* Remarks/Portability/Dependencies/Restrictions:
|
|
* To be used at program exit.
|
|
* Revision History:
|
|
* 06-19-96 created - FM
|
|
*/
|
|
static void free_HTAAGlobals(void)
|
|
{
|
|
HTAAServer *server;
|
|
int n, i;
|
|
|
|
if (server_table != NULL) {
|
|
n = HTList_count(server_table);
|
|
for (i = (n - 1); i >= 0; i--) {
|
|
if ((server = (HTAAServer *) HTList_objectAt(server_table,
|
|
i)) != NULL) {
|
|
HTAAServer_delete(server);
|
|
server = NULL;
|
|
}
|
|
}
|
|
HTList_delete(server_table);
|
|
server_table = NULL;
|
|
}
|
|
|
|
HTAAForwardAuth_reset();
|
|
FREE(HTAA_composeAuthResult);
|
|
FREE(current_hostname);
|
|
FREE(current_docname);
|
|
FREE(proxy_hostname);
|
|
FREE(proxy_docname);
|
|
FREE(compose_auth_stringResult);
|
|
FREE(secret_key);
|
|
}
|
|
|
|
/* BROWSER PUBLIC HTAA_composeAuth()
|
|
*
|
|
* SELECT THE AUTHENTICATION SCHEME AND
|
|
* COMPOSE THE ENTIRE AUTHORIZATION HEADER LINE
|
|
* IF WE ALREADY KNOW THAT THE HOST REQUIRES AUTHENTICATION
|
|
*
|
|
* ON ENTRY:
|
|
* hostname is the hostname of the server.
|
|
* portnumber is the portnumber in which the server runs.
|
|
* docname is the pathname of the document (as in URL)
|
|
* IsProxy should be TRUE if this is a proxy.
|
|
*
|
|
* ON EXIT:
|
|
* returns NULL, if no authorization seems to be needed, or
|
|
* if it is the entire Authorization: line, e.g.
|
|
*
|
|
* "Authorization: Basic username:password"
|
|
*
|
|
* As usual, this string is automatically freed.
|
|
*/
|
|
char *HTAA_composeAuth(const char *hostname,
|
|
const int portnumber,
|
|
const char *docname,
|
|
int IsProxy)
|
|
{
|
|
char *auth_string;
|
|
BOOL retry;
|
|
HTAAScheme scheme;
|
|
size_t len;
|
|
|
|
/*
|
|
* Setup atexit() freeing if not done already. - FM
|
|
*/
|
|
if (!free_HTAAGlobalsSet) {
|
|
#ifdef LY_FIND_LEAKS
|
|
atexit(free_HTAAGlobals);
|
|
#endif
|
|
free_HTAAGlobalsSet = TRUE;
|
|
}
|
|
|
|
/*
|
|
* Make gateway httpds pass authorization field as it was received. (This
|
|
* still doesn't really work because Authenticate: headers from remote
|
|
* server are not forwarded to client yet so it cannot really know that it
|
|
* should send authorization; I will not implement it yet because I feel we
|
|
* will soon change radically the way requests are represented to allow
|
|
* multithreading on server-side. Life is hard.)
|
|
*/
|
|
if (HTAAForwardAuth) {
|
|
CTRACE((tfp, "HTAA_composeAuth: %s\n",
|
|
"Forwarding received authorization"));
|
|
StrAllocCopy(HTAA_composeAuthResult, HTAAForwardAuth);
|
|
HTAAForwardAuth_reset(); /* Just a precaution */
|
|
return HTAA_composeAuthResult;
|
|
}
|
|
|
|
FREE(HTAA_composeAuthResult); /* From previous call */
|
|
|
|
if (IsProxy) {
|
|
/*
|
|
* Proxy Authorization required. - AJL
|
|
*/
|
|
|
|
CTRACE((tfp, "Composing Proxy Authorization for %s:%d/%s\n",
|
|
hostname, portnumber, docname));
|
|
|
|
if (proxy_portnumber != portnumber ||
|
|
!proxy_hostname || !proxy_docname ||
|
|
!hostname || !docname ||
|
|
0 != strcmp(proxy_hostname, hostname) ||
|
|
0 != strcmp(proxy_docname, docname)) {
|
|
|
|
retry = NO;
|
|
|
|
proxy_portnumber = portnumber;
|
|
|
|
if (hostname)
|
|
StrAllocCopy(proxy_hostname, hostname);
|
|
else
|
|
FREE(proxy_hostname);
|
|
|
|
if (docname)
|
|
StrAllocCopy(proxy_docname, docname);
|
|
else
|
|
FREE(proxy_docname);
|
|
} else {
|
|
retry = YES;
|
|
}
|
|
|
|
if (!proxy_setup || !retry)
|
|
proxy_setup = HTAASetup_lookup(hostname, portnumber,
|
|
docname, IsProxy);
|
|
|
|
if (!proxy_setup)
|
|
return NULL;
|
|
|
|
switch (scheme = HTAA_selectScheme(proxy_setup)) {
|
|
case HTAA_BASIC:
|
|
case HTAA_PUBKEY:
|
|
auth_string = compose_auth_string(hostname, scheme, proxy_setup, IsProxy);
|
|
break;
|
|
case HTAA_KERBEROS_V4:
|
|
/* OTHER AUTHENTICATION ROUTINES ARE CALLED HERE */
|
|
default:
|
|
{
|
|
char *msg = NULL;
|
|
|
|
HTSprintf0(&msg, "%s `%s'",
|
|
gettext("This client doesn't know how to compose proxy authorization information for scheme"),
|
|
HTAAScheme_name(scheme));
|
|
HTAlert(msg);
|
|
FREE(msg);
|
|
auth_string = NULL;
|
|
}
|
|
} /* switch scheme */
|
|
|
|
proxy_setup->retry = NO;
|
|
|
|
if (!auth_string)
|
|
/*
|
|
* Signal a failure. - FM
|
|
*/
|
|
return NULL; /* Added by marca. */
|
|
if (*auth_string == '\0') {
|
|
/*
|
|
* Signal an abort. - FM
|
|
*/
|
|
StrAllocCopy(HTAA_composeAuthResult, "");
|
|
return (HTAA_composeAuthResult);
|
|
}
|
|
len = strlen(auth_string) + strlen(HTAAScheme_name(scheme)) + 26;
|
|
if ((HTAA_composeAuthResult = typecallocn(char, len)) == 0)
|
|
outofmem(__FILE__, "HTAA_composeAuth");
|
|
|
|
strcpy(HTAA_composeAuthResult, "Proxy-Authorization: ");
|
|
|
|
} else {
|
|
/*
|
|
* Normal WWW authorization.
|
|
*/
|
|
CTRACE((tfp, "Composing Authorization for %s:%d/%s\n",
|
|
hostname, portnumber, docname));
|
|
|
|
if (current_portnumber != portnumber ||
|
|
!current_hostname || !current_docname ||
|
|
!hostname || !docname ||
|
|
0 != strcmp(current_hostname, hostname) ||
|
|
0 != strcmp(current_docname, docname)) {
|
|
|
|
retry = NO;
|
|
|
|
current_portnumber = portnumber;
|
|
|
|
if (hostname)
|
|
StrAllocCopy(current_hostname, hostname);
|
|
else
|
|
FREE(current_hostname);
|
|
|
|
if (docname)
|
|
StrAllocCopy(current_docname, docname);
|
|
else
|
|
FREE(current_docname);
|
|
} else {
|
|
retry = YES;
|
|
}
|
|
|
|
if (!current_setup || !retry)
|
|
current_setup = HTAASetup_lookup(hostname, portnumber,
|
|
docname, IsProxy);
|
|
|
|
if (!current_setup)
|
|
return NULL;
|
|
|
|
switch (scheme = HTAA_selectScheme(current_setup)) {
|
|
case HTAA_BASIC:
|
|
case HTAA_PUBKEY:
|
|
auth_string = compose_auth_string(hostname, scheme, current_setup, IsProxy);
|
|
break;
|
|
case HTAA_KERBEROS_V4:
|
|
/* OTHER AUTHENTICATION ROUTINES ARE CALLED HERE */
|
|
default:
|
|
{
|
|
char *msg = 0;
|
|
|
|
HTSprintf0(&msg, "%s `%s'",
|
|
gettext("This client doesn't know how to compose authorization information for scheme"),
|
|
HTAAScheme_name(scheme));
|
|
HTAlert(msg);
|
|
FREE(msg);
|
|
auth_string = NULL;
|
|
}
|
|
} /* switch scheme */
|
|
|
|
current_setup->retry = NO;
|
|
|
|
if (!auth_string)
|
|
/*
|
|
* Signal a failure. - FM
|
|
*/
|
|
return NULL; /* Added by marca. */
|
|
if (*auth_string == '\0') {
|
|
/*
|
|
* Signal an abort. - FM
|
|
*/
|
|
StrAllocCopy(HTAA_composeAuthResult, "");
|
|
return (HTAA_composeAuthResult);
|
|
}
|
|
|
|
len = strlen(auth_string) + strlen(HTAAScheme_name(scheme)) + 20;
|
|
if ((HTAA_composeAuthResult = typecallocn(char, len)) == 0)
|
|
outofmem(__FILE__, "HTAA_composeAuth");
|
|
|
|
strcpy(HTAA_composeAuthResult, "Authorization: ");
|
|
}
|
|
|
|
strcat(HTAA_composeAuthResult, HTAAScheme_name(scheme));
|
|
strcat(HTAA_composeAuthResult, " ");
|
|
strcat(HTAA_composeAuthResult, auth_string);
|
|
return HTAA_composeAuthResult;
|
|
}
|
|
|
|
/* BROWSER PUBLIC HTAA_shouldRetryWithAuth()
|
|
*
|
|
* DETERMINES IF WE SHOULD RETRY THE SERVER
|
|
* WITH AUTHORIZATION
|
|
* (OR IF ALREADY RETRIED, WITH A DIFFERENT
|
|
* USERNAME AND/OR PASSWORD (IF MISSPELLED))
|
|
* ON ENTRY:
|
|
* start_of_headers is the first block already read from socket,
|
|
* but status line skipped; i.e., points to the
|
|
* start of the header section.
|
|
* length is the remaining length of the first block.
|
|
* soc is the socket to read the rest of server reply.
|
|
* IsProxy should be TRUE if this is a proxy.
|
|
*
|
|
* This function should only be called when
|
|
* server has replied with a 401 (Unauthorized)
|
|
* status code.
|
|
* ON EXIT:
|
|
* returns YES, if connection should be retried.
|
|
* The node containing all the necessary
|
|
* information is
|
|
* * either constructed if it does not exist
|
|
* * or password is reset to NULL to indicate
|
|
* that username and password should be
|
|
* reprompted when composing Authorization:
|
|
* field (in function HTAA_composeAuth()).
|
|
* NO, otherwise.
|
|
*/
|
|
BOOL HTAA_shouldRetryWithAuth(char *start_of_headers,
|
|
size_t length,
|
|
int soc,
|
|
int IsProxy)
|
|
{
|
|
HTAAScheme scheme;
|
|
char *line = NULL;
|
|
int num_schemes = 0;
|
|
HTList *valid_schemes = HTList_new();
|
|
HTAssocList **scheme_specifics = NULL;
|
|
char *ctemplate = NULL;
|
|
char *temp = NULL;
|
|
BOOL result = NO;
|
|
|
|
/*
|
|
* Setup atexit() freeing if not done already. - FM
|
|
*/
|
|
if (!free_HTAAGlobalsSet) {
|
|
#ifdef LY_FIND_LEAKS
|
|
atexit(free_HTAAGlobals);
|
|
#endif
|
|
free_HTAAGlobalsSet = TRUE;
|
|
}
|
|
|
|
/*
|
|
* Read server reply header lines
|
|
*/
|
|
CTRACE((tfp, "Server reply header lines:\n"));
|
|
|
|
HTAA_setupReader(start_of_headers, length, soc);
|
|
while (NULL != (line = HTAA_getUnfoldedLine()) && *line != '\0') {
|
|
CTRACE((tfp, "%s\n", line));
|
|
|
|
if (StrChr(line, ':')) { /* Valid header line */
|
|
|
|
char *p = line;
|
|
char *fieldname = HTNextField(&p);
|
|
char *arg1 = HTNextField(&p);
|
|
char *args = p;
|
|
|
|
if ((IsProxy &&
|
|
0 == strcasecomp(fieldname, "Proxy-Authenticate:")) ||
|
|
(!IsProxy &&
|
|
0 == strcasecomp(fieldname, "WWW-Authenticate:"))) {
|
|
if (isEmpty(arg1) || isEmpty(args)) {
|
|
HTSprintf0(&temp, gettext("Invalid header '%s%s%s%s%s'"), line,
|
|
(non_empty(arg1) ? " " : ""),
|
|
NonNull(arg1),
|
|
(non_empty(args) ? " " : ""),
|
|
NonNull(args));
|
|
HTAlert(temp);
|
|
FREE(temp);
|
|
} else if (HTAA_UNKNOWN != (scheme = HTAAScheme_enum(arg1))) {
|
|
HTList_addObject(valid_schemes, (void *) scheme);
|
|
if (!scheme_specifics) {
|
|
int i;
|
|
|
|
scheme_specifics =
|
|
typecallocn(HTAssocList *, HTAA_MAX_SCHEMES);
|
|
|
|
if (!scheme_specifics)
|
|
outofmem(__FILE__, "HTAA_shouldRetryWithAuth");
|
|
|
|
for (i = 0; i < HTAA_MAX_SCHEMES; i++)
|
|
scheme_specifics[i] = NULL;
|
|
}
|
|
scheme_specifics[scheme] = HTAA_parseArgList(args);
|
|
num_schemes++;
|
|
} else {
|
|
CTRACE((tfp, "Unknown scheme `%s' %s\n",
|
|
NONNULL(arg1),
|
|
(IsProxy ?
|
|
"in Proxy-Authenticate: field" :
|
|
"in WWW-Authenticate: field")));
|
|
}
|
|
}
|
|
|
|
else if (!IsProxy &&
|
|
0 == strcasecomp(fieldname, "WWW-Protection-Template:")) {
|
|
CTRACE((tfp, "Protection template set to `%s'\n", arg1));
|
|
StrAllocCopy(ctemplate, arg1);
|
|
}
|
|
|
|
} else {
|
|
CTRACE((tfp, "Invalid header line `%s' ignored\n", line));
|
|
}
|
|
|
|
FREE(line);
|
|
} /* while header lines remain */
|
|
FREE(line);
|
|
|
|
/*
|
|
* So should we retry with authorization?
|
|
*/
|
|
if (IsProxy) {
|
|
if (num_schemes == 0) {
|
|
/*
|
|
* No proxy authorization valid
|
|
*/
|
|
proxy_setup = NULL;
|
|
result = NO;
|
|
}
|
|
/*
|
|
* Doing it for proxy. -AJL
|
|
*/
|
|
else if (proxy_setup && proxy_setup->server) {
|
|
/*
|
|
* We have already tried with proxy authorization. Either we don't
|
|
* have access or username or password was misspelled.
|
|
*
|
|
* Update scheme-specific parameters (in case they have expired by
|
|
* chance).
|
|
*/
|
|
HTAASetup_updateSpecifics(proxy_setup, scheme_specifics);
|
|
|
|
if (NO == HTConfirm(AUTH_FAILED_PROMPT)) {
|
|
proxy_setup = NULL;
|
|
result = NO;
|
|
} else {
|
|
/*
|
|
* Re-ask username+password (if misspelled).
|
|
*/
|
|
HTList_delete(valid_schemes);
|
|
proxy_setup->retry = YES;
|
|
result = YES;
|
|
}
|
|
} else {
|
|
/*
|
|
* proxy_setup == NULL, i.e., we have a first connection to a
|
|
* protected server or the server serves a wider set of documents
|
|
* than we expected so far.
|
|
*/
|
|
HTAAServer *server = HTAAServer_lookup(proxy_hostname,
|
|
proxy_portnumber,
|
|
IsProxy);
|
|
|
|
if (!server) {
|
|
server = HTAAServer_new(proxy_hostname,
|
|
proxy_portnumber,
|
|
IsProxy);
|
|
}
|
|
if (!ctemplate) /* Proxy matches everything -AJL */
|
|
StrAllocCopy(ctemplate, "*");
|
|
proxy_setup = HTAASetup_new(server,
|
|
ctemplate,
|
|
valid_schemes,
|
|
scheme_specifics);
|
|
FREE(ctemplate);
|
|
|
|
HTAlert(gettext("Proxy authorization required -- retrying"));
|
|
result = YES;
|
|
}
|
|
}
|
|
/*
|
|
* Normal WWW authorization.
|
|
*/
|
|
else if (num_schemes == 0) {
|
|
/*
|
|
* No authorization valid.
|
|
*/
|
|
current_setup = NULL;
|
|
result = NO;
|
|
} else if (current_setup && current_setup->server) {
|
|
/*
|
|
* So we have already tried with WWW authorization. Either we don't
|
|
* have access or username or password was misspelled.
|
|
*
|
|
* Update scheme-specific parameters (in case they have expired by
|
|
* chance).
|
|
*/
|
|
HTAASetup_updateSpecifics(current_setup, scheme_specifics);
|
|
|
|
if (NO == HTConfirm(AUTH_FAILED_PROMPT)) {
|
|
current_setup = NULL;
|
|
result = NO;
|
|
} else {
|
|
/*
|
|
* Re-ask username+password (if misspelled).
|
|
*/
|
|
current_setup->retry = YES;
|
|
result = YES;
|
|
}
|
|
} else {
|
|
/*
|
|
* current_setup == NULL, i.e., we have a first connection to a
|
|
* protected server or the server serves a wider set of documents than
|
|
* we expected so far.
|
|
*/
|
|
HTAAServer *server = HTAAServer_lookup(current_hostname,
|
|
current_portnumber,
|
|
IsProxy);
|
|
|
|
if (!server) {
|
|
server = HTAAServer_new(current_hostname,
|
|
current_portnumber,
|
|
IsProxy);
|
|
}
|
|
if (!ctemplate)
|
|
ctemplate = HTAA_makeProtectionTemplate(current_docname);
|
|
current_setup = HTAASetup_new(server,
|
|
ctemplate,
|
|
valid_schemes,
|
|
scheme_specifics);
|
|
FREE(ctemplate);
|
|
|
|
HTAlert(gettext("Access without authorization denied -- retrying"));
|
|
result = YES;
|
|
}
|
|
|
|
if (result == NO) {
|
|
HTList_delete(valid_schemes);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
* This function clears all authorization information by
|
|
* invoking the free_HTAAGlobals() function, which normally
|
|
* is invoked at exit. It allows a browser command to do
|
|
* this at any time, for example, if the user is leaving
|
|
* the terminal for a period of time, but does not want
|
|
* to end the current session. - FM
|
|
*/
|
|
void HTClearHTTPAuthInfo(void)
|
|
{
|
|
/*
|
|
* Need code to check cached documents against the protection templates,
|
|
* and do something to ensure that any protected documents no longer can be
|
|
* accessed without a new retrieval. - FM
|
|
*/
|
|
|
|
/*
|
|
* Now free all of the authorization info, and reset the
|
|
* free_HTAAGlobalsSet flag. - FM
|
|
*/
|
|
free_HTAAGlobals();
|
|
free_HTAAGlobalsSet = FALSE;
|
|
}
|