home *** CD-ROM | disk | FTP | other *** search
- /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
-
- /* backend glue code to do password caching
- * Accepts password queries and does lookups in a secure database
- *
- * Written by Lou Montulli Jan 98
- */
- #include "xp.h"
- #include "mcom_db.h"
- #include "pwcacapi.h"
-
- DB *pw_database=NULL;
- XP_List *pc_interpret_funcs=NULL;
-
- struct _PCNameValuePair {
- char *name;
- char *value;
- };
-
- struct _PCNameValueArray {
-
- int32 cur_ptr;
- int32 size;
- int32 first_empty;
- PCNameValuePair *pairs;
- };
-
- typedef struct {
- char *module;
- PCDataInterpretFunc *func;
- } PCInterpretModuleAssoc;
-
- PUBLIC void
- PC_Shutdown()
- {
-
- if(pw_database)
- {
- (*pw_database->close)(pw_database);
-
- pw_database = NULL;
- }
- }
-
- PRIVATE int
- pc_open_database(void)
- {
- char* filename = "passcac.db";
- static Bool have_tried_open=FALSE;
-
- if(!pw_database)
- {
- HASHINFO hash_info = {
- 4 * 1024,
- 0,
- 0,
- #ifdef WIN16
- 60 * 1024,
- #else
- 96 * 1024,
- #endif
- 0,
- 0};
-
- /* @@@ add .db to the end of the files
- */
- pw_database = dbopen(filename,
- O_RDWR | O_CREAT,
- 0600,
- DB_HASH,
- &hash_info);
-
- if(!have_tried_open && !pw_database)
- {
- XP_StatStruct stat_entry;
-
- have_tried_open = TRUE; /* only do this once */
-
- TRACEMSG(("Could not open cache database -- errno: %d", errno));
-
- /* if the file is zero length remove it
- */
- if(XP_Stat("", &stat_entry, xpCacheFAT) != -1)
- {
- if(stat_entry.st_size <= 0)
- {
- XP_FileRemove("", xpCacheFAT);
- }
- }
-
- /* try it again */
- if (filename) {
- pw_database = dbopen(filename,
- O_RDWR | O_CREAT,
- 0600,
- DB_HASH,
- 0);
- }
- else
- pw_database = NULL;
- }
- }
-
- /* return non-zero if the pw_database pointer is
- * non-zero
- */
- return((int) pw_database);
-
- }
-
- PRIVATE char *
- pc_gen_key(char *module, char *module_key)
- {
- char *combo=NULL;
-
- StrAllocCopy(combo, module);
- StrAllocCat(combo, "\t");
- StrAllocCat(combo, module_key);
-
- return combo;
- }
-
- PRIVATE void
- pc_separate_key(char *key, char **module, char **module_key)
- {
- char *tab;
-
- *module = NULL;
- *module_key = NULL;
-
- if(!key)
- return;
-
- tab = XP_STRCHR(key, '\t');
-
- if(!tab)
- return;
-
- *tab = '\0';
-
- *module = XP_STRDUP(key);
- *module_key = XP_STRDUP(tab+1);
-
- *tab = '\t';
- }
-
- PRIVATE PCInterpretModuleAssoc *
- pc_find_interpret_func(char *module)
- {
- XP_List *list_ptr = pc_interpret_funcs;
- PCInterpretModuleAssoc *assoc;
-
- if(!module)
- return NULL;
-
- while((assoc = (PCInterpretModuleAssoc *) XP_ListNextObject(list_ptr)) != NULL)
- {
- if(!XP_STRCMP(module, assoc->module))
- return assoc;
- }
-
- return NULL;
- }
-
- /* returns 0 on success -1 on error */
- PUBLIC int
- PC_RegisterDataInterpretFunc(char *module, PCDataInterpretFunc *func)
- {
- PCInterpretModuleAssoc *assoc;
-
- if(!pc_interpret_funcs)
- {
- pc_interpret_funcs = XP_ListNew();
-
- if(!pc_interpret_funcs)
- return -1;
- }
-
- if((assoc = pc_find_interpret_func(module)) != NULL)
- {
- assoc->func = func;
- return 0;
- }
-
- assoc = XP_NEW(PCInterpretModuleAssoc);
-
- if(!assoc)
- return -1;
-
- assoc->module = XP_STRDUP(module);
- assoc->func = func;
-
- if(!assoc->module)
- {
- XP_FREE(assoc);
- return -1;
- }
-
- XP_ListAddObject(pc_interpret_funcs, assoc);
-
- return 0;
- }
-
- PRIVATE void
- pc_lookup_module_info(char *key,
- char *data, int32 data_size,
- char *type_buffer, int type_buffer_size,
- char *url_buffer, int url_buffer_size,
- char *username_buffer, int username_buffer_size,
- char *password_buffer, int password_buffer_size)
- {
- char *module, *module_key;
- PCInterpretModuleAssoc *assoc;
-
- *type_buffer = '\0';
- *url_buffer = '\0';
- *username_buffer = '\0';
- *password_buffer = '\0';
-
- pc_separate_key(key, &module, &module_key);
-
- if(!module || !module_key)
- {
- XP_FREEIF(module);
- XP_FREEIF(module_key);
- return;
- }
-
- /* lookup an explain function from the modules list and use it to interpret the data */
- /* @@@@ */
- if(0 == (assoc = pc_find_interpret_func(module)))
- {
- /* cant find one */
- return;
- }
-
- (*assoc->func)(module,
- module_key,
- data, data_size,
- type_buffer, type_buffer_size,
- url_buffer, url_buffer_size,
- username_buffer, username_buffer_size,
- password_buffer, password_buffer_size);
-
- }
-
- /*, returns status
- */
- PUBLIC int
- PC_DisplayPasswordCacheAsHTML(URL_Struct *URL_s,
- FO_Present_Types format_out,
- MWContext *context)
- {
- DBT key, data;
- int status = 1;
- NET_StreamClass *stream;
- char tmp_buffer[512];
- char type_buffer[256];
- char url_buffer[512];
- char username_buffer[256];
- char password_buffer[256];
-
- format_out = CLEAR_CACHE_BIT(format_out);
- StrAllocCopy(URL_s->content_type, TEXT_HTML);
- stream = NET_StreamBuilder(format_out,
- URL_s,
- context);
-
- if(!stream)
- {
- return MK_UNABLE_TO_CONVERT;
- }
-
-
- /* define a macro to push a string up the stream
- * and handle errors
- */
- #define PUT_PART(part) \
- status = (*stream->put_block)(stream, \
- part ? part : "Unknown", \
- part ? XP_STRLEN(part) : 7); \
- if(status < 0) \
- goto END;
-
- if(!pc_open_database())
- {
- XP_STRCPY(tmp_buffer, "The password database is currently unopenable");
- PUT_PART(tmp_buffer);
- goto END;
- }
-
- if(0 != (*pw_database->seq)(pw_database, &key, &data, R_FIRST))
- {
- XP_STRCPY(tmp_buffer, "The password database is currently empty");
- PUT_PART(tmp_buffer);
- goto END;
- }
-
- do {
-
- pc_lookup_module_info(key.data,
- data.data, data.size,
- type_buffer, sizeof(type_buffer),
- url_buffer, sizeof(url_buffer),
- username_buffer, sizeof(username_buffer),
- password_buffer, sizeof(password_buffer));
-
- PUT_PART("Protocol: ");
- PUT_PART(type_buffer);
-
- PUT_PART("<br>\nURL: ");
- PUT_PART(url_buffer);
-
- PUT_PART("<br>\nUsername: ");
- PUT_PART(username_buffer);
-
- PUT_PART("<br>\nPassword: ");
- PUT_PART(password_buffer);
-
- PUT_PART("\n<HR>\n");
-
- } while (0 == (*pw_database->seq)(pw_database, &key, &data, R_NEXT));
-
- END:
- if(status < 0)
- (*stream->abort)(stream, status);
- else
- (*stream->complete)(stream);
-
- return status;
- }
-
- PUBLIC int
- PC_PromptUsernameAndPassword(MWContext *context,
- char *prompt,
- char **username,
- char **password,
- XP_Bool *remember,
- XP_Bool is_secure)
- {
- *remember = TRUE;
- *remember = FALSE;
-
- return FE_PromptUsernameAndPassword(context, prompt, username, password);
- }
-
- PUBLIC char *
- PC_PromptPassword(MWContext *context,
- char *prompt,
- XP_Bool *remember,
- XP_Bool is_secure)
- {
- *remember = TRUE;
- *remember = FALSE;
-
- return FE_PromptPassword(context, prompt);
- }
-
- PUBLIC char *
- PC_Prompt(MWContext *context,
- char *prompt,
- char *deflt,
- XP_Bool *remember,
- XP_Bool is_secure)
- {
- *remember = TRUE;
- *remember = FALSE;
-
- return FE_Prompt(context, prompt, deflt);
- }
-
- PUBLIC void
- PC_FreeNameValueArray(PCNameValueArray *array)
- {
- int index;
- if(array)
- {
- if(array->pairs)
- {
- for(index=0; index < array->first_empty; index++)
- {
- XP_FREEIF(array->pairs[index].name);
- XP_FREEIF(array->pairs[index].value);
- }
- XP_FREE(array->pairs);
- }
- XP_FREE(array);
- }
- }
-
-
- #define MIN_ARRAY_SIZE 4
- #define GROW_ARRAY_BY 4
-
- PRIVATE PCNameValueArray *
- pc_new_namevaluearray(int init_size)
- {
- PCNameValueArray *array = XP_NEW_ZAP(PCNameValueArray);
-
- if(!array)
- return NULL;
-
- array->pairs = (PCNameValuePair*)XP_CALLOC(init_size, sizeof(PCNameValuePair));
- array->size = init_size;
- array->first_empty = 0;
- array->cur_ptr = 0;
-
- if(!array->pairs)
- {
- PC_FreeNameValueArray(array);
- return NULL;
- }
-
- return array;
- }
-
- PUBLIC PCNameValueArray *
- PC_NewNameValueArray()
- {
- return pc_new_namevaluearray(MIN_ARRAY_SIZE);
- }
-
- PUBLIC uint32
- PC_ArraySize(PCNameValueArray *array)
- {
- return(array->first_empty);
- }
-
- /* returns value for a given name
- */
- char *
- PC_FindInNameValueArray(PCNameValueArray *array, char *name)
- {
- int i;
- for(i=0; i<array->first_empty; i++)
- {
- if(!XP_STRCMP(array->pairs[i].name, name))
- return XP_STRDUP(array->pairs[i].value);
- }
-
- return NULL;
-
- }
-
- PUBLIC int
- PC_DeleteNameFromNameValueArray(PCNameValueArray *array, char *name)
- {
- int i;
-
- if(!array)
- return -1;
-
- for(i=0; i<array->first_empty; i++)
- {
- if(!XP_STRCMP(array->pairs[i].name, name))
- {
- /* found it */
-
- /* delete it */
- XP_FREE(array->pairs[i].name);
- XP_FREEIF(array->pairs[i].value);
-
- /* move everything */
- array->first_empty--;
-
- if(array->first_empty > i+1)
- XP_MEMCPY(&array->pairs[i], &array->pairs[i+1], (array->first_empty - (i+1)) * sizeof(PCNameValuePair));
-
- return 0;
- }
- }
-
- return -1;
- }
-
- /* enumerates the array. DO NOT free the name and value results
- *
- * set beggining to TRUE to start over at the beginning
- */
- PUBLIC void
- PC_EnumerateNameValueArray(PCNameValueArray *array, char **name, char **value, XP_Bool beginning)
- {
-
- *name = NULL;
- *value = NULL;
-
- if(!array)
- return;
-
- if(beginning)
- {
- array->cur_ptr = 0;
- }
- else if(array->cur_ptr >= array->first_empty)
- {
- return;
- }
-
- *name = array->pairs[array->cur_ptr].name;
- *value = array->pairs[array->cur_ptr].value;
-
- array->cur_ptr++;
-
- return;
- }
-
- /* private ver. takes pre malloced name and value strings */
- PRIVATE int
- pc_add_to_namevaluearray(PCNameValueArray *array, char *name, char *value)
- {
- if(array)
- {
- if(array->first_empty >= array->size-1)
- {
- /* need to grow */
-
- array->size += GROW_ARRAY_BY;
- array->pairs = (PCNameValuePair *)XP_REALLOC(array->pairs, array->size * sizeof(PCNameValuePair));
- }
-
- if(!array->pairs)
- {
- array->size = 0;
- return -1;
- }
-
- array->pairs[array->first_empty].name = name;
- array->pairs[array->first_empty].value = value;
- array->first_empty++;
-
- if(!array->pairs[array->first_empty-1].name
- || !array->pairs[array->first_empty-1].value)
- return -1;
-
- return 0;
- }
-
- return -1;
- }
-
- /* adds to end of name value array
- *
- * Possible to add duplicate names with this
- */
- PUBLIC int
- PC_AddToNameValueArray(PCNameValueArray *array, char *name, char *value)
- {
- char *m_name = XP_STRDUP(name);
- char *m_value = XP_STRDUP(value);
-
- if(!m_name || !m_value)
- {
- XP_FREEIF(m_name);
- XP_FREEIF(m_value);
- return -1;
- }
-
- return pc_add_to_namevaluearray(array, name, value);
- }
-
- /* takes a key string as input and returns a char * pointer
- * in data to the serialized data structure previously stored or NULL.
- * len will be filled in to the length of the data string
- *
- * A module name is also passed in to guarentee that a key from
- * another module is never returned by an accidental key match.
- */
- PUBLIC void
- PC_CheckForStoredPasswordData(char *module, char *key, char **data, int32 *len)
- {
- DBT k_key, k_data;
- char *combo;
- int status;
-
- *len = 0;
- *data = NULL;
-
- if(!pc_open_database())
- return;
-
- if((combo = pc_gen_key(module, key)) == NULL)
- return;
-
- k_key.size = XP_STRLEN(combo);
- k_key.data = combo;
-
- status = (*pw_database->get)(pw_database, &k_key, &k_data, 0);
-
- XP_FREE(combo);
-
- if(status != 0)
- return;
-
- *data = k_data.data;
- *len = k_data.size;
-
- return;
- }
-
- /* returns 0 on success else -1
- */
- PUBLIC int
- PC_DeleteStoredPassword(char *module, char *key)
- {
- DBT k_key;
- char *combo;
- int status;
-
- if(!pc_open_database())
- return -1;
-
- if((combo = pc_gen_key(module, key)) == NULL)
- return -1;
-
- k_key.size = XP_STRLEN(combo);
- k_key.data = combo;
-
- status = (*pw_database->del)(pw_database, &k_key, 0);
-
- XP_FREE(combo);
-
- if(status != 0)
- return -1;
-
- return 0;
- }
-
- /* takes a key string as input and returns a name value array
- *
- * A module name is also passed in to guarentee that a key from
- * another module is never returned by an accidental key match.
- */
- PUBLIC PCNameValueArray *
- PC_CheckForStoredPasswordArray(char *module, char *key)
- {
- char *data;
- int32 len;
-
- PC_CheckForStoredPasswordData(module, key, &data, &len);
-
- if(!data)
- return NULL;
-
- return PC_CharToNameValueArray(data, len);
- }
-
- /* stores a serialized data stream in the password database
- * returns 0 on success
- */
- PUBLIC int
- PC_StoreSerializedPassword(char *module, char *key, char *data, int32 len)
- {
- char *combo;
- DBT k_key, k_data;
- int status;
-
- if(!pc_open_database())
- return 0;
-
- if((combo = pc_gen_key(module, key)) == NULL)
- return -1;
-
- k_key.size = XP_STRLEN(combo)+1;
- k_key.data = combo;
-
- k_data.data = data;
- k_data.size = len;
-
- status = (*pw_database->put)(pw_database, &k_key, &k_data, 0);
-
- XP_FREE(combo);
-
- if(status != 0)
- return -1;
-
- status = (*pw_database->sync)(pw_database, 0);
-
- return 0;
- }
-
- /* stores a name value array in the password database
- * returns 0 on success
- */
- PUBLIC int
- PC_StorePasswordNameValueArray(char *module, char *key, PCNameValueArray *array)
- {
- char *data;
- int32 len;
- int status;
-
- PC_SerializeNameValueArray(array, &data, &len);
-
- if(!data)
- return -1;
-
- status = PC_StoreSerializedPassword(module, key, data, len);
-
- XP_FREE(data);
-
- return status;
- }
-
- #define SERIALIZER_VERSION_NUM 1
-
- /* takes a name value array and serializes to a char string.
- * string is returned in "data" with length "len"
- *
- * data will always be NULL on error
- */
- PUBLIC void
- PC_SerializeNameValueArray(PCNameValueArray *array, char **data, int32 *len)
- {
- int32 total_size, net_long;
- char *cur_ptr;
- char *name, *value;
-
- *len = 0;
- *data = NULL;
-
- XP_ASSERT(array && array->pairs);
-
- if(!array)
- return;
-
- total_size = sizeof(int32)*3; /* start with checksum + ver + array_size amount */
-
- /* determine size of arrays */
- PC_EnumerateNameValueArray(array, &name, &value, TRUE);
- while(name)
- {
- total_size += sizeof(int32); /* size of name len */
- total_size += XP_STRLEN(name)+1;
-
- total_size += sizeof(int32); /* size of value len */
- if(value)
- total_size += XP_STRLEN(value)+1;
-
- PC_EnumerateNameValueArray(array, &name, &value, FALSE);
- }
-
- /* malloc enough space */
- *data = XP_ALLOC(sizeof(char) * total_size);
-
- if(!*data)
- return;
-
- cur_ptr = *data;
-
- net_long = PR_htonl(total_size);
- XP_MEMCPY(cur_ptr, &net_long, sizeof(int32));
- cur_ptr += sizeof(int32);
-
- net_long = PR_htonl(SERIALIZER_VERSION_NUM);
- XP_MEMCPY(cur_ptr, &net_long, sizeof(int32));
- cur_ptr += sizeof(int32);
-
- net_long = PR_htonl(PC_ArraySize(array));
- XP_MEMCPY(cur_ptr, &net_long, sizeof(int32));
- cur_ptr += sizeof(int32);
-
- PC_EnumerateNameValueArray(array, &name, &value, TRUE);
- while(name)
- {
- net_long = PR_htonl((name ? XP_STRLEN(name)+1 : 0));
- XP_MEMCPY(cur_ptr, &net_long, sizeof(int32));
- cur_ptr += sizeof(int32);
- net_long = PR_ntohl(net_long); /* convert back to true len */
- if(net_long)
- XP_MEMCPY((void *)cur_ptr, name, net_long);
- cur_ptr += net_long;
-
- net_long = PR_htonl((value ? XP_STRLEN(value)+1 : 0));
- XP_MEMCPY(cur_ptr, &net_long, sizeof(int32));
- cur_ptr += sizeof(int32);
- net_long = PR_ntohl(net_long); /* convert back to true len */
- if(net_long)
- XP_MEMCPY((void *)cur_ptr, value, net_long);
- cur_ptr += net_long;
-
- PC_EnumerateNameValueArray(array, &name, &value, FALSE);
- }
-
- *len = total_size;
-
- return;
- }
-
- /* returns a PCNameValueArray from serialized char data.
- *
- * returns NULL on error
- */
- PUBLIC PCNameValueArray *
- PC_CharToNameValueArray(char *data, int32 len)
- {
- int32 host_long, str_len, len_read, array_size, index;
- char *cur_ptr;
- char *name, *value;
- PCNameValueArray *array;
-
- /* must be at least 12 bytes, len and ver and array_size */
- XP_ASSERT(len >= 12);
-
- if(len < 12)
- return NULL;
-
- cur_ptr = data;
-
- /* read first 4 bytes as checksum */
- XP_MEMCPY(&host_long, cur_ptr, 4);
- host_long = PR_ntohl(host_long);
- cur_ptr += sizeof(int32);
- len_read = sizeof(int32);
-
- if(host_long != len)
- {
- XP_ASSERT(0); /* this one might happen on db error */
- return NULL; /* failed checksum */
- }
-
- /* read next 4 bytes as ver */
- XP_MEMCPY(&host_long, cur_ptr, 4);
- host_long = PR_ntohl(host_long);
- cur_ptr += sizeof(int32);
- len_read += sizeof(int32);
-
- if(host_long != SERIALIZER_VERSION_NUM)
- {
- XP_ASSERT(0);
- return NULL; /* failed ver check */
- }
-
- /* read next 4 bytes as array_size */
- XP_MEMCPY(&array_size, cur_ptr, 4);
- array_size = PR_ntohl(array_size);
- cur_ptr += sizeof(int32);
- len_read += sizeof(int32);
-
- /* malloc arrays */
- array = pc_new_namevaluearray(array_size);
- if(!array)
- return NULL;
-
- index = 0;
- while(len_read < len)
- {
- /* next 4 bytes is length of name string */
- XP_MEMCPY(&str_len, cur_ptr, 4);
- str_len = PR_ntohl(str_len);
- cur_ptr += sizeof(int32);
- len_read += sizeof(int32);
-
- if(len_read + str_len > len)
- goto error_out;
-
- name = XP_ALLOC(str_len * sizeof(char));
- if(!name)
- goto error_out;
-
- XP_MEMCPY(name, cur_ptr, str_len);
- len_read += str_len;
- cur_ptr += str_len;
-
- if(len_read >= len)
- goto error_out;
-
- /* next 4 bytes is length of value string */
- XP_MEMCPY(&str_len, cur_ptr, 4);
- str_len = PR_ntohl(str_len);
- cur_ptr += sizeof(int32);
- len_read += sizeof(int32);
-
- if(len_read + str_len > len)
- goto error_out;
-
- value = XP_ALLOC(str_len * sizeof(char));
- if(!value)
- goto error_out;
-
- XP_MEMCPY(value, cur_ptr, str_len);
- len_read += str_len;
- cur_ptr += str_len;
-
- pc_add_to_namevaluearray(array, name, value);
-
- index++;
- }
-
- XP_ASSERT(len_read == len);
-
- return array;
-
- error_out:
-
- XP_ASSERT(0);
-
- PC_FreeNameValueArray(array);
-
- return NULL;
- }
-