mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2025-12-08 16:43:25 +00:00
* Merged version 2.1 of GoAhead webserver. This update was submitted by Antti P Miettinen <antti.p.miettinen@nokia.com>. * NOTES, base64.c, ejIntrn.h, emfdb.c, emfdb.h, md5.h, md5c.c, um.c, um.h: New files. * wbase64.c: Removed. * Makefile.am, asp.c, balloc.c, default.c, ej.h, ejlex.c, ejparse.c, form.c, h.c, handler.c, mime.c, misc.c, ringq.c, rom.c, security.c, socket.c, sym.c, uemf.c, uemf.h, url.c, value.c, webcomp.c, webmain.c, webpage.c, webrom.c, webs.c, webs.h, websuemf.c, wsIntrn.h: Modified.
1416 lines
30 KiB
C
1416 lines
30 KiB
C
/*
|
|
* um.c -- User Management
|
|
*
|
|
* Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
|
|
*
|
|
* See the file "license.txt" for usage and redistribution license requirements
|
|
*
|
|
* $Id$
|
|
*/
|
|
|
|
/******************************** Description *********************************/
|
|
/*
|
|
* User Management routines for adding/deleting/changing users and groups
|
|
* Also, routines for determining user access
|
|
*/
|
|
|
|
/********************************* Includes ***********************************/
|
|
|
|
#include "um.h"
|
|
#include "emfdb.h"
|
|
#include "webs.h"
|
|
|
|
/********************************** Defines ***********************************/
|
|
|
|
#define UM_DB_FILENAME T("um.xml")
|
|
#define UM_TXT_FILENAME T("umconfig.txt")
|
|
|
|
/*
|
|
* Table names
|
|
*/
|
|
#define UM_USER_TABLENAME T("users")
|
|
#define UM_GROUP_TABLENAME T("groups")
|
|
#define UM_ACCESS_TABLENAME T("access")
|
|
|
|
/*
|
|
* Column names
|
|
*/
|
|
#define UM_NAME T("name")
|
|
#define UM_PASS T("password")
|
|
#define UM_GROUP T("group")
|
|
#define UM_PROT T("prot")
|
|
#define UM_DISABLE T("disable")
|
|
#define UM_METHOD T("method")
|
|
#define UM_PRIVILEGE T("priv")
|
|
#define UM_SECURE T("secure")
|
|
|
|
/*
|
|
* XOR encryption mask
|
|
* Note: This string should be modified for individual sites
|
|
* in order to enhance user password security.
|
|
*/
|
|
#define UM_XOR_ENCRYPT T("*j7a(L#yZ98sSd5HfSgGjMj8;Ss;d)(*&^#@$a2s0i3g")
|
|
|
|
/******************************** Local Data **********************************/
|
|
|
|
#ifdef UEMF
|
|
/*
|
|
* User table definition
|
|
*/
|
|
#define NUMBER_OF_USER_COLUMNS 5
|
|
|
|
char_t *userColumnNames[NUMBER_OF_USER_COLUMNS] = {
|
|
UM_NAME, UM_PASS, UM_GROUP, UM_PROT, UM_DISABLE
|
|
};
|
|
|
|
int userColumnTypes[NUMBER_OF_USER_COLUMNS] = {
|
|
T_STRING, T_STRING, T_STRING, T_INT, T_INT
|
|
};
|
|
|
|
dbTable_t userTable = {
|
|
UM_USER_TABLENAME,
|
|
NUMBER_OF_USER_COLUMNS,
|
|
userColumnNames,
|
|
userColumnTypes,
|
|
0,
|
|
NULL
|
|
};
|
|
|
|
/*
|
|
* Group table definition
|
|
*/
|
|
#define NUMBER_OF_GROUP_COLUMNS 5
|
|
|
|
char_t *groupColumnNames[NUMBER_OF_GROUP_COLUMNS] = {
|
|
UM_NAME, UM_PRIVILEGE, UM_METHOD, UM_PROT, UM_DISABLE
|
|
};
|
|
|
|
int groupColumnTypes[NUMBER_OF_GROUP_COLUMNS] = {
|
|
T_STRING, T_INT, T_INT, T_INT, T_INT
|
|
};
|
|
|
|
dbTable_t groupTable = {
|
|
UM_GROUP_TABLENAME,
|
|
NUMBER_OF_GROUP_COLUMNS,
|
|
groupColumnNames,
|
|
groupColumnTypes,
|
|
0,
|
|
NULL
|
|
};
|
|
|
|
/*
|
|
* Access Limit table definition
|
|
*/
|
|
#define NUMBER_OF_ACCESS_COLUMNS 4
|
|
|
|
char_t *accessColumnNames[NUMBER_OF_ACCESS_COLUMNS] = {
|
|
UM_NAME, UM_METHOD, UM_SECURE, UM_GROUP
|
|
};
|
|
|
|
int accessColumnTypes[NUMBER_OF_ACCESS_COLUMNS] = {
|
|
T_STRING, T_INT, T_INT, T_STRING
|
|
};
|
|
|
|
dbTable_t accessTable = {
|
|
UM_ACCESS_TABLENAME,
|
|
NUMBER_OF_ACCESS_COLUMNS,
|
|
accessColumnNames,
|
|
accessColumnTypes,
|
|
0,
|
|
NULL
|
|
};
|
|
#endif /* #ifdef UEMF */
|
|
|
|
/*
|
|
* Database Identifier returned from dbOpen()
|
|
*/
|
|
static int didUM = -1;
|
|
|
|
/*
|
|
* Configuration database persist filename
|
|
*/
|
|
static char_t *saveFilename = NULL;
|
|
|
|
static int umOpenCount = 0; /* count of apps using this module */
|
|
|
|
/*************************** Forward Declarations *****************************/
|
|
|
|
static bool_t umCheckName(char_t *name);
|
|
|
|
/*********************************** Code *************************************/
|
|
/*
|
|
* umOpen() registers the UM tables in the fake emf-database
|
|
*/
|
|
|
|
int umOpen()
|
|
{
|
|
if (++umOpenCount != 1) {
|
|
return didUM;
|
|
}
|
|
/*
|
|
* Do not initialize if intialization has already taken place
|
|
*/
|
|
if (didUM == -1) {
|
|
didUM = dbOpen(UM_USER_TABLENAME, UM_DB_FILENAME, NULL, 0);
|
|
#ifdef UEMF
|
|
dbRegisterDBSchema(&userTable);
|
|
dbRegisterDBSchema(&groupTable);
|
|
dbRegisterDBSchema(&accessTable);
|
|
#endif
|
|
}
|
|
|
|
if (saveFilename == NULL) {
|
|
saveFilename = bstrdup(B_L, UM_TXT_FILENAME);
|
|
}
|
|
|
|
return didUM;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umClose() frees up the UM tables in the fake emf-database
|
|
*/
|
|
|
|
void umClose()
|
|
{
|
|
if (--umOpenCount > 0) {
|
|
return;
|
|
}
|
|
/*
|
|
* Do not close if intialization has not taken place
|
|
*/
|
|
if (didUM != -1) {
|
|
dbClose(didUM);
|
|
didUM = -1;
|
|
}
|
|
|
|
if (saveFilename != NULL) {
|
|
bfree(B_L, saveFilename);
|
|
saveFilename = NULL;
|
|
}
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umCommit() persists all of the UM tables
|
|
*/
|
|
|
|
int umCommit(char_t *filename)
|
|
{
|
|
if (filename && *filename) {
|
|
if (saveFilename != NULL) {
|
|
bfree(B_L, saveFilename);
|
|
}
|
|
|
|
saveFilename = bstrdup(B_L, filename);
|
|
}
|
|
|
|
a_assert (saveFilename && *saveFilename);
|
|
trace(3, T("UM: Writing User Configuration to file <%s>\n"),
|
|
saveFilename);
|
|
|
|
return dbSave(didUM, saveFilename, 0);
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umRestore() loads up the UM tables with persisted data
|
|
*/
|
|
|
|
int umRestore(char_t *filename)
|
|
{
|
|
if (filename && *filename) {
|
|
if (saveFilename != NULL) {
|
|
bfree(B_L, saveFilename);
|
|
}
|
|
|
|
saveFilename = bstrdup(B_L, filename);
|
|
}
|
|
|
|
a_assert(saveFilename && *saveFilename);
|
|
|
|
trace(3, T("UM: Loading User Configuration from file <%s>\n"),
|
|
saveFilename);
|
|
|
|
/*
|
|
* First empty the database, otherwise we wind up with duplicates!
|
|
*/
|
|
dbZero(didUM);
|
|
return dbLoad(didUM, saveFilename, 0);
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* Encrypt/Decrypt a text string.
|
|
* Returns the number of characters encrypted.
|
|
*/
|
|
|
|
static int umEncryptString(char_t *textString)
|
|
{
|
|
char_t *enMask;
|
|
char_t enChar;
|
|
int numChars;
|
|
|
|
a_assert(textString);
|
|
|
|
enMask = UM_XOR_ENCRYPT;
|
|
numChars = 0;
|
|
|
|
while (*textString) {
|
|
enChar = *textString ^ *enMask;
|
|
/*
|
|
* Do not produce encrypted text with embedded linefeeds or tabs.
|
|
* Simply use existing character.
|
|
*/
|
|
if (enChar && !gisspace(enChar))
|
|
*textString = enChar;
|
|
/*
|
|
* Increment all pointers.
|
|
*/
|
|
enMask++;
|
|
textString++;
|
|
numChars++;
|
|
/*
|
|
* Wrap encryption mask pointer if at end of length.
|
|
*/
|
|
if (*enMask == '\0') {
|
|
enMask = UM_XOR_ENCRYPT;
|
|
}
|
|
}
|
|
|
|
return numChars;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umGetFirstRowData() - return a pointer to the first non-blank key value
|
|
* in the given column for the given table.
|
|
*/
|
|
|
|
static char_t *umGetFirstRowData(char_t *tableName, char_t *columnName)
|
|
{
|
|
char_t *columnData;
|
|
int row;
|
|
int check;
|
|
|
|
a_assert(tableName && *tableName);
|
|
a_assert(columnName && *columnName);
|
|
|
|
row = 0;
|
|
/*
|
|
* Move through table until we retrieve the first row with non-null
|
|
* column data.
|
|
*/
|
|
columnData = NULL;
|
|
while ((check = dbReadStr(didUM, tableName, columnName, row++,
|
|
&columnData)) == 0 || (check == DB_ERR_ROW_DELETED)) {
|
|
if (columnData && *columnData) {
|
|
return columnData;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umGetNextRowData() - return a pointer to the first non-blank
|
|
* key value following the given one.
|
|
*/
|
|
|
|
static char_t *umGetNextRowData(char_t *tableName, char_t *columnName,
|
|
char_t *keyLast)
|
|
{
|
|
char_t *key;
|
|
int row;
|
|
int check;
|
|
|
|
a_assert(tableName && *tableName);
|
|
a_assert(columnName && *columnName);
|
|
a_assert(keyLast && *keyLast);
|
|
/*
|
|
* Position row counter to row where the given key value was found
|
|
*/
|
|
row = 0;
|
|
key = NULL;
|
|
|
|
while ((((check = dbReadStr(didUM, tableName, columnName, row++,
|
|
&key)) == 0) || (check == DB_ERR_ROW_DELETED)) &&
|
|
((key == NULL) || (gstrcmp(key, keyLast) != 0))) {
|
|
}
|
|
/*
|
|
* If the last key value was not found, return NULL
|
|
*/
|
|
if (!key || gstrcmp(key, keyLast) != 0) {
|
|
return NULL;
|
|
}
|
|
/*
|
|
* Move through table until we retrieve the next row with a non-null key
|
|
*/
|
|
while (((check = dbReadStr(didUM, tableName, columnName, row++, &key))
|
|
== 0) || (check == DB_ERR_ROW_DELETED)) {
|
|
if (key && *key && (gstrcmp(key, keyLast) != 0)) {
|
|
return key;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umAddUser() - Adds a user to the "users" table.
|
|
*/
|
|
|
|
int umAddUser(char_t *user, char_t *pass, char_t *group,
|
|
bool_t prot, bool_t disabled)
|
|
{
|
|
int row;
|
|
char_t *password;
|
|
|
|
a_assert(user && *user);
|
|
a_assert(pass && *pass);
|
|
a_assert(group && *group);
|
|
|
|
trace(3, T("UM: Adding User <%s>\n"), user);
|
|
|
|
/*
|
|
* Do not allow duplicates
|
|
*/
|
|
if (umUserExists(user)) {
|
|
return UM_ERR_DUPLICATE;
|
|
}
|
|
|
|
/*
|
|
* Make sure user name and password contain valid characters
|
|
*/
|
|
if (!umCheckName(user)) {
|
|
return UM_ERR_BAD_NAME;
|
|
}
|
|
|
|
if (!umCheckName(pass)) {
|
|
return UM_ERR_BAD_PASSWORD;
|
|
}
|
|
|
|
/*
|
|
* Make sure group exists
|
|
*/
|
|
if (!umGroupExists(group)) {
|
|
return UM_ERR_NOT_FOUND;
|
|
}
|
|
|
|
/*
|
|
* Now create the user record
|
|
*/
|
|
row = dbAddRow(didUM, UM_USER_TABLENAME);
|
|
|
|
if (row < 0) {
|
|
return UM_ERR_GENERAL;
|
|
}
|
|
|
|
if (dbWriteStr(didUM, UM_USER_TABLENAME, UM_NAME, row, user) != 0) {
|
|
return UM_ERR_GENERAL;
|
|
}
|
|
|
|
password = bstrdup(B_L, pass);
|
|
umEncryptString(password);
|
|
dbWriteStr(didUM, UM_USER_TABLENAME, UM_PASS, row, password);
|
|
bfree(B_L, password);
|
|
dbWriteStr(didUM, UM_USER_TABLENAME, UM_GROUP, row, group);
|
|
dbWriteInt(didUM, UM_USER_TABLENAME, UM_PROT, row, prot);
|
|
dbWriteInt(didUM, UM_USER_TABLENAME, UM_DISABLE, row, disabled);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umDeleteUser() - remove a user from the "users" table
|
|
*/
|
|
|
|
int umDeleteUser(char_t *user)
|
|
{
|
|
int row;
|
|
|
|
a_assert(user && *user);
|
|
trace(3, T("UM: Deleting User <%s>\n"), user);
|
|
/*
|
|
* Check to see if user is delete-protected
|
|
*/
|
|
if (umGetUserProtected(user)) {
|
|
return UM_ERR_PROTECTED;
|
|
}
|
|
|
|
/*
|
|
* If found, delete the user from the database
|
|
*/
|
|
if ((row = dbSearchStr(didUM, UM_USER_TABLENAME, UM_NAME, user, 0)) >= 0) {
|
|
return dbDeleteRow(didUM, UM_USER_TABLENAME, row);
|
|
}
|
|
|
|
return UM_ERR_NOT_FOUND;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umGetFirstUser() - Returns the user ID of the first user found in the
|
|
* "users" table.
|
|
*/
|
|
|
|
char_t *umGetFirstUser()
|
|
{
|
|
return umGetFirstRowData(UM_USER_TABLENAME, UM_NAME);
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umGetNextUser() Returns the next user found in the "users" table after
|
|
* the given user.
|
|
*/
|
|
|
|
char_t *umGetNextUser(char_t *userLast)
|
|
{
|
|
return umGetNextRowData(UM_USER_TABLENAME, UM_NAME, userLast);
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umUserExists() Returns TRUE if userid exists.
|
|
*/
|
|
|
|
bool_t umUserExists(char_t *user)
|
|
{
|
|
a_assert(user && *user);
|
|
|
|
if (dbSearchStr(didUM, UM_USER_TABLENAME, UM_NAME, user, 0) >= 0) {
|
|
return TRUE;
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umGetUserPassword() returns a de-crypted copy of the user password
|
|
*/
|
|
|
|
char_t *umGetUserPassword(char_t *user)
|
|
{
|
|
char_t *password;
|
|
int row;
|
|
|
|
a_assert(user && *user);
|
|
|
|
password = NULL;
|
|
row = dbSearchStr(didUM, UM_USER_TABLENAME, UM_NAME, user, 0);
|
|
|
|
if (row >= 0) {
|
|
char_t *pass = NULL;
|
|
dbReadStr(didUM, UM_USER_TABLENAME, UM_PASS, row, &pass);
|
|
/*
|
|
* Decrypt password
|
|
* Note, this function returns a copy of the password, which must
|
|
* be deleted at some time in the future.
|
|
*/
|
|
password = bstrdup(B_L, pass);
|
|
umEncryptString(password);
|
|
}
|
|
|
|
return password;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umSetUserPassword() updates the user password in the user "table" after
|
|
* encrypting the given password
|
|
*/
|
|
|
|
int umSetUserPassword(char_t *user, char_t *pass)
|
|
{
|
|
int row, nRet;
|
|
char_t *password;
|
|
|
|
a_assert(user && *user);
|
|
a_assert(pass && *pass);
|
|
trace(3, T("UM: Attempting to change the password for user <%s>\n"), user);
|
|
/*
|
|
* Find the row of the user
|
|
*/
|
|
if ((row = dbSearchStr(didUM, UM_USER_TABLENAME, UM_NAME, user, 0)) < 0) {
|
|
return UM_ERR_NOT_FOUND;
|
|
}
|
|
|
|
password = bstrdup(B_L, pass);
|
|
umEncryptString(password);
|
|
nRet = dbWriteStr(didUM, UM_USER_TABLENAME, UM_PASS, row, password);
|
|
bfree(B_L, password);
|
|
|
|
return nRet;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umGetUserGroup() returns the name of the user group
|
|
*/
|
|
|
|
char_t *umGetUserGroup(char_t *user)
|
|
{
|
|
char_t *group;
|
|
int row;
|
|
|
|
a_assert(user && *user);
|
|
group = NULL;
|
|
/*
|
|
* Find the row of the user
|
|
*/
|
|
row = dbSearchStr(didUM, UM_USER_TABLENAME, UM_NAME, user, 0);
|
|
|
|
if (row >= 0) {
|
|
dbReadStr(didUM, UM_USER_TABLENAME, UM_GROUP, row, &group);
|
|
}
|
|
|
|
return group;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umSetUserGroup() Sets the name of the user group for the user
|
|
*/
|
|
|
|
int umSetUserGroup(char_t *user, char_t *group)
|
|
{
|
|
int row;
|
|
|
|
a_assert(user && *user);
|
|
a_assert(group && *group);
|
|
/*
|
|
* Find the row of the user
|
|
*/
|
|
row = dbSearchStr(didUM, UM_USER_TABLENAME, UM_NAME, user, 0);
|
|
|
|
if (row >= 0) {
|
|
return dbWriteStr(didUM, UM_USER_TABLENAME, UM_GROUP, row, group);
|
|
} else {
|
|
return UM_ERR_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umGetUserEnabled() - returns if the user is enabled
|
|
* Returns FALSE if the user is not found.
|
|
*/
|
|
|
|
bool_t umGetUserEnabled(char_t *user)
|
|
{
|
|
int disabled, row;
|
|
|
|
a_assert(user && *user);
|
|
|
|
disabled = 1;
|
|
/*
|
|
* Find the row of the user
|
|
*/
|
|
row = dbSearchStr(didUM, UM_USER_TABLENAME, UM_NAME, user, 0);
|
|
|
|
if (row >= 0) {
|
|
dbReadInt(didUM, UM_USER_TABLENAME, UM_DISABLE, row, &disabled);
|
|
}
|
|
|
|
return (bool_t)!disabled;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umSetUserEnabled() Enables/disables the user
|
|
*/
|
|
int umSetUserEnabled(char_t *user, bool_t enabled)
|
|
{
|
|
int row;
|
|
|
|
a_assert(user && *user);
|
|
/*
|
|
* Find the row of the user
|
|
*/
|
|
row = dbSearchStr(didUM, UM_USER_TABLENAME, UM_NAME, user, 0);
|
|
if (row >= 0) {
|
|
return dbWriteInt(didUM, UM_USER_TABLENAME, UM_DISABLE, row, !enabled);
|
|
} else {
|
|
return UM_ERR_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umGetUserProtected() - determine deletability of user
|
|
*/
|
|
|
|
bool_t umGetUserProtected(char_t *user)
|
|
{
|
|
int protect, row;
|
|
|
|
a_assert(user && *user);
|
|
/*
|
|
* Find the row of the user
|
|
*/
|
|
row = dbSearchStr(didUM, UM_USER_TABLENAME, UM_NAME, user, 0);
|
|
protect = FALSE;
|
|
|
|
if (row >= 0) {
|
|
dbReadInt(didUM, UM_USER_TABLENAME, UM_PROT, row, &protect);
|
|
}
|
|
|
|
return (bool_t)protect;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umSetUserProtected() sets the delete protection for the user
|
|
*/
|
|
int umSetUserProtected(char_t *user, bool_t protect)
|
|
{
|
|
int row;
|
|
|
|
a_assert(user && *user);
|
|
/*
|
|
* Find the row of the user
|
|
*/
|
|
row = dbSearchStr(didUM, UM_USER_TABLENAME, UM_NAME, user, 0);
|
|
|
|
if (row >= 0) {
|
|
return dbWriteInt(didUM, UM_USER_TABLENAME, UM_PROT, row, protect);
|
|
} else {
|
|
return UM_ERR_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umAddGroup() adds a group to the "Group" table
|
|
*/
|
|
|
|
int umAddGroup(char_t *group, short priv, accessMeth_t am,
|
|
bool_t prot, bool_t disabled)
|
|
{
|
|
int row;
|
|
|
|
a_assert(group && *group);
|
|
trace(3, T("UM: Adding group <%s>\n"), group);
|
|
|
|
/*
|
|
* Do not allow duplicates
|
|
*/
|
|
if (umGroupExists(group)) {
|
|
return UM_ERR_DUPLICATE;
|
|
}
|
|
|
|
/*
|
|
* Only allow valid characters in key field
|
|
*/
|
|
if (!umCheckName(group)) {
|
|
return UM_ERR_BAD_NAME;
|
|
}
|
|
|
|
/*
|
|
* Add a new row to the table
|
|
*/
|
|
if ((row = dbAddRow(didUM, UM_GROUP_TABLENAME)) < 0) {
|
|
return UM_ERR_GENERAL;
|
|
}
|
|
|
|
/*
|
|
* Write the key field
|
|
*/
|
|
if (dbWriteStr(didUM, UM_GROUP_TABLENAME, UM_NAME, row, group) != 0) {
|
|
return UM_ERR_GENERAL;
|
|
}
|
|
|
|
/*
|
|
* Write the remaining fields
|
|
*/
|
|
dbWriteInt(didUM, UM_GROUP_TABLENAME, UM_PRIVILEGE, row, priv);
|
|
dbWriteInt(didUM, UM_GROUP_TABLENAME, UM_METHOD, row, (int) am);
|
|
dbWriteInt(didUM, UM_GROUP_TABLENAME, UM_PROT, row, prot);
|
|
dbWriteInt(didUM, UM_GROUP_TABLENAME, UM_DISABLE, row, disabled);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umDeleteGroup() - Delete a user group, if not protected
|
|
*/
|
|
|
|
int umDeleteGroup(char_t *group)
|
|
{
|
|
int row;
|
|
|
|
a_assert(group && *group);
|
|
trace(3, T("UM: Deleting Group <%s>\n"), group);
|
|
|
|
/*
|
|
* Check to see if the group is in use
|
|
*/
|
|
if (umGetGroupInUse(group)) {
|
|
return UM_ERR_IN_USE;
|
|
}
|
|
|
|
/*
|
|
* Check to see if the group is delete-protected
|
|
*/
|
|
if (umGetGroupProtected(group)) {
|
|
return UM_ERR_PROTECTED;
|
|
}
|
|
|
|
/*
|
|
* Find the row of the group to delete
|
|
*/
|
|
if ((row = dbSearchStr(didUM, UM_GROUP_TABLENAME, UM_NAME, group, 0)) < 0) {
|
|
return UM_ERR_NOT_FOUND;
|
|
}
|
|
|
|
return dbDeleteRow(didUM, UM_GROUP_TABLENAME, row);
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umGroupExists() returns TRUE if group exists, FALSE otherwise
|
|
*/
|
|
|
|
bool_t umGroupExists(char_t *group)
|
|
{
|
|
a_assert(group && *group);
|
|
|
|
if (dbSearchStr(didUM, UM_GROUP_TABLENAME, UM_NAME, group, 0) >= 0) {
|
|
return TRUE;
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umGetGroupInUse() returns TRUE if the group is referenced by a user or by
|
|
* an access limit.
|
|
*/
|
|
|
|
bool_t umGetGroupInUse(char_t *group)
|
|
{
|
|
a_assert(group && *group);
|
|
|
|
/*
|
|
* First, check the user table
|
|
*/
|
|
if (dbSearchStr(didUM, UM_USER_TABLENAME, UM_GROUP, group, 0) >= 0) {
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* Second, check the access limit table
|
|
*/
|
|
if (dbSearchStr(didUM, UM_ACCESS_TABLENAME, UM_GROUP, group, 0) >= 0) {
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umGetFirstGroup() - return a pointer to the first non-blank group name
|
|
*/
|
|
|
|
char_t *umGetFirstGroup()
|
|
{
|
|
return umGetFirstRowData(UM_GROUP_TABLENAME, UM_NAME);
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umGetNextGroup() - return a pointer to the first non-blank group name
|
|
* following the given group name
|
|
*/
|
|
|
|
char_t *umGetNextGroup(char_t *groupLast)
|
|
{
|
|
return umGetNextRowData(UM_GROUP_TABLENAME, UM_NAME, groupLast);
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* Returns the default access method to use for a given group
|
|
*/
|
|
|
|
accessMeth_t umGetGroupAccessMethod(char_t *group)
|
|
{
|
|
int am, row;
|
|
|
|
a_assert(group && *group);
|
|
row = dbSearchStr(didUM, UM_GROUP_TABLENAME, UM_NAME, group, 0);
|
|
|
|
if (row >= 0) {
|
|
dbReadInt(didUM, UM_GROUP_TABLENAME, UM_METHOD, row, (int *)&am);
|
|
} else {
|
|
am = AM_INVALID;
|
|
}
|
|
|
|
return (accessMeth_t) am;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* Set the default access method to use for a given group
|
|
*/
|
|
|
|
int umSetGroupAccessMethod(char_t *group, accessMeth_t am)
|
|
{
|
|
int row;
|
|
|
|
a_assert(group && *group);
|
|
row = dbSearchStr(didUM, UM_GROUP_TABLENAME, UM_NAME, group, 0);
|
|
|
|
if (row >= 0) {
|
|
return dbWriteInt(didUM, UM_GROUP_TABLENAME, UM_METHOD, row, (int) am);
|
|
} else {
|
|
return UM_ERR_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* Returns the privilege mask for a given group
|
|
*/
|
|
|
|
short umGetGroupPrivilege(char_t *group)
|
|
{
|
|
int privilege, row;
|
|
|
|
a_assert(group && *group);
|
|
privilege = -1;
|
|
row = dbSearchStr(didUM, UM_GROUP_TABLENAME, UM_NAME, group, 0);
|
|
|
|
if (row >= 0) {
|
|
dbReadInt(didUM, UM_GROUP_TABLENAME, UM_PRIVILEGE, row, &privilege);
|
|
}
|
|
|
|
return (short) privilege;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* Set the privilege mask for a given group
|
|
*/
|
|
|
|
int umSetGroupPrivilege(char_t *group, short privilege)
|
|
{
|
|
int row;
|
|
|
|
a_assert(group && *group);
|
|
row = dbSearchStr(didUM, UM_GROUP_TABLENAME, UM_NAME, group, 0);
|
|
|
|
if (row >= 0) {
|
|
return dbWriteInt(didUM, UM_GROUP_TABLENAME, UM_PRIVILEGE, row,
|
|
(int)privilege);
|
|
} else {
|
|
return UM_ERR_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* Returns the enabled setting for a given group.
|
|
* Returns FALSE if group is not found.
|
|
*/
|
|
|
|
bool_t umGetGroupEnabled(char_t *group)
|
|
{
|
|
int disabled, row;
|
|
|
|
a_assert(group && *group);
|
|
row = dbSearchStr(didUM, UM_GROUP_TABLENAME, UM_NAME, group, 0);
|
|
disabled = 1;
|
|
|
|
if (row >= 0) {
|
|
dbReadInt(didUM, UM_GROUP_TABLENAME, UM_DISABLE, row, &disabled);
|
|
}
|
|
|
|
return (bool_t) !disabled;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* Sets the enabled setting for a given group.
|
|
*/
|
|
|
|
int umSetGroupEnabled(char_t *group, bool_t enabled)
|
|
{
|
|
int row;
|
|
|
|
a_assert(group && *group);
|
|
row = dbSearchStr(didUM, UM_GROUP_TABLENAME, UM_NAME, group, 0);
|
|
|
|
if (row >= 0) {
|
|
return dbWriteInt(didUM, UM_GROUP_TABLENAME, UM_DISABLE, row,
|
|
(int) !enabled);
|
|
} else {
|
|
return UM_ERR_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* Returns the protected setting for a given group
|
|
* Returns FALSE if user is not found
|
|
*/
|
|
|
|
bool_t umGetGroupProtected(char_t *group)
|
|
{
|
|
int protect, row;
|
|
|
|
a_assert(group && *group);
|
|
|
|
protect = 0;
|
|
row = dbSearchStr(didUM, UM_GROUP_TABLENAME, UM_NAME, group, 0);
|
|
if (row >= 0) {
|
|
dbReadInt(didUM, UM_GROUP_TABLENAME, UM_PROT, row, &protect);
|
|
}
|
|
|
|
return (bool_t) protect;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* Sets the protected setting for a given group
|
|
*/
|
|
|
|
int umSetGroupProtected(char_t *group, bool_t protect)
|
|
{
|
|
int row;
|
|
|
|
a_assert(group && *group);
|
|
row = dbSearchStr(didUM, UM_GROUP_TABLENAME, UM_NAME, group, 0);
|
|
|
|
if (row >= 0) {
|
|
return dbWriteInt(didUM, UM_GROUP_TABLENAME, UM_PROT, row,
|
|
(int) protect);
|
|
} else {
|
|
return UM_ERR_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umAddAccessLimit() adds an access limit to the "access" table
|
|
*/
|
|
|
|
int umAddAccessLimit(char_t *url, accessMeth_t am, short secure, char_t *group)
|
|
{
|
|
int row;
|
|
|
|
a_assert(url && *url);
|
|
trace(3, T("UM: Adding Access Limit for <%s>\n"), url);
|
|
|
|
/*
|
|
* Do not allow duplicates
|
|
*/
|
|
if (umAccessLimitExists(url)) {
|
|
return UM_ERR_DUPLICATE;
|
|
}
|
|
|
|
/*
|
|
* Add a new row to the table
|
|
*/
|
|
if ((row = dbAddRow(didUM, UM_ACCESS_TABLENAME)) < 0) {
|
|
return UM_ERR_GENERAL;
|
|
}
|
|
|
|
/*
|
|
* Write the key field
|
|
*/
|
|
if(dbWriteStr(didUM, UM_ACCESS_TABLENAME, UM_NAME, row, url) < 0) {
|
|
return UM_ERR_GENERAL;
|
|
}
|
|
|
|
/*
|
|
* Write the remaining fields
|
|
*/
|
|
dbWriteInt(didUM, UM_ACCESS_TABLENAME, UM_METHOD, row, (int)am);
|
|
dbWriteInt(didUM, UM_ACCESS_TABLENAME, UM_SECURE, row, (int)secure);
|
|
dbWriteStr(didUM, UM_ACCESS_TABLENAME, UM_GROUP, row, group);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umDeleteAccessLimit()
|
|
*/
|
|
|
|
int umDeleteAccessLimit(char_t *url)
|
|
{
|
|
int row;
|
|
|
|
a_assert(url && *url);
|
|
trace(3, T("UM: Deleting Access Limit for <%s>\n"), url);
|
|
/*
|
|
* Find the row of the access limit to delete
|
|
*/
|
|
if ((row = dbSearchStr(didUM, UM_ACCESS_TABLENAME, UM_NAME, url, 0)) < 0) {
|
|
return UM_ERR_NOT_FOUND;
|
|
}
|
|
|
|
return dbDeleteRow(didUM, UM_ACCESS_TABLENAME, row);
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umGetFirstGroup() - return a pointer to the first non-blank access limit
|
|
*/
|
|
|
|
char_t *umGetFirstAccessLimit()
|
|
{
|
|
return umGetFirstRowData(UM_ACCESS_TABLENAME, UM_NAME);
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umGetNextAccessLimit() - return a pointer to the first non-blank
|
|
* access limit following the given one
|
|
*/
|
|
|
|
char_t *umGetNextAccessLimit(char_t *urlLast)
|
|
{
|
|
return umGetNextRowData(UM_ACCESS_TABLENAME, UM_NAME, urlLast);
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umAccessLimitExists() returns TRUE if this access limit exists
|
|
*/
|
|
|
|
bool_t umAccessLimitExists(char_t *url)
|
|
{
|
|
a_assert(url && *url);
|
|
|
|
if (dbSearchStr(didUM, UM_ACCESS_TABLENAME, UM_NAME, url, 0) < 0) {
|
|
return FALSE;
|
|
} else {
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umGetAccessLimit() returns the Access Method for the URL
|
|
*/
|
|
|
|
accessMeth_t umGetAccessLimitMethod(char_t *url)
|
|
{
|
|
int am, row;
|
|
|
|
am = (int) AM_INVALID;
|
|
row = dbSearchStr(didUM, UM_ACCESS_TABLENAME, UM_NAME, url, 0);
|
|
|
|
if (row >= 0) {
|
|
dbReadInt(didUM, UM_ACCESS_TABLENAME, UM_METHOD, row, &am);
|
|
}
|
|
|
|
return (accessMeth_t) am;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umSetAccessLimitMethod() - set Access Method for Access Limit
|
|
*/
|
|
|
|
int umSetAccessLimitMethod(char_t *url, accessMeth_t am)
|
|
{
|
|
int row;
|
|
|
|
a_assert(url && *url);
|
|
row = dbSearchStr(didUM, UM_ACCESS_TABLENAME, UM_NAME, url, 0);
|
|
|
|
if (row >= 0) {
|
|
return dbWriteInt(didUM, UM_ACCESS_TABLENAME, UM_METHOD, row, (int) am);
|
|
} else {
|
|
return UM_ERR_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umGetAccessLimitSecure() - returns secure switch for access limit
|
|
*/
|
|
|
|
short umGetAccessLimitSecure(char_t *url)
|
|
{
|
|
int secure, row;
|
|
|
|
a_assert(url && *url);
|
|
secure = -1;
|
|
row = dbSearchStr(didUM, UM_ACCESS_TABLENAME, UM_NAME, url, 0);
|
|
|
|
if (row >= 0) {
|
|
dbReadInt(didUM, UM_ACCESS_TABLENAME, UM_SECURE, row, &secure);
|
|
}
|
|
|
|
return (short)secure;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umSetAccessLimitSecure() - sets the secure flag for the URL
|
|
*/
|
|
|
|
int umSetAccessLimitSecure(char_t *url, short secure)
|
|
{
|
|
int row;
|
|
|
|
a_assert(url && *url);
|
|
row = dbSearchStr(didUM, UM_ACCESS_TABLENAME, UM_NAME, url, 0);
|
|
|
|
if (row >= 0) {
|
|
return dbWriteInt(didUM, UM_ACCESS_TABLENAME, UM_SECURE, row,
|
|
(int)secure);
|
|
} else {
|
|
return UM_ERR_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umGetAccessLimitGroup() - returns the user group of the access limit
|
|
*/
|
|
|
|
char_t *umGetAccessLimitGroup(char_t *url)
|
|
{
|
|
char_t *group;
|
|
int row;
|
|
|
|
a_assert(url && *url);
|
|
group = NULL;
|
|
row = dbSearchStr(didUM, UM_ACCESS_TABLENAME, UM_NAME, url, 0);
|
|
|
|
if (row >= 0) {
|
|
dbReadStr(didUM, UM_ACCESS_TABLENAME, UM_GROUP, row, &group);
|
|
}
|
|
|
|
return group;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* umSetAccessLimitGroup() - sets the user group for the access limit.
|
|
*/
|
|
|
|
int umSetAccessLimitGroup(char_t *url, char_t *group)
|
|
{
|
|
int row;
|
|
|
|
a_assert(url && *url);
|
|
row = dbSearchStr(didUM, UM_ACCESS_TABLENAME, UM_NAME, url, 0);
|
|
|
|
if (row >= 0) {
|
|
return dbWriteStr(didUM, UM_ACCESS_TABLENAME, UM_GROUP, row, group);
|
|
} else {
|
|
return UM_ERR_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* Returns the access limit to use for a given URL, by checking for URLs up
|
|
* the directory tree. Creates a new string that must be deleted.
|
|
*/
|
|
|
|
char_t *umGetAccessLimit(char_t *url)
|
|
{
|
|
char_t *urlRet, *urlCheck, *lastChar;
|
|
int len;
|
|
|
|
a_assert(url && *url);
|
|
urlRet = NULL;
|
|
urlCheck = bstrdup(B_L, url);
|
|
a_assert(urlCheck);
|
|
len = gstrlen(urlCheck);
|
|
/*
|
|
* Scan back through URL to see if there is a "parent" access limit
|
|
*/
|
|
while (len && !urlRet) {
|
|
if (umAccessLimitExists(urlCheck)) {
|
|
urlRet = bstrdup(B_L, urlCheck);
|
|
} else {
|
|
/*
|
|
* Trim the end portion of the URL to the previous directory marker
|
|
*/
|
|
lastChar = urlCheck + len;
|
|
lastChar--;
|
|
|
|
while ((lastChar >= urlCheck) && ((*lastChar == '/') ||
|
|
(*lastChar == '\\'))) {
|
|
*lastChar = 0;
|
|
lastChar--;
|
|
}
|
|
|
|
while ((lastChar >= urlCheck) && (*lastChar != '/') &&
|
|
(*lastChar != '\\')) {
|
|
*lastChar = 0;
|
|
lastChar--;
|
|
}
|
|
|
|
len = gstrlen(urlCheck);
|
|
}
|
|
}
|
|
bfree (B_L, urlCheck);
|
|
|
|
return urlRet;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* Returns the access method to use for a given URL
|
|
*/
|
|
|
|
accessMeth_t umGetAccessMethodForURL(char_t *url)
|
|
{
|
|
accessMeth_t amRet;
|
|
char_t *urlHavingLimit, *group;
|
|
|
|
urlHavingLimit = umGetAccessLimit(url);
|
|
if (urlHavingLimit) {
|
|
group = umGetAccessLimitGroup(urlHavingLimit);
|
|
|
|
if (group && *group) {
|
|
amRet = umGetGroupAccessMethod(group);
|
|
} else {
|
|
amRet = umGetAccessLimitMethod(urlHavingLimit);
|
|
}
|
|
|
|
bfree(B_L, urlHavingLimit);
|
|
} else {
|
|
amRet = AM_FULL;
|
|
}
|
|
|
|
return amRet;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* Returns TRUE if user can access URL
|
|
*/
|
|
|
|
bool_t umUserCanAccessURL(char_t *user, char_t *url)
|
|
{
|
|
accessMeth_t amURL;
|
|
char_t *group, *usergroup, *urlHavingLimit;
|
|
short priv;
|
|
|
|
a_assert(user && *user);
|
|
a_assert(url && *url);
|
|
|
|
/*
|
|
* Make sure user exists
|
|
*/
|
|
if (!umUserExists(user)) {
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Make sure user is enabled
|
|
*/
|
|
if (!umGetUserEnabled(user)) {
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Make sure user has sufficient privileges (any will do)
|
|
*/
|
|
usergroup = umGetUserGroup(user);
|
|
priv = umGetGroupPrivilege(usergroup);
|
|
if (priv == 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Make sure user's group is enabled
|
|
*/
|
|
if (!umGetGroupEnabled(usergroup)) {
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* The access method of the user group must not be AM_NONE
|
|
*/
|
|
if (umGetGroupAccessMethod(usergroup) == AM_NONE) {
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Check to see if there is an Access Limit for this URL
|
|
*/
|
|
urlHavingLimit = umGetAccessLimit(url);
|
|
if (urlHavingLimit) {
|
|
amURL = umGetAccessLimitMethod(urlHavingLimit);
|
|
group = umGetAccessLimitGroup(urlHavingLimit);
|
|
bfree(B_L, urlHavingLimit);
|
|
} else {
|
|
/*
|
|
* If there isn't an access limit for the URL, user has full access
|
|
*/
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* If the access method for the URL is AM_NONE then
|
|
* the file "doesn't exist".
|
|
*/
|
|
if (amURL == AM_NONE) {
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* If Access Limit has a group specified, then the user must be a
|
|
* member of that group
|
|
*/
|
|
if (group && *group) {
|
|
if (usergroup && (gstrcmp(group, usergroup) != 0)) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Otherwise, user can access the URL
|
|
*/
|
|
return TRUE;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* Returns TRUE if given name has only valid chars
|
|
*/
|
|
|
|
static bool_t umCheckName(char_t *name)
|
|
{
|
|
a_assert(name && *name);
|
|
|
|
if (name && *name) {
|
|
while (*name) {
|
|
if (gisspace(*name)) {
|
|
return FALSE;
|
|
}
|
|
|
|
name++;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/******************************************************************************/
|