/** BEGIN COPYRIGHT BLOCK
* Copyright 2001 Sun Microsystems, Inc.
* Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
* All rights reserved.
* END COPYRIGHT BLOCK **/
/*
* Description (nsadb.c)
*
* This module contains routines for retrieving information from
* a Netscape authentication database. An authentication database
* consists of a user database and a group database. This module
* implements an authentication database based on Netscape user and
* group databases defined in nsuser.h and nsgroup.h, which in turn
* are based on the Netscape (server) database implementation
* defined in nsdb.h. The interface for managing information in
* an authentication database is described separately in nsamgmt.h.
*/
#include
#include
#include
#include
#include
#define __PRIVATE_NSADB
#include
#include
#include
/*
* Description (NSADB_AuthIF)
*
* This structure defines a generic authentication database
* interface for this module. It does not currently support
* user/group id lookup.
*/
AuthIF_t NSADB_AuthIF = {
0, /* find user/group by id */
nsadbFindByName, /* find user/group by name */
nsadbIdToName, /* lookup name for user/group id */
nsadbOpen, /* open a named database */
nsadbClose, /* close a database */
};
/*
* Description (nsadbClose)
*
* This function closes an authentication database previously opened
* via nsadbOpen().
*
* Arguments:
*
* authdb - handle returned by nsadbOpen()
* flags - unused (must be zero)
*/
NSAPI_PUBLIC void nsadbClose(void * authdb, int flags)
{
AuthDB_t * adb = (AuthDB_t *)authdb;
if (adb->adb_userdb != 0) {
ndbClose(adb->adb_userdb, 0);
}
if (adb->adb_groupdb != 0) {
ndbClose(adb->adb_groupdb, 0);
}
#if defined(CLIENT_AUTH)
nsadbCloseCerts(authdb, flags);
#endif
if (adb->adb_dbname) {
FREE(adb->adb_dbname);
}
FREE(adb);
}
/*
* Description (nsadbOpen)
*
* This function is used to open an authentication database.
* The caller specifies a name for the database, which is actually
* the name of a directory containing the files which comprise the
* database. The caller also indicates whether this is a new
* database, in which case it is created.
*
* Arguments:
*
* errp - error frame list pointer (may be null)
* adbname - name of this database (directory)
* flags - open flags:
* AIF_CREATE - new database (create)
* rptr - pointer to returned handle
*
* Returns:
*
* A handle for accessing the database is always returned via 'rptr'
* unless there was a shortage of dynamic memory, in which case a
* null handle is returned. The return value of the function is
* 0 if it completes successfully. An error is indicated by a
* negative return value (see nsautherr.h).
*/
NSAPI_PUBLIC int nsadbOpen(NSErr_t * errp,
char * adbname, int flags, void **rptr)
{
AuthDB_t * authdb = 0; /* pointer to database descriptor */
SYS_DIR dbdir; /* database directory handle */
int eid; /* error id code */
int rv; /* result value */
/* Make sure we have a place to return the database handle */
if (rptr == 0) goto err_inval;
/* Allocate the database descriptor */
authdb = (AuthDB_t *)MALLOC(sizeof(AuthDB_t));
if (authdb == 0) goto err_nomem;
/* Return the descriptor pointer as the database handle */
*rptr = (void *)authdb;
authdb->adb_dbname = STRDUP(adbname);
authdb->adb_userdb = 0;
authdb->adb_groupdb = 0;
#if defined(CLIENT_AUTH)
authdb->adb_certdb = 0;
authdb->adb_certlock = 0;
authdb->adb_certnm = 0;
#endif
authdb->adb_flags = 0;
/* See if the database directory exists */
dbdir = dir_open(adbname);
if (dbdir == 0) {
/* No, create it if this is a new database, else error */
if (flags & AIF_CREATE) {
rv = dir_create(adbname);
if (rv < 0) goto err_mkdir;
authdb->adb_flags |= ADBF_NEW;
}
else goto err_dopen;
}
else {
/* Ok, it's there */
dir_close(dbdir);
}
return 0;
err_inval:
eid = NSAUERR3000;
rv = NSAERRINVAL;
goto err_ret;
err_nomem:
/* Error - insufficient dynamic memory */
eid = NSAUERR3020;
rv = NSAERRNOMEM;
goto err_ret;
err_ret:
nserrGenerate(errp, rv, eid, NSAuth_Program, 0);
goto punt;
err_mkdir:
eid = NSAUERR3040;
rv = NSAERRMKDIR;
goto err_dir;
err_dopen:
eid = NSAUERR3060;
rv = NSAERROPEN;
goto err_dir;
err_dir:
nserrGenerate(errp, rv, eid, NSAuth_Program, 1, adbname);
goto punt;
punt:
/* Fatal error - free database descriptor and return null handle */
if (authdb) {
if (authdb->adb_dbname) {
FREE(authdb->adb_dbname);
}
FREE(authdb);
}
if (rptr) *rptr = 0;
return rv;
}
/*
* Description (nsadbOpenUsers)
*
* This function is called to open the users subdatabase of an
* open authentication database. The caller specifies flags to
* indicate whether read or write access is required. This
* function is normally called only by routines below the
* nsadbOpen() API, in response to perform particular operations
* on user or group objects. If the open is successful, the
* resulting handle is stored in the AuthDB_t structure.
*
* Arguments:
*
* errp - error frame list pointer (may be null)
* authdb - handle returned by nsadbOpen()
* flags - open flags:
* ADBF_UREAD - open for read
* ADBF_UWRITE - open for read/write
* Returns:
*
* The return value is zero if the operation is successfully
* completed. An error is indicated by a negative return value
* (see nsautherr.h), and an error frame is generated if an error
* frame list was provided.
*/
NSAPI_PUBLIC int nsadbOpenUsers(NSErr_t * errp, void * authdb, int flags)
{
AuthDB_t * adb = (AuthDB_t *)authdb;
char * userfn = 0; /* user database name */
int dblen; /* strlen(adb_dbname) */
int uversion; /* user database version number */
int eid; /* error id code */
int rv; /* result value */
if (adb == 0) goto err_inval;
/* Is the user database already open? */
if (adb->adb_userdb != 0) {
/* Yes, is it open for the desired access? */
if (adb->adb_flags & flags) {
/* Yes, that was easy */
return 0;
}
}
else {
/* We need to open the database */
/* Allocate space for the user database filename */
dblen = strlen(adb->adb_dbname);
userfn = (char *)MALLOC(dblen + strlen(ADBUSERDBNAME) + 2);
if (userfn == 0) goto err_nomem;
/* Construct user database name */
strcpy(userfn, adb->adb_dbname);
/* Put in a '/' (or '\') if it's not there */
if (userfn[dblen-1] != FILE_PATHSEP) {
userfn[dblen] = FILE_PATHSEP;
userfn[dblen+1] = 0;
++dblen;
}
strcpy(&userfn[dblen], ADBUSERDBNAME);
adb->adb_userdb = ndbOpen(errp,
userfn, 0, NDB_TYPE_USERDB, &uversion);
if (adb->adb_userdb == 0) goto err_uopen;
FREE(userfn);
}
/*
* We don't really reopen the database to get the desired
* access mode, since that is handled at the nsdb level.
* But we do update the flags, just for the record.
*/
adb->adb_flags &= ~(ADBF_UREAD|ADBF_UWRITE);
if (flags & ADBF_UWRITE) adb->adb_flags |= ADBF_UWRITE;
else adb->adb_flags |= ADBF_UREAD;
return 0;
err_inval:
eid = NSAUERR3200;
rv = NSAERRINVAL;
goto err_ret;
err_nomem:
eid = NSAUERR3220;
rv = NSAERRNOMEM;
goto err_ret;
err_ret:
nserrGenerate(errp, rv, eid, NSAuth_Program, 0);
goto punt;
err_uopen:
eid = NSAUERR3240;
rv = NSAERROPEN;
nserrGenerate(errp, rv, eid, NSAuth_Program, 1, userfn);
goto punt;
punt:
return rv;
}
/*
* Description (nsadbOpenGroups)
*
* This function is called to open the groups subdatabase of an
* open authentication database. The caller specifies flags to
* indicate whether read or write access is required. This
* function is normally called only by routines below the
* nsadbOpen() API, in response to perform particular operations
* on user or group objects. If the open is successful, the
* resulting handle is stored in the AuthDB_t structure.
*
* Arguments:
*
* errp - error frame list pointer (may be null)
* authdb - handle returned by nsadbOpen()
* flags - open flags:
* ADBF_GREAD - open for read
* ADBF_GWRITE - open for read/write
* Returns:
*
* The return value is zero if the operation is successfully
* completed. An error is indicated by a negative return value
* (see nsautherr.h), and an error frame is generated if an error
* frame list was provided.
*/
NSAPI_PUBLIC int nsadbOpenGroups(NSErr_t * errp, void * authdb, int flags)
{
AuthDB_t * adb = (AuthDB_t *)authdb;
char * groupfn = 0; /* group database name */
int dblen; /* strlen(adb_dbname) */
int gversion; /* group database version number */
int eid; /* error id code */
int rv; /* result value */
if (adb == 0) goto err_inval;
/* Is the group database already open? */
if (adb->adb_groupdb != 0) {
/* Yes, is it open for the desired access? */
if (adb->adb_flags & flags) {
/* Yes, that was easy */
return 0;
}
}
else {
/* We need to open the database */
/* Allocate space for the group database filename */
dblen = strlen(adb->adb_dbname);
groupfn = (char *)MALLOC(dblen + strlen(ADBGROUPDBNAME) + 2);
if (groupfn == 0) goto err_nomem;
/* Construct group database name */
strcpy(groupfn, adb->adb_dbname);
/* Put in a '/' (or '\') if it's not there */
if (groupfn[dblen-1] != FILE_PATHSEP) {
groupfn[dblen] = FILE_PATHSEP;
groupfn[dblen+1] = 0;
++dblen;
}
strcpy(&groupfn[dblen], ADBGROUPDBNAME);
adb->adb_groupdb = ndbOpen(errp,
groupfn, 0, NDB_TYPE_GROUPDB, &gversion);
if (adb->adb_groupdb == 0) goto err_gopen;
FREE(groupfn);
}
/*
* We don't really reopen the database to get the desired
* access mode, since that is handled at the nsdb level.
* But we do update the flags, just for the record.
*/
adb->adb_flags &= ~(ADBF_GREAD|ADBF_GWRITE);
if (flags & ADBF_GWRITE) adb->adb_flags |= ADBF_GWRITE;
else adb->adb_flags |= ADBF_GREAD;
return 0;
err_inval:
eid = NSAUERR3300;
rv = NSAERRINVAL;
goto err_ret;
err_nomem:
eid = NSAUERR3320;
rv = NSAERRNOMEM;
goto err_ret;
err_ret:
nserrGenerate(errp, rv, eid, NSAuth_Program, 0);
goto punt;
err_gopen:
eid = NSAUERR3340;
rv = NSAERROPEN;
nserrGenerate(errp, rv, eid, NSAuth_Program, 1, groupfn);
goto punt;
punt:
return rv;
}
/*
* Description (nsadbIdToName)
*
* This function looks up a specified user or group id in the
* authentication database. The name associated with the specified
* id is returned.
*
* Arguments:
*
* errp - error frame list pointer (may be null)
* authdb - handle returned by nsadbOpen()
* id - user or group id
* flags - AIF_USER or AIF_GROUP (defined in nsauth.h)
* rptr - pointer to returned group or user name
*
* Returns:
*
* The return value is zero if no error occurs,
* A negative return value indicates an error.
*/
NSAPI_PUBLIC int nsadbIdToName(NSErr_t * errp,
void * authdb, USI_t id, int flags, char **rptr)
{
AuthDB_t * adb = (AuthDB_t *)authdb;
void * whichdb = 0;
char * name;
int rv;
if (rptr != 0) *rptr = 0;
/* Decide whether to use user or group database */
if (flags & AIF_USER) {
whichdb = adb->adb_userdb;
if (whichdb == 0) {
rv = nsadbOpenUsers(errp, authdb, ADBF_UREAD);
if (rv < 0) goto punt;
whichdb = adb->adb_userdb;
}
}
else if (flags & AIF_GROUP) {
whichdb = adb->adb_groupdb;
if (whichdb == 0) {
rv = nsadbOpenGroups(errp, authdb, ADBF_GREAD);
if (rv < 0) goto punt;
whichdb = adb->adb_groupdb;
}
}
if (whichdb != 0) {
/* Get the name corresponding to the id */
rv = ndbIdToName(errp, whichdb, id, 0, &name);
if (rv < 0) goto punt;
if ((rptr != 0)) *rptr = name;
rv = 0;
}
punt:
return rv;
}
/*
* Description (nsadbFindByName)
*
* This function looks up a specified name in the authentication
* database. Flags specified by the caller indicate whether a
* group name, user name, or either should be found. The caller
* may optionally provide for the return of a user or group object
* pointer, in which case the information associated with a
* matching group or user is used to create a group or user object.
*
* Arguments:
*
* errp - error frame list pointer (may be null)
* authdb - handle returned by nsadbOpen()
* name - name of group or user
* flags - search flags (defined in nsauth.h)
* rptr - pointer to returned group or user
* object pointer (may be null)
*
* Returns:
*
* The return value is a non-negative value if no error occurs,
* and the value indicates whether the name matched a group or
* user:
*
* AIF_NONE - name did not match a group or user name
* AIF_GROUP - name matched a group name
* AIF_USER - name matched a user name
*
* If the value is AIF_GROUP or AIF_USER, and rptr is non-null,
* then a group or user object is created, and a pointer to it is
* returned in the location indicated by rptr.
*
* A negative return value indicates an error.
*/
NSAPI_PUBLIC int nsadbFindByName(NSErr_t * errp, void * authdb,
char * name, int flags, void **rptr)
{
AuthDB_t * adb = (AuthDB_t *)authdb;
ATR_t recptr;
int reclen;
int rv;
if (rptr != 0) *rptr = 0;
/* Search for group name? */
if (flags & AIF_GROUP) {
if (adb->adb_groupdb == 0) {
rv = nsadbOpenGroups(errp, authdb, ADBF_GREAD);
if (rv < 0) goto punt;
}
/* Look up the name in the group database */
rv = ndbFindName(errp, adb->adb_groupdb, 0, (char *)name,
&reclen, (char **)&recptr);
if (rv == 0) {
/* Found it. Make a group object if requested. */
if (rptr != 0) {
/* Got the group record. Decode into a group object. */
*rptr = (void *)groupDecode((NTS_t)name, reclen, recptr);
}
return AIF_GROUP;
}
}
/* Search for user name? */
if (flags & AIF_USER) {
if (adb->adb_userdb == 0) {
rv = nsadbOpenUsers(errp, authdb, ADBF_UREAD);
if (rv < 0) goto punt;
}
/* Look up the name in the user database */
rv = ndbFindName(errp, adb->adb_userdb, 0, (char *)name,
&reclen, (char **)&recptr);
if (rv == 0) {
/* Found it. Make a user object if requested. */
if (rptr != 0) {
/* Got the user record. Decode into a user object. */
*rptr = (void *)userDecode((NTS_t)name, reclen, recptr);
}
return AIF_USER;
}
}
/* Nothing found */
nserrDispose(errp);
return AIF_NONE;
punt:
return rv;
}