5793 lines
164 KiB
C
5793 lines
164 KiB
C
/****************************************************************************
|
|
|
|
|
| (C) Copyright 1996 - 2005 Novell, Inc.
|
|
| All Rights Reserved.
|
|
|
|
|
| This program is free software; you can redistribute it and/or
|
|
| modify it under the terms of version 2 of the GNU General Public
|
|
| License as published by the Free Software Foundation.
|
|
|
|
|
| This program is distributed in the hope that it will be useful,
|
|
| but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
| GNU General Public License for more details.
|
|
|
|
|
| You should have received a copy of the GNU General Public License
|
|
| along with this program; if not, contact Novell, Inc.
|
|
|
|
|
| To contact Novell about this file by physical or electronic mail,
|
|
| you may find current contact information at www.novell.com
|
|
|
|
|
|***************************************************************************
|
|
|
|
|
| Novell Storage Services (NSS) module
|
|
|
|
|
|---------------------------------------------------------------------------
|
|
|
|
|
| $Author: gpachner $
|
|
| $Date: 2008-04-11 02:30:25 +0530 (Fri, 11 Apr 2008) $
|
|
|
|
|
| $RCSfile$
|
|
| $Revision: 2315 $
|
|
|
|
|
|---------------------------------------------------------------------------
|
|
| This module is used to:
|
|
| These are the authorization routines that are model specific.
|
|
+-------------------------------------------------------------------------*/
|
|
#include <procdefs.h>
|
|
#include <version.h>
|
|
#include <portable.h>
|
|
#include <connect.h>
|
|
#include <connexp.h> /* NetWare Source*/
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <xError.h>
|
|
|
|
#include <omni.h> /* NSS Library*/
|
|
|
|
#include "zParams.h"
|
|
#include "zasAuthModel.h"
|
|
#include "zasAuthSpace.h"
|
|
#include "unixAuthSpace.h"
|
|
#include "msgGen.h"
|
|
#include "zasAuthCache.h"
|
|
#include "pssConnection.h"
|
|
#include "comnPublics.h"
|
|
#include "comnBeasts.h"
|
|
//#include "sanwErr.h"
|
|
#include "volume.h"
|
|
#include "pssStartup.h"
|
|
#include "msgName.h"
|
|
#include "nameSpace.h"
|
|
#include "comnZAS.h"
|
|
#include "guid.h"
|
|
#include "adminVolume.h"
|
|
#include "comnLock.h"
|
|
#include "objectIDStore.h"
|
|
#include "xAdminVolume.h"
|
|
#include "checker.h"
|
|
#include "nssPubs.h"
|
|
#include "hardLinkBeast.h"
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Global variables
|
|
*-------------------------------------------------------------------------*/
|
|
NINT ZASindex; /* the index assigned to the Z authorization space */
|
|
BOOL AuthorizeStarted = FALSE;
|
|
|
|
STATUS ZAS_RemoveLatchedACLEntry(
|
|
GeneralMsg_s *genMsg,
|
|
AuthBeast_s *authBeast,
|
|
UserID_t *trusteeID,
|
|
NINT purgedFileFlag,
|
|
Xaction_s *xaction);
|
|
|
|
STATUS ZAS_CountVis(
|
|
GeneralMsg_s *genMsg,
|
|
AuthBeast_s *authBeast,
|
|
NINT *entryCount);
|
|
|
|
STATUS ZAS_GetAllVis(
|
|
GeneralMsg_s *genMsg,
|
|
AuthBeast_s *authBeast,
|
|
VisEntry_s *vis,
|
|
NINT count);
|
|
|
|
/* Visibility rebuild stats */
|
|
typedef struct VisRebuildStats_s
|
|
{
|
|
QUAD VisNumBeasts;
|
|
QUAD VisNumOverflowRemoved;
|
|
QUAD VisNumFilesCleaned;
|
|
QUAD VisNumTrusteesProcessed;
|
|
} VisRebuildStats_s;
|
|
|
|
typedef struct VisRebParms_s
|
|
{
|
|
Volume_s *vol;
|
|
unicode_t name[zMAX_COMPONENT_NAME];
|
|
} VisRebParms_s;
|
|
|
|
/****************************************************************************
|
|
*
|
|
****************************************************************************/
|
|
void *ZAS_LookupOverflowBeast (
|
|
GeneralMsg_s *genMsg,
|
|
void *voidVol,
|
|
Zid_t zid,
|
|
NINT latchType,
|
|
NINT classID)
|
|
{
|
|
RootBeast_s *beast;
|
|
|
|
beast = BEASTHASH_LookupByZid(genMsg, voidVol, zid, latchType);
|
|
|
|
if (beast == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
if (!(COMN_IsDerivedFrom(beast, classID)))
|
|
{
|
|
zASSERT("Overflow beast is not the correct type" == NULL);
|
|
COMN_UnlatchAndRelease(&beast, latchType);
|
|
return NULL;
|
|
}
|
|
return beast;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
****************************************************************************/
|
|
|
|
#if NSS_DEBUG IS_ENABLED
|
|
/* Authorization useage information */
|
|
NINT AuthResets = 0;
|
|
NINT AuthPartialResets = 0;
|
|
NINT AuthERRequests = 0;
|
|
NINT AuthERHits = 0;
|
|
NINT AuthERImmediateHits = 0;
|
|
|
|
/****************************************************************************
|
|
*
|
|
****************************************************************************/
|
|
void DEBUG_Display_Visibility(
|
|
AuthBeast_s *authBeast)
|
|
|
|
{
|
|
NINT entry;
|
|
ZASAuthorizeInfo_s *authInfo;
|
|
ZasVisOverflowBeast_s *overflowBeast;
|
|
Zid_t overflowZid;
|
|
GeneralMsg_s genMsg;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
COMN_SETUP_GENERAL_MSG_NO_CONNECTION_RESOLVE(&genMsg);
|
|
DBG_DebugPrintf(GREEN, MSGNot("\nVisiblibilty entries for ZID 0x%Lx\n"), authBeast->AUTHzid);
|
|
authInfo = authBeast->AUTHauthInfo.zas;
|
|
|
|
/* display the entries in the main beast */
|
|
for (entry=0; entry < authInfo->p.numVisibilityTrusteesAssigned; entry++)
|
|
{
|
|
DBG_DebugPrintf(CYAN, MSGNot(" (%d) Trustee: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x Count: %d\n"),
|
|
entry,
|
|
authInfo->p.visibilityList[entry].trusteeID.timeLow,
|
|
authInfo->p.visibilityList[entry].trusteeID.timeMid,
|
|
authInfo->p.visibilityList[entry].trusteeID.timeHighAndVersion,
|
|
authInfo->p.visibilityList[entry].trusteeID.clockSeqHighAndReserved,
|
|
authInfo->p.visibilityList[entry].trusteeID.clockSeqLow,
|
|
authInfo->p.visibilityList[entry].trusteeID.node[0],
|
|
authInfo->p.visibilityList[entry].trusteeID.node[1],
|
|
authInfo->p.visibilityList[entry].trusteeID.node[2],
|
|
authInfo->p.visibilityList[entry].trusteeID.node[3],
|
|
authInfo->p.visibilityList[entry].trusteeID.node[4],
|
|
authInfo->p.visibilityList[entry].trusteeID.node[5],
|
|
authInfo->p.visibilityList[entry].count);
|
|
}
|
|
|
|
/* display the entries in the overflow beasts */
|
|
overflowZid = authInfo->p.visibilityOverflow;
|
|
while (overflowZid != zINVALID_ZID)
|
|
{
|
|
/* get the next overflow beast */
|
|
overflowBeast = ZAS_LookupOverflowBeast(&genMsg, authBeast->AUTHvolume,
|
|
overflowZid, SLATCHED, zFTYPE_ZAS_VIS_OVERFLOW);
|
|
if (overflowBeast == NULL)
|
|
{ /* error */
|
|
DBG_DebugPrintf(RED, MSGNot("Error opening an overflow beast: %d\n"), GetErrno(&genMsg));
|
|
return;
|
|
}
|
|
|
|
for (entry=0; entry < overflowBeast->p.numEntries; entry++)
|
|
{
|
|
DBG_DebugPrintf(LBLUE, MSGNot(" (%d) Trustee: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x Count: %d\n"),
|
|
entry,
|
|
overflowBeast->vis[entry].trusteeID.timeLow,
|
|
overflowBeast->vis[entry].trusteeID.timeMid,
|
|
overflowBeast->vis[entry].trusteeID.timeHighAndVersion,
|
|
overflowBeast->vis[entry].trusteeID.clockSeqHighAndReserved,
|
|
overflowBeast->vis[entry].trusteeID.clockSeqLow,
|
|
overflowBeast->vis[entry].trusteeID.node[0],
|
|
overflowBeast->vis[entry].trusteeID.node[1],
|
|
overflowBeast->vis[entry].trusteeID.node[2],
|
|
overflowBeast->vis[entry].trusteeID.node[3],
|
|
overflowBeast->vis[entry].trusteeID.node[4],
|
|
overflowBeast->vis[entry].trusteeID.node[5],
|
|
overflowBeast->vis[entry].count);
|
|
}
|
|
|
|
overflowZid = overflowBeast->p.nextOverflowZid;
|
|
zASSERT((overflowZid == zINVALID_ZID) ||
|
|
(overflowBeast->p.numEntries == MAX_VIS_OVERFLOW_ENTRIES));
|
|
COMN_UnlatchAndRelease(&overflowBeast, SLATCHED);
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
/***************************************************************************
|
|
* The authorization operations for the system
|
|
* (FixFixFix6 -- these should be loaded)
|
|
***************************************************************************/
|
|
struct AuthModelOps_s ZASAuthorizeModelOps =
|
|
{
|
|
VAUTH_ConstructAuthBeast,
|
|
VAUTH_DestructAuthBeast,
|
|
VAUTH_PackedSize,
|
|
VAUTH_PackAuthBeast,
|
|
VAUTH_NoPackAuthBeastCleanup,
|
|
VAUTH_UnpackAuthBeast,
|
|
VAUTH_AddAuthInfo,
|
|
VAUTH_RemoveAuthInfo,
|
|
VAUTH_DeleteAuthInfo,
|
|
VAUTH_IsAuthInfo,
|
|
VAUTH_MayIDoThis,
|
|
VAUTH_InitVolumeAuthInfo,
|
|
VAUTH_RemoveIDsFromAVolume,
|
|
VAUTH_AddObjectNames,
|
|
VAUTH_CheckUserIDs,
|
|
VAUTH_InvalidateAuthInfo,
|
|
};
|
|
|
|
/***************************************************************************
|
|
* This will be called at Authorization model init time
|
|
***************************************************************************/
|
|
STATUS ZAS_Startup(void)
|
|
{
|
|
GeneralMsg_s genMsg;
|
|
AuthModelBeast_s *authModel;
|
|
AuthSpaceBeast_s *authSpace;
|
|
ASSERT_MPKNSS_LOCK();
|
|
ENTER(TAUTH, ZAS_Startup);
|
|
COMN_STRUCT_INIT(genMsg);
|
|
COMN_SETUP_GENERAL_MSG_NOSA(&genMsg);
|
|
|
|
if ((authModel = COMN_RegisterAuthorizeModel(&genMsg, AUTH_MODEL_VERSION,
|
|
zFTYPE_ZAS_AUTH_MODEL, MSGNot("NetWare"),
|
|
&ZASAuthorizeModelOps)) == NULL)
|
|
{
|
|
RTN_STATUS(zFAILURE);
|
|
}
|
|
|
|
if ((authSpace = COMN_RegisterAuthorizeSpace(&genMsg, authModel,
|
|
zFTYPE_ZAS_AUTH_SPACE, MSGNot("NetWareToNetWare"),
|
|
(AuthSpaceOps_s *)&ZASAuthorizeSpaceOps)) == NULL)
|
|
{
|
|
RTN_STATUS(zFAILURE);
|
|
}
|
|
ZASindex = authSpace->spaceIndex;
|
|
|
|
if (ZAS_CacheInit(&genMsg) != zOK)
|
|
{
|
|
RTN_STATUS(zFAILURE);
|
|
}
|
|
|
|
if ((authSpace = COMN_RegisterAuthorizeSpace(&genMsg, authModel,
|
|
zFTYPE_UNIX_AUTH_SPACE, MSGNot("UnixToNetWare"),
|
|
(AuthSpaceOps_s *)&UnixToNetWareAuthorizeSpaceOps)) == NULL)
|
|
{
|
|
RTN_STATUS(zFAILURE);
|
|
}
|
|
UXASindex = authSpace->spaceIndex;
|
|
|
|
AuthorizeStarted = TRUE;
|
|
RTN_STATUS(zOK);
|
|
}
|
|
|
|
/***************************************************************************
|
|
* This will be called at Authorization shutdown time
|
|
***************************************************************************/
|
|
void ZAS_Shutdown(void)
|
|
{
|
|
ENTER(TAUTH, ZAS_Shutdown);
|
|
ASSERT_MPKNSS_LOCK();
|
|
ZAS_CacheUninit();
|
|
AuthorizeStarted = FALSE;
|
|
RTN_VOID();
|
|
}
|
|
|
|
/***************************************************************************
|
|
* This routine is called when an auth beast is allocated in memory
|
|
* (it may still be on disk)
|
|
***************************************************************************/
|
|
STATUS VAUTH_ConstructAuthBeast(
|
|
GeneralMsg_s *genMsg,
|
|
AuthBeast_s *authBeast)
|
|
{
|
|
ZASAuthorizeInfo_s *authInfo;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
ENTER(TAUTH, VAUTH_ConstructAuthBeast);
|
|
authInfo = (ZASAuthorizeInfo_s *)zalloc(sizeof(ZASAuthorizeInfo_s));
|
|
if (authInfo == NULL)
|
|
{
|
|
SetErrno(genMsg,zERR_NO_MEMORY);
|
|
RTN_STATUS(zFAILURE);
|
|
}
|
|
|
|
authBeast->AUTHauthInfo.zas = authInfo;
|
|
|
|
/* authInfo->p.inheritedRightsMask = zAUTHORIZE_SUPERVISOR; *//* always allow superviser to inherit */
|
|
authInfo->p.inheritedRightsMask = -1; /* allow all rights */
|
|
authInfo->p.cacheIndex = INVALID_EACL_CACHE_INDEX;
|
|
authInfo->p.version = CURRENT_AUTH_VERSION;
|
|
authInfo->flags = 0;
|
|
|
|
RTN_STATUS(zOK);
|
|
}
|
|
|
|
/***************************************************************************
|
|
* This routine is called when an auth beast is freed from memory
|
|
* (it may still be on disk)
|
|
***************************************************************************/
|
|
void VAUTH_DestructAuthBeast(
|
|
AuthBeast_s *authBeast)
|
|
{
|
|
ASSERT_MPKNSS_LOCK();
|
|
ENTER(TAUTH, VAUTH_DestructAuthBeast);
|
|
free(authBeast->AUTHauthInfo.zas);
|
|
RTN_VOID();
|
|
}
|
|
|
|
/***************************************************************************
|
|
* This routine is called when an auth beast is written to storage
|
|
***************************************************************************/
|
|
NINT VAUTH_PackedSize(
|
|
AuthBeast_s *authBeast)
|
|
{
|
|
ZASAuthorizeInfo_s *authInfo;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
ENTER(TAUTH, VAUTH_PackedSize);
|
|
authInfo = authBeast->AUTHauthInfo.zas;
|
|
if (!(authInfo->flags & ZAS_ALLOW_FORCED_WRITE))
|
|
S_LATCH(&authInfo->authLatch);
|
|
RTN_NINT(sizeof(ZASPersistentAuthInfo_s) -
|
|
(sizeof(authInfo->p.ACL) + sizeof(authInfo->p.visibilityList)) +
|
|
sizeof(ACLEntry_s) * authInfo->p.numTrusteesAssigned +
|
|
sizeof(VisEntry_s) * authInfo->p.numVisibilityTrusteesAssigned);
|
|
}
|
|
|
|
/***************************************************************************
|
|
* This routine is called when an auth beast is written to storage
|
|
***************************************************************************/
|
|
BYTE *VAUTH_PackAuthBeast(
|
|
AuthBeast_s *authBeast,
|
|
BYTE *storeBuffer)
|
|
{
|
|
ZASAuthorizeInfo_s *authInfo;
|
|
NINT len;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
ENTER(TAUTH, VAUTH_PackAuthBeast);
|
|
authInfo = authBeast->AUTHauthInfo.zas;
|
|
zASSERT((authInfo->flags & ZAS_ALLOW_FORCED_WRITE) ||
|
|
(authBeast->AUTHauthInfo.zas->authLatch.count != 0));
|
|
// now being latched in VAUTH_PackedSize
|
|
// if (!(authInfo->flags & ZAS_ALLOW_FORCED_WRITE))
|
|
// S_LATCH(&authInfo->authLatch);
|
|
len = sizeof(ZASPersistentAuthInfo_s) -
|
|
(sizeof(authInfo->p.ACL) + sizeof(authInfo->p.visibilityList));
|
|
memcpy(storeBuffer, &authInfo->p, len);
|
|
storeBuffer += len;
|
|
len = sizeof(ACLEntry_s) * authInfo->p.numTrusteesAssigned;
|
|
memcpy(storeBuffer, &authInfo->p.ACL, len);
|
|
storeBuffer += len;
|
|
len = sizeof(VisEntry_s) * authInfo->p.numVisibilityTrusteesAssigned;
|
|
memcpy(storeBuffer, &authInfo->p.visibilityList, len);
|
|
if (!(authInfo->flags & ZAS_ALLOW_FORCED_WRITE))
|
|
UNS_LATCH(&authInfo->authLatch);
|
|
RTN_PTR(storeBuffer + len);
|
|
}
|
|
|
|
/**************************************************************************
|
|
* This routine is called when we have done a "getPackedSize" but we can't
|
|
* do the pack do to an error. This will cleanup the latch that we
|
|
* aquired at "getPackedSize" time.
|
|
***************************************************************************/
|
|
void VAUTH_NoPackAuthBeastCleanup(
|
|
AuthBeast_s *authBeast)
|
|
{
|
|
ZASAuthorizeInfo_s *authInfo;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
ENTER(TAUTH, VAUTH_NoPackAuthBeastCleanup);
|
|
|
|
authInfo = authBeast->AUTHauthInfo.zas;
|
|
if (!(authInfo->flags & ZAS_ALLOW_FORCED_WRITE))
|
|
UNS_LATCH(&authInfo->authLatch);
|
|
|
|
RTN_VOID();
|
|
}
|
|
|
|
/***************************************************************************
|
|
* This routine is called when an auth beast is read from storage
|
|
***************************************************************************/
|
|
BYTE *VAUTH_UnpackAuthBeast(
|
|
GeneralMsg_s *genMsg,
|
|
AuthBeast_s *authBeast,
|
|
BYTE *storeBuffer)
|
|
{
|
|
ZASAuthorizeInfo_s *authInfo;
|
|
V1_ZASPersistentAuthInfo_s *oldInfo;
|
|
V1_ACLEntry_s *oldACLEntry;
|
|
V1_VisEntry_s *oldVisEntry;
|
|
NINT len;
|
|
NINT count;
|
|
STATUS status;
|
|
NINT inner;
|
|
VisEntry_s temp;
|
|
NINT convertCount;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
ENTER(TAUTH, VAUTH_UnpackAuthBeast);
|
|
authInfo = authBeast->AUTHauthInfo.zas;
|
|
X_LATCH(&authInfo->authLatch);
|
|
|
|
/*
|
|
* Perform an on-the-fly upgrade upgrade of the auth beast. In the
|
|
* future we will check the version number in the persistent auth
|
|
* info. Since we are adding it in version two we cannot check it
|
|
* this time.
|
|
*/
|
|
#if (CURRENT_BEAST_VERSION != BEAST_VERSION_3)
|
|
#error "Check code here to ensure the new version is handled correctly."
|
|
#endif
|
|
if (authBeast->AUTHbeastVersion == BEAST_VERSION_1)
|
|
{
|
|
#if NSS_DEBUG IS_ENABLED
|
|
DBG_DebugPrintf(LMAGENTA,"On-the-fly: authorization\n");
|
|
#endif
|
|
#if (CURRENT_BEAST_VERSION != BEAST_VERSION_3)
|
|
#error "Check to see if the beastVersion code below is still correct."
|
|
#endif
|
|
oldInfo = (V1_ZASPersistentAuthInfo_s *)storeBuffer;
|
|
authInfo->p.version = CURRENT_AUTH_VERSION;
|
|
authInfo->p.extra1 = 0;
|
|
authInfo->p.extra2 = 0;
|
|
authInfo->p.cacheIndex = oldInfo->cacheIndex;
|
|
authInfo->p.restartCount = oldInfo->restartCount;
|
|
authInfo->p.signature = oldInfo->signature;
|
|
authInfo->p.inheritedRightsMask = oldInfo->inheritedRightsMask;
|
|
authInfo->p.trusteeOverflow = oldInfo->trusteeOverflow;
|
|
authInfo->p.visibilityOverflow = oldInfo->visibilityOverflow;
|
|
authInfo->p.numTrusteesAssigned = oldInfo->numTrusteesAssigned;
|
|
authInfo->p.numVisibilityTrusteesAssigned =
|
|
oldInfo->numVisibilityTrusteesAssigned;
|
|
storeBuffer += sizeof(V1_ZASPersistentAuthInfo_s);
|
|
|
|
if( (authInfo->p.numTrusteesAssigned > MAX_TRUSTEES_IN_BEAST) ||
|
|
(authInfo->p.numVisibilityTrusteesAssigned > MAX_VISIBILITY_TRUSTEES_IN_BEAST) )
|
|
{
|
|
storeBuffer = NULL;
|
|
SetErrno( genMsg, zERR_BEAST_CORRUPTED );
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* If there are visibility overflow beasts that will need to
|
|
* be fixed up then set the version to a previous value.
|
|
*/
|
|
if (authInfo->p.visibilityOverflow != zINVALID_ZID)
|
|
{
|
|
authInfo->p.version = CURRENT_AUTH_VERSION - 1;
|
|
}
|
|
|
|
/* Convert ACL entries */
|
|
if (authInfo->p.numTrusteesAssigned > 0)
|
|
{
|
|
oldACLEntry = (V1_ACLEntry_s *)storeBuffer;
|
|
convertCount = 0;
|
|
for (count = 0; count < authInfo->p.numTrusteesAssigned; count++)
|
|
{
|
|
#if zNETWARE
|
|
/*
|
|
* If there is an error converting then the entry is ignored.
|
|
*/
|
|
if (COMN_MapNDSIDToGUID(&status, oldACLEntry->trusteeID,
|
|
&authInfo->p.ACL[convertCount].trusteeID) == zOK)
|
|
{
|
|
authInfo->p.ACL[convertCount].rights = oldACLEntry->rights;
|
|
authInfo->p.ACL[convertCount].attributes =
|
|
oldACLEntry->attributes;
|
|
convertCount++;
|
|
}
|
|
#if NSS_DEBUG IS_ENABLED
|
|
else
|
|
{
|
|
DBG_DebugPrintf(LRED, "VAUTH_UnpackAuthBeast: Ignored an invalid ACL entry\n");
|
|
}
|
|
#endif
|
|
#endif
|
|
#if zLINUX
|
|
status = zFAILURE;
|
|
printk(KERN_ALERT "VAUTH_UnpackAuthBeast: Ignored an old-version ACL entry\n");
|
|
#endif
|
|
oldACLEntry++;
|
|
}
|
|
authInfo->p.numTrusteesAssigned = convertCount;
|
|
storeBuffer = (BYTE *)oldACLEntry ;
|
|
}
|
|
|
|
/* Convert Visibility entries */
|
|
if (authInfo->p.numVisibilityTrusteesAssigned > 0)
|
|
{
|
|
oldVisEntry = (V1_VisEntry_s *)storeBuffer;
|
|
convertCount = 0;
|
|
for (count = 0; count < authInfo->p.numVisibilityTrusteesAssigned;
|
|
count++)
|
|
{
|
|
#if zNETWARE
|
|
if (COMN_MapNDSIDToGUID(&status, oldVisEntry->trusteeID,
|
|
&authInfo->p.visibilityList[convertCount].trusteeID) == zOK)
|
|
{
|
|
authInfo->p.visibilityList[convertCount].count =
|
|
oldVisEntry->count;
|
|
#if NSS_DEBUG IS_ENABLED
|
|
DBG_DebugPrintf(LBLUE,
|
|
"VAUTH_UnpackAuthBeast: Valid visibility entry. ID=%x GUID=%x-%x\n",
|
|
oldVisEntry->trusteeID,
|
|
authInfo->p.visibilityList[convertCount].trusteeID.timeLow,
|
|
authInfo->p.visibilityList[convertCount].trusteeID.node[5]);
|
|
#endif
|
|
convertCount++;
|
|
}
|
|
#if NSS_DEBUG IS_ENABLED
|
|
else
|
|
{
|
|
DBG_DebugPrintf(LRED,
|
|
"VAUTH_UnpackAuthBeast: Ignored an invalid visibility entry. ID=%x\n",
|
|
oldVisEntry->trusteeID);
|
|
}
|
|
#endif
|
|
#endif
|
|
#if zLINUX
|
|
status = zFAILURE;
|
|
printk(KERN_ALERT "VAUTH_UnpackAuthBeast: Ignored an old-version visibility entry\n");
|
|
#endif
|
|
oldVisEntry++;
|
|
}
|
|
authInfo->p.numVisibilityTrusteesAssigned = convertCount;
|
|
storeBuffer = (BYTE *)oldVisEntry ;
|
|
|
|
/* Sort the entries */
|
|
for (count = 1; count < authInfo->p.numVisibilityTrusteesAssigned;
|
|
count++)
|
|
{
|
|
for (inner = 0;
|
|
inner < authInfo->p.numVisibilityTrusteesAssigned - count; inner++)
|
|
{
|
|
if (LB_GUIDCompare(&authInfo->p.visibilityList[inner].trusteeID,
|
|
&authInfo->p.visibilityList[inner + 1].trusteeID) > 0)
|
|
{
|
|
temp = authInfo->p.visibilityList[inner];
|
|
authInfo->p.visibilityList[inner] =
|
|
authInfo->p.visibilityList[inner + 1];
|
|
authInfo->p.visibilityList[inner + 1] = temp;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
len = sizeof(ZASPersistentAuthInfo_s) -
|
|
(sizeof(authInfo->p.ACL) + sizeof(authInfo->p.visibilityList));
|
|
memcpy(&authInfo->p, storeBuffer, len);
|
|
storeBuffer += len;
|
|
/* Bug#377670 - Need to place the data into authInfo->p before testing
|
|
that it has legal values. Before counts would be 0 always so we
|
|
did not catch corrupt beasts and then would corrupt lots of memory. */
|
|
if( (authInfo->p.numTrusteesAssigned > MAX_TRUSTEES_IN_BEAST) ||
|
|
(authInfo->p.numVisibilityTrusteesAssigned > MAX_VISIBILITY_TRUSTEES_IN_BEAST) )
|
|
{
|
|
storeBuffer = NULL;
|
|
SetErrno( genMsg, zERR_BEAST_CORRUPTED );
|
|
}
|
|
else
|
|
{
|
|
len = sizeof(ACLEntry_s) * authInfo->p.numTrusteesAssigned;
|
|
memcpy(&authInfo->p.ACL, storeBuffer, len);
|
|
storeBuffer += len;
|
|
len = sizeof(ACLEntry_s) * authInfo->p.numVisibilityTrusteesAssigned;
|
|
memcpy(&authInfo->p.visibilityList, storeBuffer, len);
|
|
storeBuffer += len;
|
|
}
|
|
|
|
/* The following lines are for the cluster file system read only vol */
|
|
if ((authBeast->AUTHvolume->VOLenabledAttributes & zATTR_READONLY) &&
|
|
(!(genMsg->flags & UPDATE_EXISTING_BEAST)))
|
|
{
|
|
authInfo->p.signature = 0;
|
|
authInfo->p.restartCount = 0;
|
|
authInfo->p.cacheIndex = INVALID_EACL_CACHE_INDEX;
|
|
}
|
|
}
|
|
UNX_LATCH(&authInfo->authLatch);
|
|
RTN_PTR(storeBuffer);
|
|
}
|
|
|
|
///****************************************************************************
|
|
// * findVisTrustee
|
|
// * Use a binary search to find a visibility trustee in an overflow beast.
|
|
// * Returns the index into the overflow beast. If the entry is not found
|
|
// * it returns the next higher value (the place to insert it);
|
|
// ****************************************************************************/
|
|
//NINT findVisTrustee(
|
|
// ZasVisOverflowBeast_s *overflowBeast;
|
|
// NINT trusteeID)
|
|
//{
|
|
// LONG midID;
|
|
// NINT start;
|
|
// NINT end;
|
|
// NINT mid;
|
|
//
|
|
// start = 0;
|
|
// end = overflowBeast->p.numEntries;
|
|
// do
|
|
// {
|
|
// mid = (start + end) / 2;
|
|
// midID = overflowBeast->vis[mid].trusteeID;
|
|
// if(trusteeID <= midID)
|
|
// {
|
|
// if (trusteeID == midID)
|
|
// return mid;
|
|
// end = mid;
|
|
// }
|
|
// else
|
|
// {
|
|
// start = mid + 1;
|
|
// }
|
|
// } while(start < end);
|
|
//
|
|
// return end; /* not found */
|
|
//}
|
|
|
|
|
|
#if (CURRENT_BEAST_VERSION != BEAST_VERSION_3)
|
|
#error "Check to see if the conversion code below is still needed. It was"
|
|
#error "used to convert beast version 1 to beast version 2."
|
|
#endif
|
|
/****************************************************************************
|
|
*
|
|
* This routine converts an ACL overflow beast from beast version 1 to
|
|
* beast version 2. It is done here instead of the unpack routine because
|
|
* one beast may create many. The unpack routine has already converted the
|
|
* IDs to GUIDs.
|
|
*
|
|
****************************************************************************/
|
|
STATUS ZAS_ConvertACLFromVersionOne (
|
|
GeneralMsg_s *genMsg,
|
|
ZasAclOverflowBeast_s *overflowBeast)
|
|
{
|
|
NINT numToMove;
|
|
ZasAclOverflowBeast_s *newOverflowBeast;
|
|
STATUS status;
|
|
Xaction_s *xaction;
|
|
BOOL needToDownLatch = FALSE;
|
|
|
|
if (overflowBeast->ACLObeastVersion > BEAST_VERSION_1)
|
|
{
|
|
zASSERT(overflowBeast->p.numEntries <= MAX_ACL_OVERFLOW_ENTRIES);
|
|
return zOK;
|
|
}
|
|
|
|
/*
|
|
* This is an older beast that could hold more entries. It
|
|
* will now be split up into multiple beasts if it is too big
|
|
* for the current version. This code can be removed when we
|
|
* are no longer converting from version 1 beasts.
|
|
*/
|
|
ASSERT_LATCH(&overflowBeast->ACLObeastLatch);
|
|
if (!IS_XLATCHED(&overflowBeast->ACLObeastLatch))
|
|
{
|
|
UP_LATCH(&overflowBeast->ACLObeastLatch);
|
|
if (overflowBeast->p.numEntries <= MAX_ACL_OVERFLOW_ENTRIES)
|
|
{ /* We now don't need to convert -- it was done by someone else while we were uplatching */
|
|
DOWN_LATCH(&overflowBeast->ACLObeastLatch);
|
|
return zOK;
|
|
}
|
|
needToDownLatch = TRUE;
|
|
}
|
|
|
|
#if NSS_DEBUG IS_ENABLED
|
|
DBG_DebugPrintf(LBLUE,"After on-the-fly: ACL overflow\n");
|
|
#endif
|
|
xaction = COMN_BeginXLocal(overflowBeast);
|
|
/* Create new beasts to handle the excess */
|
|
while (overflowBeast->p.numEntries > MAX_ACL_OVERFLOW_ENTRIES)
|
|
{
|
|
newOverflowBeast = (ZasAclOverflowBeast_s *)BST_create(genMsg,
|
|
zFTYPE_ZAS_ACL_OVERFLOW, overflowBeast->ACLOvolume, xaction);
|
|
if (overflowBeast == NULL)
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
numToMove = overflowBeast->p.numEntries % MAX_ACL_OVERFLOW_ENTRIES;
|
|
if (numToMove == 0)
|
|
{
|
|
numToMove = MAX_ACL_OVERFLOW_ENTRIES;
|
|
}
|
|
newOverflowBeast->numAlloced = numToMove;
|
|
/* free the memory alloced by the BST_create */
|
|
free(newOverflowBeast->acl);
|
|
newOverflowBeast->acl =
|
|
malloc(newOverflowBeast->numAlloced * sizeof (ACLEntry_s));
|
|
if (newOverflowBeast->acl == NULL)
|
|
{
|
|
SetErrno(genMsg, zERR_NO_MEMORY);
|
|
UNX_LATCH(&newOverflowBeast->ACLObeastLatch);
|
|
BST_free(newOverflowBeast);
|
|
goto cleanup;
|
|
}
|
|
overflowBeast->p.numEntries -= numToMove;
|
|
/* insert entries in the new beast */
|
|
memcpy(newOverflowBeast->acl,
|
|
&overflowBeast->acl[overflowBeast->p.numEntries],
|
|
sizeof(ACLEntry_s) * numToMove);
|
|
|
|
newOverflowBeast->ACLObstState |= BST_STATE_NEW;
|
|
newOverflowBeast->p.numEntries = numToMove;
|
|
|
|
/* fix up the links */
|
|
newOverflowBeast->p.nextOverflowZid =
|
|
overflowBeast->p.nextOverflowZid;
|
|
overflowBeast->p.nextOverflowZid = newOverflowBeast->ACLOzid;
|
|
|
|
/* write out the new beast */
|
|
COMN_MARK_BEAST_XLOCAL(&newOverflowBeast->ACLOroot, xaction);
|
|
status = COMN_ForceBeastWrite(genMsg, newOverflowBeast, xaction);
|
|
BEASTHASH_Insert(&newOverflowBeast->ACLOroot);
|
|
COMN_UnlatchAndRelease(&newOverflowBeast, XLATCHED);
|
|
if (status != zOK)
|
|
{
|
|
goto cleanup;
|
|
}
|
|
}
|
|
/* update the original beast */
|
|
COMN_MARK_BEAST_XLOCAL(&overflowBeast->ACLOroot, xaction);
|
|
status = COMN_ForceBeastWrite(genMsg, overflowBeast, xaction);
|
|
if (status != zOK)
|
|
{
|
|
goto cleanup;
|
|
}
|
|
COMN_EndXLocal(overflowBeast, &xaction);
|
|
if (needToDownLatch)
|
|
{
|
|
DOWN_LATCH(&overflowBeast->ACLObeastLatch);
|
|
}
|
|
return zOK;
|
|
|
|
cleanup:
|
|
COMN_EndXLocal(overflowBeast, &xaction);
|
|
if (needToDownLatch)
|
|
{
|
|
DOWN_LATCH(&overflowBeast->ACLObeastLatch);
|
|
}
|
|
return zFAILURE;
|
|
}
|
|
|
|
#if (CURRENT_BEAST_VERSION != BEAST_VERSION_3)
|
|
#error "Check to see if the conversion code below is still needed. It was"
|
|
#error "used to convert beast version 1 to beast version 2."
|
|
#endif
|
|
/****************************************************************************
|
|
*
|
|
* This routine converts all VIS overflow beasts on this auth beast
|
|
* from beast version 1 to beast version 2. It is done here instead of the
|
|
* unpack routine because one beast may create many. The unpack routine has
|
|
* already converted the IDs to GUIDs.
|
|
*
|
|
* The routine reads in all of visibility entries from the old beasts, sorts
|
|
* them and them writes them out again in the new format.
|
|
*
|
|
* If there is no transaction active then one is created.
|
|
*
|
|
****************************************************************************/
|
|
STATUS ZAS_ConvertVisFromVersionOne (
|
|
GeneralMsg_s *genMsg,
|
|
Xaction_s *passedInXaction,
|
|
AuthBeast_s *authBeast)
|
|
{
|
|
ZasVisOverflowBeast_s *overflowBeast = NULL;
|
|
ZasVisOverflowBeast_s *prevOverflowBeast = NULL;
|
|
ZASAuthorizeInfo_s *authInfo;
|
|
NINT numToMove;
|
|
NINT numMoved = 0;
|
|
NINT count;
|
|
NINT inner;
|
|
VisEntry_s *holdVis = NULL;
|
|
NINT totalEntries;
|
|
Xaction_s *xaction;
|
|
BOOL needToDownLatch = FALSE;
|
|
BOOL downAuthBeastLatch = FALSE;
|
|
Zid_t overflowZid;
|
|
VisEntry_s temp;
|
|
STATUS status;
|
|
BOOL clearForceFlag = FALSE;
|
|
|
|
|
|
authInfo = authBeast->AUTHauthInfo.zas;
|
|
if (authInfo->p.version == CURRENT_AUTH_VERSION)
|
|
{
|
|
return zOK;
|
|
}
|
|
if (!(IS_LATCHED(&authBeast->AUTHbeastLatch)))
|
|
{
|
|
/*Cannot convert visibility if we don't have a latch */
|
|
/* Do not know if we can get a latch without deadlocking if we
|
|
* come in here without a latch
|
|
*/
|
|
return zFAILURE;
|
|
}
|
|
ASSERT_LATCH(&authBeast->AUTHbeastLatch);
|
|
ASSERT_LATCH(&authInfo->authLatch);
|
|
|
|
#if NSS_DEBUG IS_ENABLED
|
|
DBG_DebugPrintf(LBLUE,"After on-the-fly: visibility overflow\n");
|
|
#endif
|
|
|
|
if (IS_XLATCHED(&authBeast->AUTHbeastLatch))
|
|
{
|
|
if (!IS_XLATCHED(&authInfo->authLatch))
|
|
{
|
|
UP_LATCH(&authInfo->authLatch);
|
|
needToDownLatch = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (IS_XLATCHED(&authInfo->authLatch))
|
|
{
|
|
UNX_LATCH(&authInfo->authLatch);
|
|
}
|
|
else
|
|
{
|
|
UNS_LATCH(&authInfo->authLatch);
|
|
needToDownLatch = TRUE;
|
|
}
|
|
UP_LATCH(&authBeast->AUTHbeastLatch);
|
|
downAuthBeastLatch = TRUE;
|
|
X_LATCH(&authInfo->authLatch);
|
|
}
|
|
|
|
if (authInfo->p.version == CURRENT_AUTH_VERSION)
|
|
{
|
|
/* We now don't need to convert -- it was done by someone else
|
|
* while we were uplatching */
|
|
status = zOK;
|
|
goto fixupLatchesAndReturnStatus;
|
|
}
|
|
|
|
ASSERT_XLATCH(&authBeast->AUTHbeastLatch);
|
|
ASSERT_XLATCH(&authInfo->authLatch);
|
|
|
|
if (!(authInfo->flags & ZAS_ALLOW_FORCED_WRITE))
|
|
{
|
|
authInfo->flags |= ZAS_ALLOW_FORCED_WRITE;
|
|
clearForceFlag = TRUE;
|
|
}
|
|
|
|
/****************************************
|
|
* Count the entries
|
|
****************************************/
|
|
|
|
totalEntries = authInfo->p.numVisibilityTrusteesAssigned;
|
|
overflowZid = authInfo->p.visibilityOverflow;
|
|
while (overflowZid != zINVALID_ZID)
|
|
{
|
|
/* get the next overflow beast */
|
|
overflowBeast = ZAS_LookupOverflowBeast(genMsg, authBeast->AUTHvolume,
|
|
overflowZid, SLATCHED, zFTYPE_ZAS_VIS_OVERFLOW);
|
|
if (overflowBeast == NULL)
|
|
{ /* error */
|
|
goto cleanup;
|
|
}
|
|
|
|
totalEntries += overflowBeast->p.numEntries;
|
|
|
|
overflowZid = overflowBeast->p.nextOverflowZid;
|
|
COMN_UnlatchAndRelease(&overflowBeast, SLATCHED);
|
|
}
|
|
|
|
/* Get the needed memory block */
|
|
if (totalEntries != 0)
|
|
{
|
|
holdVis = malloc(totalEntries * sizeof (VisEntry_s));
|
|
if (holdVis == NULL)
|
|
{
|
|
SetErrno(genMsg, zERR_NO_MEMORY);
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
/****************************************
|
|
* Read all of the entries into memory
|
|
****************************************/
|
|
|
|
/* read the entries from the main beast */
|
|
for (numToMove = 0; numToMove < authInfo->p.numVisibilityTrusteesAssigned;
|
|
numToMove++)
|
|
{
|
|
if (LB_GUIDCompare(&authInfo->p.visibilityList[numToMove].trusteeID,
|
|
&zINVALID_USERID) != 0)
|
|
{
|
|
holdVis[numMoved++] = authInfo->p.visibilityList[numToMove];
|
|
}
|
|
#if NSS_DEBUG IS_ENABLED
|
|
else
|
|
{
|
|
DBG_DebugPrintf(LRED, "ZAS_ConvertVisFromVersionOne: Ignored an invalid visibility entry\n");
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* read the entries from the overflow beasts */
|
|
overflowZid = authInfo->p.visibilityOverflow;
|
|
while (overflowZid != zINVALID_ZID)
|
|
{
|
|
/* get the next overflow beast */
|
|
overflowBeast = ZAS_LookupOverflowBeast(genMsg, authBeast->AUTHvolume,
|
|
overflowZid, SLATCHED, zFTYPE_ZAS_VIS_OVERFLOW);
|
|
if (overflowBeast == NULL)
|
|
{ /* error */
|
|
goto cleanupFree;
|
|
}
|
|
|
|
for (numToMove = 0; numToMove < overflowBeast->p.numEntries;
|
|
numToMove++)
|
|
{
|
|
if (LB_GUIDCompare(&overflowBeast->vis[numToMove].trusteeID,
|
|
&zINVALID_USERID) != 0)
|
|
{
|
|
holdVis[numMoved++] = overflowBeast->vis[numToMove];
|
|
}
|
|
#if NSS_DEBUG IS_ENABLED
|
|
else
|
|
{
|
|
DBG_DebugPrintf(LRED, "ZAS_ConvertVisFromVersionOne: Ignored an invalid overflow visibility entry\n");
|
|
}
|
|
#endif
|
|
}
|
|
|
|
overflowZid = overflowBeast->p.nextOverflowZid;
|
|
COMN_UnlatchAndRelease(&overflowBeast, SLATCHED);
|
|
}
|
|
|
|
totalEntries = numMoved;
|
|
|
|
/****************************************
|
|
* Sort the entries
|
|
****************************************/
|
|
|
|
for (count = 1; count < totalEntries; count++)
|
|
{
|
|
for (inner = 0;
|
|
inner < totalEntries - count; inner++)
|
|
{
|
|
if (LB_GUIDCompare(&holdVis[inner].trusteeID,
|
|
&holdVis[inner + 1].trusteeID) > 0)
|
|
{
|
|
temp = holdVis[inner];
|
|
holdVis[inner] = holdVis[inner + 1];
|
|
holdVis[inner + 1] = temp;
|
|
}
|
|
}
|
|
}
|
|
|
|
//#if NSS_DEBUG IS_ENABLED
|
|
// DBG_DebugPrintf(YELLOW, "Convert visibility structure after sorting:\n");
|
|
// for (count=0; count < totalEntries; count++)
|
|
// {
|
|
// DBG_DebugPrintf(LBLUE, MSGNot(" (%d) Trustee: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x Count: %d\n"),
|
|
// count,
|
|
// holdVis[count].trusteeID.timeLow,
|
|
// holdVis[count].trusteeID.timeMid,
|
|
// holdVis[count].trusteeID.timeHighAndVersion,
|
|
// holdVis[count].trusteeID.clockSeqHighAndReserved,
|
|
// holdVis[count].trusteeID.clockSeqLow,
|
|
// holdVis[count].trusteeID.node[0],
|
|
// holdVis[count].trusteeID.node[1],
|
|
// holdVis[count].trusteeID.node[2],
|
|
// holdVis[count].trusteeID.node[3],
|
|
// holdVis[count].trusteeID.node[4],
|
|
// holdVis[count].trusteeID.node[5],
|
|
// holdVis[count].count);
|
|
// }
|
|
//#endif
|
|
/****************************************
|
|
* Write out the new overflow beasts
|
|
****************************************/
|
|
|
|
xaction = (passedInXaction == NULL) ? COMN_BeginXLocal(authBeast) :
|
|
passedInXaction;
|
|
|
|
numMoved = 0;
|
|
|
|
/* fill up the main beast */
|
|
authInfo->p.numVisibilityTrusteesAssigned =
|
|
totalEntries > MAX_VISIBILITY_TRUSTEES_IN_BEAST ?
|
|
MAX_VISIBILITY_TRUSTEES_IN_BEAST :
|
|
totalEntries;
|
|
|
|
for (numToMove = 0; numToMove < authInfo->p.numVisibilityTrusteesAssigned;
|
|
numToMove++)
|
|
{
|
|
authInfo->p.visibilityList[numToMove] = holdVis[numMoved++];
|
|
}
|
|
|
|
/* Remove the old beasts */
|
|
overflowZid = authInfo->p.visibilityOverflow;
|
|
while (overflowZid != zINVALID_ZID)
|
|
{
|
|
/* get the next overflow beast */
|
|
overflowBeast = ZAS_LookupOverflowBeast(genMsg, authBeast->AUTHvolume,
|
|
overflowZid, XLATCHED, zFTYPE_ZAS_VIS_OVERFLOW);
|
|
if (overflowBeast == NULL)
|
|
{ /* error */
|
|
goto cleanupXaction;
|
|
}
|
|
|
|
overflowZid = overflowBeast->p.nextOverflowZid;
|
|
if (BST_delete(genMsg, NULL, overflowBeast, NULL, NULL, xaction,
|
|
FALSE, TRUE) != zOK)
|
|
{
|
|
zASSERT("Failed to remove old beasts during conversion" == 0);
|
|
}
|
|
COMN_UnlatchAndRelease(&overflowBeast, XLATCHED);
|
|
}
|
|
authInfo->p.visibilityOverflow = zINVALID_ZID;
|
|
|
|
/* create the new beasts */
|
|
while (numMoved < totalEntries)
|
|
{
|
|
overflowBeast = (ZasVisOverflowBeast_s *)BST_create(genMsg,
|
|
zFTYPE_ZAS_VIS_OVERFLOW, authBeast->AUTHvolume, xaction);
|
|
if (overflowBeast == NULL)
|
|
{
|
|
goto cleanupXaction;
|
|
}
|
|
|
|
numToMove = ((totalEntries - numMoved) >= MAX_VIS_OVERFLOW_ENTRIES) ?
|
|
MAX_VIS_OVERFLOW_ENTRIES : totalEntries - numMoved;
|
|
|
|
overflowBeast->numAlloced = numToMove;
|
|
free(overflowBeast->vis); /* this was alloced by the constructor */
|
|
overflowBeast->vis =
|
|
malloc(overflowBeast->numAlloced * sizeof (VisEntry_s));
|
|
if (overflowBeast->vis == NULL)
|
|
{
|
|
SetErrno(genMsg, zERR_NO_MEMORY);
|
|
UNX_LATCH(&overflowBeast->VISObeastLatch);
|
|
BST_free(overflowBeast);
|
|
goto cleanupXaction;
|
|
}
|
|
/* insert entries in the new beast */
|
|
memcpy(overflowBeast->vis, &holdVis[numMoved],
|
|
sizeof(VisEntry_s) * numToMove);
|
|
|
|
numMoved += numToMove;
|
|
|
|
overflowBeast->VISObstState |= BST_STATE_NEW;
|
|
overflowBeast->p.numEntries = numToMove;
|
|
|
|
/* fix up the links */
|
|
overflowBeast->p.nextOverflowZid = zINVALID_ZID;
|
|
if (prevOverflowBeast == NULL)
|
|
{ /* link to the main beast */
|
|
authInfo->p.visibilityOverflow = overflowBeast->VISOzid;
|
|
}
|
|
else
|
|
{
|
|
prevOverflowBeast->p.nextOverflowZid = overflowBeast->VISOzid;
|
|
/* write out the previous beast */
|
|
|
|
BEASTHASH_Insert(&prevOverflowBeast->VISOroot);
|
|
COMN_MARK_BEAST_XLOCAL(&prevOverflowBeast->VISOroot, xaction);
|
|
COMN_ForceBeastWrite(genMsg, prevOverflowBeast, xaction);
|
|
zASSERT(prevOverflowBeast->VISOuseCount > 1);
|
|
COMN_UnlatchAndRelease(&prevOverflowBeast, XLATCHED);
|
|
}
|
|
|
|
prevOverflowBeast = overflowBeast;
|
|
}
|
|
|
|
/* write out the final beast if we need to */
|
|
if (prevOverflowBeast != NULL)
|
|
{
|
|
BEASTHASH_Insert(&prevOverflowBeast->VISOroot);
|
|
COMN_MARK_BEAST_XLOCAL(&prevOverflowBeast->VISOroot, xaction);
|
|
COMN_ForceBeastWrite(genMsg, prevOverflowBeast, xaction);
|
|
zASSERT(prevOverflowBeast->VISOuseCount > 1);
|
|
COMN_UnlatchAndRelease(&prevOverflowBeast, XLATCHED);
|
|
}
|
|
|
|
/* write out the main beast */
|
|
authInfo->p.version = CURRENT_AUTH_VERSION;
|
|
|
|
COMN_MARK_BEAST_XLOCAL(&authBeast->AUTHroot, xaction);
|
|
COMN_ForceBeastWrite(genMsg, authBeast, xaction);
|
|
|
|
/* If the transaction was started in this routine then end it */
|
|
if (passedInXaction == NULL)
|
|
{
|
|
COMN_EndXLocal(authBeast, &xaction);
|
|
}
|
|
|
|
if (holdVis != NULL)
|
|
{
|
|
free(holdVis);
|
|
}
|
|
status = zOK;
|
|
|
|
fixupLatchesAndReturnStatus:
|
|
if (clearForceFlag)
|
|
{
|
|
authInfo->flags &= ~ZAS_ALLOW_FORCED_WRITE;
|
|
}
|
|
if (downAuthBeastLatch)
|
|
{
|
|
UNX_LATCH(&authInfo->authLatch);
|
|
DOWN_LATCH(&authBeast->AUTHbeastLatch);
|
|
if (needToDownLatch)
|
|
{
|
|
S_LATCH(&authInfo->authLatch);
|
|
}
|
|
else
|
|
{
|
|
X_LATCH(&authInfo->authLatch);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (needToDownLatch)
|
|
{
|
|
DOWN_LATCH(&authInfo->authLatch);
|
|
}
|
|
}
|
|
return status;
|
|
|
|
|
|
cleanupXaction:
|
|
/* If the transaction was started in this routine then end it */
|
|
if (passedInXaction == NULL)
|
|
{
|
|
COMN_EndXLocal(authBeast, &xaction);
|
|
}
|
|
cleanupFree:
|
|
if (holdVis != NULL)
|
|
{
|
|
free(holdVis);
|
|
}
|
|
cleanup:
|
|
status = zFAILURE;
|
|
goto fixupLatchesAndReturnStatus;
|
|
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* This routine will find a trustee and return a pointer to the visibility
|
|
* info.
|
|
*
|
|
* output: returnBeast - The beast where the entry is found or where it
|
|
* should be inserted. Returned opened and latched. If it is
|
|
* null then there are no overflow beasts OR we got an error
|
|
* on lookup of an overflow beast!
|
|
*
|
|
* entryPtr - A pointer to the found entry. If the trustee is not
|
|
* found then then a null is returned.
|
|
*
|
|
* entry - The index into either the authInfo in the main beast or
|
|
* the visibility info in the overflow beast.
|
|
* If an entry is found then it points to the entry, or it points
|
|
* to the location where a new entry should be inserted. The
|
|
* insertion point is the place to insert and not a free 'slot'.
|
|
* IDs are kept in order so everything must be memmoved and etc.
|
|
*
|
|
* parentZid - the zid of the parent beast. If invalid then the
|
|
* parent was the main beast.
|
|
*
|
|
****************************************************************************/
|
|
STATUS ZAS_FindVisibilityTrustee(
|
|
GeneralMsg_s *genMsg,
|
|
AuthBeast_s *authBeast,
|
|
#if (CURRENT_BEAST_VERSION != BEAST_VERSION_3)
|
|
#error "Check to see if the xaction below is still needed."
|
|
#endif
|
|
Xaction_s *xaction,
|
|
UserID_t *trusteeID,
|
|
NINT latchType,
|
|
VisEntry_s **entryPtr,
|
|
NINT *entry,
|
|
ZasVisOverflowBeast_s **returnBeast,
|
|
Zid_t *parentZid)
|
|
{
|
|
ZASAuthorizeInfo_s *authInfo;
|
|
ZasVisOverflowBeast_s *overflowBeast;
|
|
ZasVisOverflowBeast_s *prevOverflowBeast = NULL;
|
|
Zid_t overflowZid;
|
|
UserID_t midID;
|
|
NINT start;
|
|
NINT end;
|
|
NINT mid;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
ENTER(TAUTH, ZAS_FindVisibilityTrustee);
|
|
authInfo = authBeast->AUTHauthInfo.zas;
|
|
ASSERT_LATCH(&authInfo->authLatch);
|
|
*returnBeast = NULL;
|
|
*parentZid = zINVALID_ZID;
|
|
*entryPtr = NULL;
|
|
|
|
#if (CURRENT_BEAST_VERSION != BEAST_VERSION_3)
|
|
#error "Check to see if the beastVersion code below is still needed."
|
|
#endif
|
|
/* BEGINNING OF BEAST VERSION ONE CONVERSION CODE */
|
|
if (ZAS_ConvertVisFromVersionOne(genMsg, xaction, authBeast) != zOK)
|
|
{
|
|
RTN_STATUS(zFAILURE);
|
|
}
|
|
/* END OF BEAST VERSION ONE CONVERSION CODE */
|
|
|
|
/* search the main beast for the visibility trustee */
|
|
for (*entry=0; *entry < authInfo->p.numVisibilityTrusteesAssigned;
|
|
(*entry)++)
|
|
{
|
|
if (LB_GUIDCompare(&authInfo->p.visibilityList[*entry].trusteeID,
|
|
trusteeID) > 0)
|
|
{
|
|
*entryPtr = NULL;
|
|
RTN_STATUS(zOK);
|
|
}
|
|
if (LB_GUIDCompare(&authInfo->p.visibilityList[*entry].trusteeID,
|
|
trusteeID) == 0)
|
|
{
|
|
*entryPtr = &authInfo->p.visibilityList[*entry];
|
|
RTN_STATUS(zOK);
|
|
}
|
|
}
|
|
|
|
overflowBeast = NULL;
|
|
|
|
/* search the overflow beasts for the visibility trustee */
|
|
overflowZid = authInfo->p.visibilityOverflow;
|
|
while (overflowZid != zINVALID_ZID)
|
|
{ /* find an overflow beast with an open entry */
|
|
|
|
/* get the next overflow beast */
|
|
prevOverflowBeast = overflowBeast;
|
|
overflowBeast = ZAS_LookupOverflowBeast(genMsg, authBeast->AUTHvolume,
|
|
overflowZid, latchType, zFTYPE_ZAS_VIS_OVERFLOW);
|
|
if (overflowBeast == NULL)
|
|
{ /*
|
|
* Error -- fix up the beast so it looks like it did not have
|
|
* another overflow (simple self-healing).
|
|
*/
|
|
zASSERT("Error looking up visibility overflow beast" == NULL);
|
|
*returnBeast = prevOverflowBeast;
|
|
if (prevOverflowBeast)
|
|
{
|
|
prevOverflowBeast->p.nextOverflowZid = zINVALID_ZID;
|
|
}
|
|
else
|
|
{
|
|
authInfo->p.visibilityOverflow = zINVALID_ZID;
|
|
}
|
|
*entryPtr = NULL;
|
|
RTN_STATUS(zOK);
|
|
}
|
|
if (prevOverflowBeast != NULL)
|
|
{
|
|
COMN_UnlatchAndRelease(&prevOverflowBeast, latchType);
|
|
}
|
|
|
|
*entry = end = overflowBeast->p.numEntries;
|
|
if ( end == 0 )
|
|
{ /* not found -- return the insertion point */
|
|
/* *entry = end; Already set */
|
|
*returnBeast = overflowBeast;
|
|
*entryPtr = NULL; /* not found */
|
|
RTN_STATUS(zOK);
|
|
}
|
|
if (LB_GUIDCompare(trusteeID, &overflowBeast->vis[end-1].trusteeID) <= 0)
|
|
{ /* it should fall in this record */
|
|
/* use a binary search to find the entry */
|
|
start = 0;
|
|
do
|
|
{
|
|
mid = (start + end) / 2;
|
|
midID = overflowBeast->vis[mid].trusteeID;
|
|
if(LB_GUIDCompare(trusteeID, &midID) <= 0)
|
|
{
|
|
if (LB_GUIDCompare(trusteeID, &midID) == 0)
|
|
{ /* found the trustee entry */
|
|
*returnBeast = overflowBeast;
|
|
*entry = mid;
|
|
*entryPtr = &overflowBeast->vis[mid];
|
|
RTN_STATUS(zOK);
|
|
}
|
|
end = mid;
|
|
}
|
|
else
|
|
{
|
|
start = mid + 1;
|
|
}
|
|
} while(start < end);
|
|
|
|
/* not found -- return the insertion point */
|
|
*entry = end;
|
|
*returnBeast = overflowBeast;
|
|
*entryPtr = NULL; /* not found */
|
|
RTN_STATUS(zOK);
|
|
}
|
|
|
|
*parentZid = overflowZid;
|
|
overflowZid = overflowBeast->p.nextOverflowZid;
|
|
zASSERT((overflowZid == zINVALID_ZID) ||
|
|
(overflowBeast->p.numEntries == MAX_VIS_OVERFLOW_ENTRIES));
|
|
}
|
|
*returnBeast = overflowBeast;
|
|
*entryPtr = NULL;
|
|
RTN_STATUS(zOK);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* This routines will get the visibility entries for a single auth Beast.
|
|
*
|
|
* Parameter:
|
|
* genMsg
|
|
* authBeast The beast we will search for visibility
|
|
* maxEntries The maximum number of entries that can be returned
|
|
* visEntries A buffer that will be filled in this routine
|
|
* numReturned The number of
|
|
****************************************************************************/
|
|
STATUS ZAS_GetVisibilityEntries(
|
|
GeneralMsg_s *genMsg,
|
|
AuthBeast_s *authBeast, /* The beast we will search for visibility */
|
|
NINT maxEntries, /* The maximum number of entries that can be returned */
|
|
VisEntry_s *visEntries, /* A buffer that will be filled in this routine */
|
|
NINT *numReturned) /* The number of entries being returned.
|
|
If there are more entries than space
|
|
in the buffer the return count will be
|
|
-1, and the buffer will be filled */
|
|
{
|
|
ZASAuthorizeInfo_s *authInfo;
|
|
ZasVisOverflowBeast_s *overflowBeast;
|
|
Zid_t overflowZid;
|
|
NINT count;
|
|
|
|
ENTER(TAUTH, ZAS_GetVisibilityEntries);
|
|
authInfo = authBeast->AUTHauthInfo.zas;
|
|
S_LATCH(&authInfo->authLatch);
|
|
|
|
|
|
/* search the main beast for the visibility trustee */
|
|
for (*numReturned = 0;
|
|
*numReturned < authInfo->p.numVisibilityTrusteesAssigned;
|
|
(*numReturned)++)
|
|
{
|
|
if (*numReturned >= maxEntries)
|
|
{
|
|
*numReturned = -1;
|
|
goto finished;
|
|
}
|
|
visEntries[*numReturned] = authInfo->p.visibilityList[*numReturned];
|
|
}
|
|
|
|
/* search the overflow beasts for the visibility trustee */
|
|
overflowZid = authInfo->p.visibilityOverflow;
|
|
while (overflowZid != zINVALID_ZID)
|
|
{
|
|
/* get the next overflow beast */
|
|
overflowBeast = ZAS_LookupOverflowBeast(genMsg, authBeast->AUTHvolume,
|
|
overflowZid, SLATCHED, zFTYPE_ZAS_VIS_OVERFLOW);
|
|
if (overflowBeast == NULL)
|
|
{ /* error */
|
|
UNS_LATCH(&authInfo->authLatch);
|
|
RTN_STATUS(zFAILURE);
|
|
}
|
|
|
|
for (count = 0; count < overflowBeast->p.numEntries; count++)
|
|
{
|
|
if (*numReturned >= maxEntries)
|
|
{
|
|
COMN_UnlatchAndRelease(&overflowBeast, SLATCHED);
|
|
*numReturned = -1;
|
|
goto finished;
|
|
}
|
|
visEntries[(*numReturned)++] = overflowBeast->vis[count];
|
|
}
|
|
|
|
overflowZid = overflowBeast->p.nextOverflowZid;
|
|
COMN_UnlatchAndRelease(&overflowBeast, SLATCHED);
|
|
}
|
|
finished:
|
|
UNS_LATCH(&authInfo->authLatch);
|
|
RTN_STATUS(zOK);
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* This routine will add visibility rights up the tree for an object.
|
|
*
|
|
****************************************************************************/
|
|
AuthBeast_s *ZAS_InternalMakeItVisible(
|
|
GeneralMsg_s *genMsg,
|
|
AuthBeast_s *authBeast,
|
|
Volume_s *volume,
|
|
UserID_t *trusteeIDList,
|
|
NINT *trusteeCount,
|
|
FixVisibPLog_s *pLogLocPtrList)
|
|
{
|
|
Zid_t overflowZid = zINVALID_ZID;
|
|
Zid_t dummyZid;
|
|
ZASAuthorizeInfo_s *authInfo;
|
|
Zid_t parentZID = authBeast->AUTHzid;
|
|
AuthBeast_s *pBeast;
|
|
VisEntry_s *visEntry;
|
|
VisEntry_s holdEntry;
|
|
VisEntry_s tempEntry;
|
|
ZasVisOverflowBeast_s *overflowBeast;
|
|
ZasVisOverflowBeast_s *parentBeast;
|
|
NINT entryIndex;
|
|
BOOL writeMainBeast = FALSE;
|
|
Xaction_s *xaction;
|
|
PurgeLogMsg_s purgeLogMsg;
|
|
UserID_t *trusteeID = trusteeIDList;
|
|
FixVisibPLog_s *pLogLocPtr = pLogLocPtrList;
|
|
NINT i;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
|
|
authInfo = authBeast->AUTHauthInfo.zas;
|
|
|
|
X_LATCH(&authInfo->authLatch);
|
|
authInfo->flags |= ZAS_ALLOW_FORCED_WRITE;
|
|
|
|
//#if NSS_DEBUG IS_ENABLED
|
|
//DBG_DebugPrintf(GREEN, MSGNot("\nEntering Insert Visibility -- Trustee: %x"), *trusteeID);
|
|
//DEBUG_Display_Visibility(authBeast);
|
|
//#endif
|
|
|
|
/** NOTE: It is ok to do a forcebeastwrite on the overflow beast, and
|
|
** unlatch the beast before the transaction ends, because
|
|
** we have a latch on the auth beast until after the xaction
|
|
** ends, and no one can get the overflow beast without first
|
|
** getting a latch on the auth beast.
|
|
**/
|
|
|
|
for (i = 0; i < *trusteeCount; )
|
|
{
|
|
xaction = COMN_BeginXLocal(authBeast);
|
|
|
|
zASSERT(pLogLocPtr != NULL);
|
|
|
|
SETUP_FIX_VISIBILITY_PURGE_LOG(&purgeLogMsg, pLogLocPtr,
|
|
VIS_ACTION_ADD, parentZID, trusteeID);
|
|
if (authBeast->AUTHcomnVolOps.VOL_removePurgeLogEntry(
|
|
genMsg, authBeast->AUTHvolume,
|
|
PLOG_FIX_VISIBILITY, &purgeLogMsg, xaction) != zOK)
|
|
{
|
|
goto errorTryNextTrustee;
|
|
}
|
|
|
|
holdEntry.trusteeID = zINVALID_USERID;
|
|
if (ZAS_FindVisibilityTrustee(genMsg, authBeast, xaction, trusteeID,
|
|
XLATCHED, &visEntry, &entryIndex,
|
|
&overflowBeast, &dummyZid) != zOK)
|
|
{
|
|
/* error */
|
|
goto errorTryNextTrustee;
|
|
}
|
|
if (visEntry != NULL)
|
|
{ /* if it is found */
|
|
visEntry->count++;
|
|
if (overflowBeast == NULL)
|
|
{ /* in the main beast */
|
|
COMN_MARK_BEAST_XLOCAL(&authBeast->AUTHroot, xaction);
|
|
COMN_ForceBeastWrite(genMsg, authBeast, xaction);
|
|
}
|
|
else
|
|
{ /* in an overflow beast */
|
|
COMN_MARK_BEAST_XLOCAL(&overflowBeast->VISOroot, xaction);
|
|
COMN_ForceBeastWrite(genMsg, overflowBeast, xaction);
|
|
COMN_UnlatchAndRelease(&overflowBeast, XLATCHED);
|
|
}
|
|
|
|
//#if NSS_DEBUG IS_ENABLED
|
|
//DBG_DebugPrintf(GREEN, MSGNot("\n(1)Exiting Insert Visibility -- Trustee: %x"), *trusteeID);
|
|
//DEBUG_Display_Visibility(authBeast);
|
|
//#endif
|
|
goto visibilityDoneForThisTrustee;
|
|
}
|
|
else
|
|
{ /* add a new entry */
|
|
if (overflowBeast == NULL)
|
|
{ /* the new entry should go in the main beast */
|
|
zASSERT(authInfo->p.numVisibilityTrusteesAssigned <=
|
|
MAX_VISIBILITY_TRUSTEES_IN_BEAST);
|
|
zASSERT(entryIndex <= authInfo->p.numVisibilityTrusteesAssigned);
|
|
if (authInfo->p.numVisibilityTrusteesAssigned ==
|
|
MAX_VISIBILITY_TRUSTEES_IN_BEAST)
|
|
{ /* the main beast is full */
|
|
overflowZid = authInfo->p.visibilityOverflow;
|
|
if (entryIndex == MAX_VISIBILITY_TRUSTEES_IN_BEAST)
|
|
{ /* the new entry should go in the overflow */
|
|
holdEntry.trusteeID = *trusteeID;
|
|
holdEntry.count = 1;
|
|
}
|
|
else
|
|
{ /* the new entry goes in the main beast */
|
|
/* save the last entry to move it to the next beast */
|
|
holdEntry = authInfo->p.visibilityList[
|
|
MAX_VISIBILITY_TRUSTEES_IN_BEAST - 1];
|
|
memmove(&authInfo->p.visibilityList[entryIndex + 1],
|
|
&authInfo->p.visibilityList[entryIndex],
|
|
((MAX_VISIBILITY_TRUSTEES_IN_BEAST - 1) -
|
|
entryIndex) * sizeof(VisEntry_s));
|
|
authInfo->p.visibilityList[entryIndex].trusteeID =
|
|
*trusteeID;
|
|
authInfo->p.visibilityList[entryIndex].count = 1;
|
|
writeMainBeast = TRUE;
|
|
}
|
|
/* insert holdEntry at the front of the overflow beast */
|
|
entryIndex = 0;
|
|
/* open the overflow beast if needed */
|
|
if (overflowZid != zINVALID_ZID)
|
|
{
|
|
overflowBeast = ZAS_LookupOverflowBeast(genMsg,
|
|
authBeast->AUTHvolume, overflowZid,
|
|
XLATCHED, zFTYPE_ZAS_VIS_OVERFLOW);
|
|
if (overflowBeast == NULL)
|
|
{ /* error */
|
|
goto errorTryNextTrustee;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
zASSERT(overflowZid == zINVALID_ZID);
|
|
memmove(&authInfo->p.visibilityList[entryIndex+1],
|
|
&authInfo->p.visibilityList[entryIndex],
|
|
(authInfo->p.numVisibilityTrusteesAssigned - entryIndex)
|
|
* sizeof(VisEntry_s));
|
|
authInfo->p.numVisibilityTrusteesAssigned++;
|
|
authInfo->p.visibilityList[entryIndex].trusteeID =
|
|
*trusteeID;
|
|
authInfo->p.visibilityList[entryIndex].count = 1;
|
|
writeMainBeast = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{ /* adding an entry to the overflow beast */
|
|
overflowZid = overflowBeast->VISOzid;
|
|
holdEntry.trusteeID = *trusteeID;
|
|
holdEntry.count = 1;
|
|
}
|
|
|
|
/*
|
|
* Insert into an overflow beast.
|
|
*
|
|
* If an insert to a full overflow beast has occured then shift
|
|
* all entries in beasts that follow up one slot.
|
|
*/
|
|
|
|
while (overflowZid != zINVALID_ZID)
|
|
{ /* while there are still overflow beasts */
|
|
zASSERT(overflowBeast->p.numEntries <= MAX_VIS_OVERFLOW_ENTRIES);
|
|
zASSERT(entryIndex <= overflowBeast->p.numEntries);
|
|
overflowZid = overflowBeast->p.nextOverflowZid;
|
|
if (overflowBeast->p.numEntries == MAX_VIS_OVERFLOW_ENTRIES)
|
|
{ /* if the beast is full */
|
|
if (entryIndex < MAX_VIS_OVERFLOW_ENTRIES)
|
|
{ /* entry goes in this beast */
|
|
tempEntry = overflowBeast->vis[MAX_VIS_OVERFLOW_ENTRIES
|
|
- 1];
|
|
memmove(&overflowBeast->vis[entryIndex + 1],
|
|
&overflowBeast->vis[entryIndex],
|
|
((MAX_VIS_OVERFLOW_ENTRIES - 1) - entryIndex) *
|
|
sizeof(VisEntry_s));
|
|
overflowBeast->vis[entryIndex].trusteeID =
|
|
holdEntry.trusteeID;
|
|
overflowBeast->vis[entryIndex].count = holdEntry.count;
|
|
holdEntry = tempEntry;
|
|
}
|
|
else
|
|
{ /* entry will go in a new overflow beast */
|
|
zASSERT(overflowZid == zINVALID_ZID);
|
|
}
|
|
}
|
|
else
|
|
{ /* there is still room in the beast */
|
|
VisEntry_s *vis;
|
|
zASSERT(overflowZid == zINVALID_ZID);
|
|
if (overflowBeast->p.numEntries >=
|
|
overflowBeast->numAlloced)
|
|
{ /* we need to make the memory structure bigger */
|
|
overflowBeast->numAlloced += OVERFLOW_ALLOC_UNIT;
|
|
vis = (VisEntry_s *)realloc(overflowBeast->vis,
|
|
overflowBeast->numAlloced * sizeof (VisEntry_s));
|
|
if (vis == NULL)
|
|
{
|
|
overflowBeast->numAlloced -= OVERFLOW_ALLOC_UNIT;
|
|
SetErrno(genMsg, zERR_NO_MEMORY);
|
|
goto errorTryNextTrustee;
|
|
}
|
|
overflowBeast->vis = vis;
|
|
}
|
|
memmove(&overflowBeast->vis[entryIndex+1],
|
|
&overflowBeast->vis[entryIndex],
|
|
(overflowBeast->p.numEntries -entryIndex) *
|
|
sizeof(VisEntry_s));
|
|
overflowBeast->p.numEntries++;
|
|
overflowBeast->vis[entryIndex].trusteeID =
|
|
holdEntry.trusteeID;
|
|
overflowBeast->vis[entryIndex].count = holdEntry.count;
|
|
holdEntry.trusteeID = zINVALID_USERID;
|
|
}
|
|
|
|
/* always insert at the front after the first insert */
|
|
entryIndex = 0;
|
|
|
|
if (overflowZid != zINVALID_ZID)
|
|
{
|
|
COMN_MARK_BEAST_XLOCAL(&overflowBeast->VISOroot, xaction);
|
|
COMN_ForceBeastWrite(genMsg, overflowBeast, xaction);
|
|
COMN_UnlatchAndRelease(&overflowBeast, XLATCHED);
|
|
|
|
overflowBeast = ZAS_LookupOverflowBeast(genMsg,
|
|
authBeast->AUTHvolume, overflowZid, XLATCHED, zFTYPE_ZAS_VIS_OVERFLOW);
|
|
if (overflowBeast == NULL)
|
|
{ /* error */
|
|
goto errorTryNextTrustee;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Create a new beast if needed */
|
|
if (LB_GUIDCompare(&holdEntry.trusteeID, &zINVALID_USERID) != 0)
|
|
{
|
|
parentBeast = overflowBeast;
|
|
overflowBeast = (ZasVisOverflowBeast_s *)BST_create(genMsg,
|
|
zFTYPE_ZAS_VIS_OVERFLOW, authBeast->AUTHvolume, xaction);
|
|
if (overflowBeast == NULL)
|
|
{
|
|
if (parentBeast != NULL)
|
|
{
|
|
COMN_UnlatchAndRelease(&parentBeast, XLATCHED);
|
|
}
|
|
goto errorTryNextTrustee;
|
|
}
|
|
|
|
/* link the new beast to the ones already there */
|
|
if (parentBeast == NULL)
|
|
{ /* link to main beast */
|
|
authInfo->p.visibilityOverflow = overflowBeast->VISOzid;
|
|
writeMainBeast = TRUE;
|
|
}
|
|
else
|
|
{ /* link to another overflow beast */
|
|
parentBeast->p.nextOverflowZid = overflowBeast->VISOzid;
|
|
COMN_MARK_BEAST_XLOCAL(&parentBeast->VISOroot, xaction);
|
|
COMN_ForceBeastWrite(genMsg, parentBeast, xaction);
|
|
COMN_UnlatchAndRelease(&parentBeast, XLATCHED);
|
|
}
|
|
BEASTHASH_Insert(&overflowBeast->VISOroot);
|
|
overflowBeast->VISObstState |= BST_STATE_NEW;
|
|
overflowBeast->p.numEntries = 1;
|
|
overflowBeast->vis[0] = holdEntry;
|
|
}
|
|
if (overflowBeast != NULL)
|
|
{
|
|
COMN_MARK_BEAST_XLOCAL(&overflowBeast->VISOroot, xaction);
|
|
COMN_ForceBeastWrite(genMsg, overflowBeast, xaction);
|
|
COMN_UnlatchAndRelease(&overflowBeast, XLATCHED);
|
|
}
|
|
}
|
|
if (writeMainBeast)
|
|
{ /* if the main beast is dirty */
|
|
COMN_MARK_BEAST_XLOCAL(&authBeast->AUTHroot, xaction);
|
|
COMN_ForceBeastWrite(genMsg, authBeast, xaction);
|
|
writeMainBeast = FALSE;
|
|
}
|
|
|
|
//#if NSS_DEBUG IS_ENABLED
|
|
//DBG_DebugPrintf(GREEN, MSGNot("\n(2)Exiting Insert Visibility -- Trustee: %x"), *trusteeID);
|
|
//DEBUG_Display_Visibility(authBeast);
|
|
//#endif
|
|
|
|
if (authBeast->AUTHzid != zROOTDIR_ZID)
|
|
{
|
|
SETUP_FIX_VISIBILITY_PURGE_LOG(&purgeLogMsg, pLogLocPtr,
|
|
VIS_ACTION_ADD, authBeast->AUTHfirstParentZid, trusteeID);
|
|
if (authBeast->AUTHcomnVolOps.VOL_addPurgeLogEntry(
|
|
genMsg, authBeast->AUTHvolume,
|
|
PLOG_FIX_VISIBILITY, &purgeLogMsg, xaction) != zOK)
|
|
{
|
|
goto errorTryNextTrustee;
|
|
}
|
|
}
|
|
trusteeID++;
|
|
pLogLocPtr++;
|
|
i++;
|
|
COMN_EndXLocal(authBeast, &xaction);
|
|
continue;
|
|
|
|
errorTryNextTrustee:
|
|
errPrintf(WHERE, Module, 713,
|
|
MSG("Error adding visibility for a trustee.\n", 1193));
|
|
visibilityDoneForThisTrustee:
|
|
(*trusteeCount)--;
|
|
*trusteeID = trusteeIDList[*trusteeCount];
|
|
*pLogLocPtr = pLogLocPtrList[*trusteeCount];
|
|
COMN_EndXLocal(authBeast, &xaction);
|
|
continue;
|
|
}
|
|
|
|
xaction = COMN_BeginXLocal(authBeast);
|
|
VOL_insertEFLEntry(genMsg, &authBeast->AUTHroot,
|
|
EFL_FILE_STATE_MODIFY_METADATA, NULL, xaction);
|
|
COMN_EndXLocal(authBeast, &xaction);
|
|
|
|
if ((authBeast->AUTHzid == zROOTDIR_ZID) || (*trusteeCount == 0))
|
|
{
|
|
goto doneFixingVisibility;
|
|
}
|
|
parentZID = authBeast->AUTHfirstParentZid;
|
|
|
|
/* We do not want a yield between the UNX_LATCH of authBeast and
|
|
* X_LATCH request of the parent Beast below. Hence we look
|
|
* up the parent beast first in unlatched mode and then later
|
|
* request a latch on it
|
|
*
|
|
* This routine's calling function has to guarantee that when we
|
|
* return from here, the first thing we do is request a latch
|
|
* on the returned pBeast, without any yields in between
|
|
*/
|
|
pBeast = (AuthBeast_s *)BEASTHASH_LookupByZid(genMsg, volume,
|
|
parentZID, NOTLATCHED);
|
|
if (pBeast == NULL)
|
|
{ /* error */
|
|
SetErrno(genMsg, zERR_UNABLE_TO_OPEN_BEAST);
|
|
goto errorCleanup;
|
|
}
|
|
|
|
authInfo->flags &= ~ZAS_ALLOW_FORCED_WRITE;
|
|
UNX_LATCH(&authInfo->authLatch);
|
|
UNX_LATCH(&authBeast->AUTHbeastLatch);
|
|
|
|
return pBeast;
|
|
|
|
|
|
errorCleanup:
|
|
errPrintf(WHERE, Module, 713,
|
|
MSG("Error adding visibility for trustees just added\n", 986));
|
|
|
|
doneFixingVisibility:
|
|
authInfo->flags &= ~ZAS_ALLOW_FORCED_WRITE;
|
|
UNX_LATCH(&authInfo->authLatch);
|
|
COMN_UnlatchAndRelease(&authBeast, XLATCHED);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* This routine will setup to remove visibility up the tree
|
|
*
|
|
***************************************************************************/
|
|
AuthBeast_s *ZAS_InternalRemoveVisibility(
|
|
GeneralMsg_s *genMsg,
|
|
AuthBeast_s *authBeast,
|
|
Volume_s *volume,
|
|
UserID_t *trusteeIDList,
|
|
NINT *trusteeCount,
|
|
FixVisibPLog_s *pLogLocPtrList)
|
|
{
|
|
Zid_t parentZID = authBeast->AUTHzid;
|
|
Zid_t overflowZid;
|
|
Zid_t overflowParentZid;
|
|
ZASAuthorizeInfo_s *authInfo;
|
|
VisEntry_s *VisEntry;
|
|
ZasVisOverflowBeast_s *overflowBeast;
|
|
ZasVisOverflowBeast_s *parentBeast;
|
|
NINT entryIndex;
|
|
BOOL writeMainBeast = FALSE;
|
|
Xaction_s *xaction;
|
|
PurgeLogMsg_s purgeLogMsg;
|
|
AuthBeast_s *pBeast;
|
|
UserID_t *trusteeID = trusteeIDList;
|
|
FixVisibPLog_s *pLogLocPtr = pLogLocPtrList;
|
|
NINT i;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
|
|
authInfo = authBeast->AUTHauthInfo.zas;
|
|
X_LATCH(&authInfo->authLatch);
|
|
authInfo->flags |= ZAS_ALLOW_FORCED_WRITE;
|
|
|
|
//#if NSS_DEBUG IS_ENABLED
|
|
//DBG_DebugPrintf(GREEN, MSGNot("\nEntering Remove Visibility -- Trustee: %x"), *trusteeID);
|
|
//DEBUG_Display_Visibility(authBeast);
|
|
//#endif
|
|
|
|
/** NOTE: It is ok to do a forcebeastwrite on the overflow beast, and
|
|
** unlatch the beast before the transaction ends, because
|
|
** we have a latch on the auth beast until after the xaction
|
|
** ends, and no one can get the overflow beast without first
|
|
** getting a latch on the auth beast.
|
|
**/
|
|
|
|
for (i = 0; i < *trusteeCount; )
|
|
{
|
|
xaction = COMN_BeginXLocal(authBeast);
|
|
|
|
SETUP_FIX_VISIBILITY_PURGE_LOG(&purgeLogMsg, pLogLocPtr,
|
|
VIS_ACTION_REMOVE, parentZID, trusteeID);
|
|
if (authBeast->AUTHcomnVolOps.VOL_removePurgeLogEntry(
|
|
genMsg, authBeast->AUTHvolume,
|
|
PLOG_FIX_VISIBILITY, &purgeLogMsg, xaction) != zOK)
|
|
{
|
|
goto errorTryNextTrustee;
|
|
}
|
|
|
|
if (ZAS_FindVisibilityTrustee(genMsg, authBeast, xaction, trusteeID,
|
|
XLATCHED, &VisEntry, &entryIndex, &overflowBeast,
|
|
&overflowParentZid) != zOK)
|
|
{
|
|
goto errorTryNextTrustee;
|
|
}
|
|
if (VisEntry == NULL)
|
|
{
|
|
/* if the entry is not found then get out. This should not happen */
|
|
if (overflowBeast != NULL)
|
|
{
|
|
COMN_UnlatchAndRelease(&overflowBeast, XLATCHED);
|
|
}
|
|
SetErrno(genMsg, zERR_TRUSTEE_NOT_FOUND);
|
|
zASSERT("Trustee not found when trying to remove visibility" == 0);
|
|
goto errorTryNextTrustee;
|
|
}
|
|
|
|
/*
|
|
* if it is found
|
|
*/
|
|
if(--VisEntry->count == 0)
|
|
{ /* if the count is zero then remove the entry */
|
|
if (overflowBeast == NULL)
|
|
{ /* remove from the main beast */
|
|
authInfo->p.numVisibilityTrusteesAssigned--;
|
|
memmove(&authInfo->p.visibilityList[entryIndex],
|
|
&authInfo->p.visibilityList[entryIndex + 1],
|
|
(authInfo->p.numVisibilityTrusteesAssigned - entryIndex)
|
|
* sizeof(VisEntry_s));
|
|
overflowZid = authInfo->p.visibilityOverflow;
|
|
writeMainBeast = TRUE;
|
|
}
|
|
else
|
|
{ /* remove from an overflow beast */
|
|
overflowBeast->p.numEntries--;
|
|
memmove(&overflowBeast->vis[entryIndex],
|
|
&overflowBeast->vis[entryIndex + 1],
|
|
(overflowBeast->p.numEntries - entryIndex) *
|
|
sizeof(VisEntry_s));
|
|
overflowZid = overflowBeast->p.nextOverflowZid;
|
|
}
|
|
|
|
/*
|
|
* handle shifting entries in the overflow beasts
|
|
*/
|
|
while (overflowZid != zINVALID_ZID)
|
|
{ /* while there are overflow beasts */
|
|
parentBeast = overflowBeast;
|
|
if (parentBeast == NULL)
|
|
{
|
|
overflowParentZid = zINVALID_ZID;
|
|
}
|
|
else
|
|
{
|
|
overflowParentZid = parentBeast->VISOzid;
|
|
}
|
|
|
|
overflowBeast = ZAS_LookupOverflowBeast(genMsg,
|
|
authBeast->AUTHvolume, overflowZid, XLATCHED, zFTYPE_ZAS_VIS_OVERFLOW);
|
|
if (overflowBeast == NULL)
|
|
{
|
|
if (parentBeast)
|
|
{
|
|
COMN_UnlatchAndRelease(&parentBeast, XLATCHED);
|
|
}
|
|
goto errorTryNextTrustee;
|
|
}
|
|
|
|
if (parentBeast == NULL)
|
|
{ /* moving into the main beast */
|
|
authInfo->p.visibilityList[
|
|
MAX_VISIBILITY_TRUSTEES_IN_BEAST - 1] =
|
|
overflowBeast->vis[0];
|
|
authInfo->p.numVisibilityTrusteesAssigned++;
|
|
zASSERT(MAX_VISIBILITY_TRUSTEES_IN_BEAST ==
|
|
authInfo->p.numVisibilityTrusteesAssigned);
|
|
}
|
|
else
|
|
{ /* moving into an overflow beast */
|
|
parentBeast->vis[MAX_VIS_OVERFLOW_ENTRIES - 1] =
|
|
overflowBeast->vis[0];
|
|
parentBeast->p.numEntries++;
|
|
zASSERT(MAX_VIS_OVERFLOW_ENTRIES==parentBeast->p.numEntries);
|
|
COMN_MARK_BEAST_XLOCAL(&parentBeast->VISOroot, xaction);
|
|
COMN_ForceBeastWrite(genMsg, parentBeast, xaction);
|
|
COMN_UnlatchAndRelease(&parentBeast, XLATCHED);
|
|
}
|
|
overflowBeast->p.numEntries--;
|
|
memmove(&overflowBeast->vis[0],
|
|
&overflowBeast->vis[1],
|
|
overflowBeast->p.numEntries * sizeof(VisEntry_s));
|
|
overflowZid = overflowBeast->p.nextOverflowZid;
|
|
}
|
|
|
|
if (overflowBeast != NULL)
|
|
{
|
|
/*
|
|
* Check to see if the overflow beast should be deleted.
|
|
*/
|
|
if (overflowBeast->p.numEntries == 0)
|
|
{ /* the overflow beast is empty */
|
|
zASSERT(overflowZid == zINVALID_ZID);
|
|
if (BST_delete(genMsg, NULL, overflowBeast, NULL, NULL,
|
|
xaction, FALSE, TRUE) != zOK)
|
|
{
|
|
zASSERT("Failed to delete trustee overflow beast"==NULL);
|
|
}
|
|
COMN_UnlatchAndRelease(&overflowBeast, XLATCHED);
|
|
if (overflowParentZid == zINVALID_ZID)
|
|
{ /* the parent is the main beast */
|
|
authInfo->p.visibilityOverflow = zINVALID_ZID;
|
|
writeMainBeast = TRUE;
|
|
}
|
|
else
|
|
{ /* the parent is another overflow beast */
|
|
parentBeast = ZAS_LookupOverflowBeast(genMsg,
|
|
authBeast->AUTHvolume, overflowParentZid,
|
|
XLATCHED, zFTYPE_ZAS_VIS_OVERFLOW);
|
|
if (parentBeast == NULL)
|
|
{
|
|
goto errorTryNextTrustee;
|
|
}
|
|
parentBeast->p.nextOverflowZid = zINVALID_ZID;
|
|
COMN_MARK_BEAST_XLOCAL(&parentBeast->VISOroot, xaction);
|
|
COMN_ForceBeastWrite(genMsg, parentBeast, xaction);
|
|
COMN_UnlatchAndRelease(&parentBeast, XLATCHED);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
COMN_MARK_BEAST_XLOCAL(&overflowBeast->VISOroot, xaction);
|
|
COMN_ForceBeastWrite(genMsg, overflowBeast, xaction);
|
|
COMN_UnlatchAndRelease(&overflowBeast, XLATCHED);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (overflowBeast == NULL)
|
|
{ /* in the main beast */
|
|
COMN_MARK_BEAST_XLOCAL(&authBeast->AUTHroot, xaction);
|
|
COMN_ForceBeastWrite(genMsg, authBeast, xaction);
|
|
}
|
|
else
|
|
{ /* in an overflow beast */
|
|
COMN_MARK_BEAST_XLOCAL(&overflowBeast->VISOroot, xaction);
|
|
COMN_ForceBeastWrite(genMsg, overflowBeast, xaction);
|
|
COMN_UnlatchAndRelease(&overflowBeast, XLATCHED);
|
|
}
|
|
|
|
//#if NSS_DEBUG IS_ENABLED
|
|
//DBG_DebugPrintf(GREEN, MSGNot("\n(1)Exiting Remove Visibility -- Trustee: %x"), *trusteeID);
|
|
//DEBUG_Display_Visibility(authBeast);
|
|
//#endif
|
|
|
|
goto visibilityDoneForThisTrustee;
|
|
}
|
|
if (writeMainBeast)
|
|
{ /* if the main beast is dirty */
|
|
COMN_MARK_BEAST_XLOCAL(&authBeast->AUTHroot, xaction);
|
|
COMN_ForceBeastWrite(genMsg, authBeast, xaction);
|
|
writeMainBeast = FALSE;
|
|
}
|
|
|
|
//#if NSS_DEBUG IS_ENABLED
|
|
//DBG_DebugPrintf(GREEN, MSGNot("\n(2)Exiting Remove Visibility -- Trustee: %x"), *trusteeID);
|
|
//DEBUG_Display_Visibility(authBeast);
|
|
//#endif
|
|
|
|
if (authBeast->AUTHzid != zROOTDIR_ZID)
|
|
{
|
|
SETUP_FIX_VISIBILITY_PURGE_LOG(&purgeLogMsg, pLogLocPtr,
|
|
VIS_ACTION_REMOVE, authBeast->AUTHfirstParentZid, trusteeID);
|
|
if (authBeast->AUTHcomnVolOps.VOL_addPurgeLogEntry(
|
|
genMsg, authBeast->AUTHvolume,
|
|
PLOG_FIX_VISIBILITY, &purgeLogMsg, xaction) != zOK)
|
|
{
|
|
goto errorTryNextTrustee;
|
|
}
|
|
}
|
|
trusteeID++;
|
|
pLogLocPtr++;
|
|
i++;
|
|
COMN_EndXLocal(authBeast, &xaction);
|
|
continue;
|
|
|
|
errorTryNextTrustee:
|
|
errPrintf(WHERE, Module, 713,
|
|
MSG("Error removing visibility for a trustee.\n", 1194));
|
|
visibilityDoneForThisTrustee:
|
|
(*trusteeCount)--;
|
|
*trusteeID = trusteeIDList[*trusteeCount];
|
|
*pLogLocPtr = pLogLocPtrList[*trusteeCount];
|
|
COMN_EndXLocal(authBeast, &xaction);
|
|
continue;
|
|
}
|
|
|
|
xaction = COMN_BeginXLocal(authBeast);
|
|
VOL_insertEFLEntry(genMsg, &authBeast->AUTHroot,
|
|
EFL_FILE_STATE_MODIFY_METADATA, NULL, xaction);
|
|
COMN_EndXLocal(authBeast, &xaction);
|
|
|
|
if ((authBeast->AUTHzid == zROOTDIR_ZID) || (*trusteeCount == 0))
|
|
{
|
|
goto doneFixingVisibility;
|
|
}
|
|
parentZID = authBeast->AUTHfirstParentZid;
|
|
|
|
/* We do not want a yield between the UNX_LATCH of authBeast and
|
|
* X_LATCH request of the parent Beast below. Hence we look
|
|
* up the parent beast first in unlatched mode and then later
|
|
* request a latch on it
|
|
*
|
|
* This routine's calling function has to guarantee that when we
|
|
* return from here, the first thing we do is request a latch
|
|
* on the returned pBeast, without any yields in between
|
|
*/
|
|
pBeast = (AuthBeast_s *)BEASTHASH_LookupByZid(genMsg, volume,
|
|
parentZID, NOTLATCHED);
|
|
if (pBeast == NULL)
|
|
{ /* error */
|
|
SetErrno(genMsg, zERR_UNABLE_TO_OPEN_BEAST);
|
|
goto errorCleanup;
|
|
}
|
|
|
|
authInfo->flags &= ~ZAS_ALLOW_FORCED_WRITE;
|
|
UNX_LATCH(&authInfo->authLatch);
|
|
UNX_LATCH(&authBeast->AUTHbeastLatch);
|
|
|
|
return pBeast;
|
|
|
|
|
|
errorCleanup:
|
|
errPrintf(WHERE, Module, 714,
|
|
MSG("Error removing visibility for trustees just removed\n", 987));
|
|
|
|
doneFixingVisibility:
|
|
authInfo->flags &= ~ZAS_ALLOW_FORCED_WRITE;
|
|
UNX_LATCH(&authInfo->authLatch);
|
|
COMN_UnlatchAndRelease(&authBeast, XLATCHED);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* These routines will switch from fsm to scheduling a work (after we get a
|
|
* latch on the parent beast we are fixing visibility on).
|
|
*
|
|
***************************************************************************/
|
|
void ZAS_FixVisibilityThread(FsmLite_s *fsm);
|
|
|
|
void ZAS_FixVisibilityGotParentLatch(FsmLite_s *fsm)
|
|
{
|
|
TotalVisibilityProcesses++;
|
|
WORK_Schedule(fsm, ZAS_FixVisibilityThread, 0);
|
|
return;
|
|
}
|
|
|
|
void ZAS_FixVisibilityThread(FsmLite_s *fsm)
|
|
{
|
|
GeneralMsg_s genMsg;
|
|
FixVisibPurgeLogFsm_s *workFsm = (FixVisibPurgeLogFsm_s *)fsm;
|
|
AuthBeast_s *authBeast;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
|
|
COMN_SETUP_GENERAL_MSG_NOSA(&genMsg);
|
|
|
|
zASSERT(workFsm->action == VIS_ACTION_REMOVE ||
|
|
workFsm->action == VIS_ACTION_ADD);
|
|
|
|
authBeast = workFsm->parentBeast;
|
|
|
|
switch (workFsm->action)
|
|
{
|
|
case VIS_ACTION_ADD:
|
|
workFsm->parentBeast = ZAS_InternalMakeItVisible(
|
|
&genMsg,
|
|
workFsm->parentBeast,
|
|
workFsm->volume,
|
|
workFsm->trusteeID,
|
|
&workFsm->trusteeCount,
|
|
workFsm->purgeLogLocations);
|
|
break;
|
|
|
|
case VIS_ACTION_REMOVE:
|
|
workFsm->parentBeast = ZAS_InternalRemoveVisibility(
|
|
&genMsg,
|
|
workFsm->parentBeast,
|
|
workFsm->volume,
|
|
workFsm->trusteeID,
|
|
&workFsm->trusteeCount,
|
|
workFsm->purgeLogLocations);
|
|
break;
|
|
}
|
|
|
|
TotalVisibilityProcesses--;
|
|
|
|
/* IMPORTANT NOTE: If the return values from ZAS_MakeItVisible &
|
|
* ZAS_InternalRemovingVisibility are non-NULL, the last thing they
|
|
* do is UNX_LATCH the previous parentBeast (we have it saved in the
|
|
* authBeast pointer.
|
|
*
|
|
* There should be no yield between the return from that call and
|
|
* queueing for a X_LATCH using the FSM_X_LATCH below. So do not put
|
|
* any code here.
|
|
*
|
|
* A NULL return from the above routines implies that visibility
|
|
* has been added/removed and all the beasts have been unlatched,
|
|
* and released. All we need to do is cleanup the workFsm
|
|
*/
|
|
if (workFsm->parentBeast != NULL)
|
|
{
|
|
FSM_X_LATCH(&workFsm->parentBeast->AUTHbeastLatch, &workFsm->fsm,
|
|
ZAS_FixVisibilityGotParentLatch);
|
|
COMN_Release(&authBeast);
|
|
}
|
|
else
|
|
{
|
|
--workFsm->volume->VOLv_keepActiveUseCount;
|
|
free(workFsm);
|
|
}
|
|
return;
|
|
}
|
|
|
|
/****************************************************************************
|
|
*
|
|
* This routine will set up fsm to add/remove visibility up the tree
|
|
*
|
|
***************************************************************************/
|
|
STATUS ZAS_FixVisibilityFsmStart(
|
|
GeneralMsg_s *genMsg,
|
|
Xaction_s *xaction,
|
|
AuthBeast_s *authBeast,
|
|
Zid_t parentZID,
|
|
UserID_t *trusteeID,
|
|
NINT trusteeCount,
|
|
BOOL checkForVisRebuild,
|
|
LONG action)
|
|
{
|
|
PurgeLogMsg_s purgeLogMsg;
|
|
FixVisibPurgeLogFsm_s *workFsm;
|
|
STATUS status = zOK;
|
|
AuthBeast_s *parentBeast;
|
|
FixVisibPLog_s *pLogLocations;
|
|
NINT i;
|
|
Volume_s *vol = authBeast->AUTHvolume;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
/*This routine assumes the beast is already open and the auth latch is set*/
|
|
|
|
ENTER(TAUTH, ZAS_FixVisibilityFsmStart);
|
|
ASSERT_XLATCH(&authBeast->AUTHauthInfo.zas->authLatch);
|
|
zASSERT(action == VIS_ACTION_ADD || action == VIS_ACTION_REMOVE);
|
|
|
|
/*
|
|
* If the visibility lists of the volume are being rebuilt then return
|
|
* unless we are already in the rebuild pass and the rebuild has passed
|
|
* the beast we are adding to.
|
|
*/
|
|
if (checkForVisRebuild && (vol->v_statusFlag & VOL_SF_CLEAN_VIS_SCHEDULED))
|
|
{
|
|
if (vol->v_statusFlag & VOL_SF_CLEAN_VIS_REBUILD)
|
|
{
|
|
if (authBeast->AUTHzid >= vol->VOLzidInProcess)
|
|
{
|
|
return zOK;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return zOK;
|
|
}
|
|
}
|
|
|
|
if (authBeast->AUTHzid == zROOTDIR_ZID)
|
|
{
|
|
RTN_STATUS(zOK);
|
|
}
|
|
|
|
if (trusteeCount == 0)
|
|
{
|
|
RTN_STATUS(zOK);
|
|
}
|
|
|
|
workFsm = zalloc(sizeof(FixVisibPurgeLogFsm_s) +
|
|
(trusteeCount * sizeof(UserID_t)) +
|
|
(trusteeCount * sizeof(FixVisibPLog_s)));
|
|
if (workFsm == NULL)
|
|
{
|
|
SetErrno(genMsg, zERR_NO_MEMORY);
|
|
RTN_STATUS(zFAILURE);
|
|
}
|
|
/* We lookup the beast not latched since it can yield, before we
|
|
* unlock the previous beast. We want the unlock and request for
|
|
* the latch on this beast to be simultaneous, without a yield
|
|
* in between.
|
|
*/
|
|
parentBeast = (AuthBeast_s *)BEASTHASH_LookupByZid(genMsg,
|
|
authBeast->AUTHvolume, parentZID, NOTLATCHED);
|
|
if (parentBeast == NULL)
|
|
{
|
|
ForceSetErrno(genMsg, zERR_UNABLE_TO_OPEN_BEAST);
|
|
free(workFsm);
|
|
RTN_STATUS(zFAILURE);
|
|
}
|
|
|
|
FSMLITE_INIT(&workFsm->fsm, MSGNot("FSM to fix visibility"), 0);
|
|
workFsm->parentBeast = parentBeast;
|
|
workFsm->trusteeID = (UserID_t *)((ADDR)workFsm +
|
|
sizeof(FixVisibPurgeLogFsm_s));
|
|
workFsm->trusteeCount = trusteeCount;
|
|
workFsm->volume = authBeast->AUTHvolume;
|
|
workFsm->action = action;
|
|
memcpy(workFsm->trusteeID, trusteeID, (trusteeCount * sizeof(UserID_t)));
|
|
workFsm->purgeLogLocations = (FixVisibPLog_s *)((ADDR)workFsm +
|
|
sizeof(FixVisibPurgeLogFsm_s) +
|
|
(trusteeCount * sizeof(UserID_t)));
|
|
|
|
++workFsm->volume->VOLv_keepActiveUseCount;
|
|
|
|
pLogLocations = workFsm->purgeLogLocations;
|
|
|
|
for (i = 0; i < trusteeCount; i++)
|
|
{
|
|
SETUP_FIX_VISIBILITY_PURGE_LOG(&purgeLogMsg,
|
|
pLogLocations, action, parentZID, trusteeID);
|
|
|
|
status = authBeast->AUTHcomnVolOps.VOL_addPurgeLogEntry(
|
|
genMsg, authBeast->AUTHvolume,
|
|
PLOG_FIX_VISIBILITY, &purgeLogMsg, xaction);
|
|
|
|
if (status == zOK)
|
|
{
|
|
trusteeID++;
|
|
pLogLocations++;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (status != zOK)
|
|
{
|
|
--workFsm->volume->VOLv_keepActiveUseCount;
|
|
free(workFsm);
|
|
RTN_STATUS(zFAILURE);
|
|
}
|
|
|
|
FSM_X_LATCH(&workFsm->parentBeast->AUTHbeastLatch, &workFsm->fsm,
|
|
ZAS_FixVisibilityGotParentLatch);
|
|
|
|
RTN_STATUS(zOK);
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* This routine will start a fsm to add visibility up the tree
|
|
*
|
|
***************************************************************************/
|
|
STATUS ZAS_MakeItVisible(
|
|
GeneralMsg_s *genMsg,
|
|
Xaction_s *xaction,
|
|
AuthBeast_s *authBeast,
|
|
Zid_t parentZID,
|
|
UserID_t *trusteeID,
|
|
NINT trusteeCount,
|
|
BOOL checkForVisRebuild)
|
|
{
|
|
return ZAS_FixVisibilityFsmStart(genMsg, xaction, authBeast, parentZID,
|
|
trusteeID, trusteeCount,
|
|
checkForVisRebuild, VIS_ACTION_ADD);
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* This routine will start a fsm to remove visibility up the tree
|
|
*
|
|
***************************************************************************/
|
|
STATUS ZAS_RemoveVisibility(
|
|
GeneralMsg_s *genMsg,
|
|
Xaction_s *xaction,
|
|
AuthBeast_s *authBeast,
|
|
Zid_t parentZID,
|
|
UserID_t *trusteeID,
|
|
NINT trusteeCount,
|
|
BOOL checkForVisRebuild)
|
|
{
|
|
return ZAS_FixVisibilityFsmStart(genMsg, xaction, authBeast, parentZID,
|
|
trusteeID, trusteeCount, checkForVisRebuild,
|
|
VIS_ACTION_REMOVE);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* This routine is called from PlayPurgeLog to finish fixing up visibility
|
|
*
|
|
***************************************************************************/
|
|
STATUS ZAS_FixVisibility(
|
|
GeneralMsg_s *genMsg,
|
|
NINT action,
|
|
Volume_s *volume,
|
|
Zid_t parentZID,
|
|
UserID_t *trusteeID,
|
|
void *purgeLogLoc)
|
|
{
|
|
STATUS status = zOK;
|
|
UserID_t localTrusteeID = *trusteeID;
|
|
AuthBeast_s *authBeast;
|
|
AuthBeast_s *parentBeast;
|
|
NINT trusteeCount = 1;
|
|
|
|
|
|
parentBeast = (AuthBeast_s *)BEASTHASH_LookupByZid(genMsg, volume,
|
|
parentZID, NOTLATCHED);
|
|
if (parentBeast == NULL)
|
|
{
|
|
ForceSetErrno(genMsg, zERR_UNABLE_TO_OPEN_BEAST);
|
|
return zFAILURE;
|
|
}
|
|
|
|
TotalVisibilityProcesses++;
|
|
|
|
X_LATCH(&parentBeast->AUTHbeastLatch);
|
|
ClearErrno(genMsg);
|
|
|
|
for (;;)
|
|
{
|
|
authBeast = parentBeast;
|
|
|
|
switch (action)
|
|
{
|
|
case VIS_ACTION_ADD:
|
|
parentBeast = ZAS_InternalMakeItVisible(genMsg, parentBeast,
|
|
volume, &localTrusteeID, &trusteeCount, purgeLogLoc);
|
|
break;
|
|
|
|
case VIS_ACTION_REMOVE:
|
|
parentBeast = ZAS_InternalRemoveVisibility(genMsg, parentBeast,
|
|
volume, &localTrusteeID, &trusteeCount, purgeLogLoc);
|
|
break;
|
|
}
|
|
TotalVisibilityProcesses--;
|
|
if (parentBeast == NULL)
|
|
{
|
|
if (GetErrno(genMsg) != zOK)
|
|
{
|
|
status = zFAILURE;
|
|
}
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
TotalVisibilityProcesses++;
|
|
X_LATCH(&parentBeast->AUTHbeastLatch);
|
|
COMN_Release(&authBeast);
|
|
}
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* This routine will check visibility rights for an object
|
|
****************************************************************************/
|
|
STATUS ZAS_CheckInheritedVisibility(
|
|
GeneralMsg_s *genMsg,
|
|
AuthBeast_s *authBeast,
|
|
NINT numIDs,
|
|
UserID_t *IDs)
|
|
{
|
|
Zid_t dummyZid;
|
|
NINT connectIndex;
|
|
NINT entryIndex;
|
|
VisEntry_s *entry;
|
|
ZASAuthorizeInfo_s *authInfo;
|
|
ZasVisOverflowBeast_s *beast;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
ENTER(TAUTH, ZAS_CheckInheritedVisibility);
|
|
|
|
authInfo = authBeast->AUTHauthInfo.zas;
|
|
S_LATCH(&authInfo->authLatch);
|
|
if ((authInfo->p.numVisibilityTrusteesAssigned > 0) ||
|
|
(authInfo->p.visibilityOverflow != zINVALID_ZID))
|
|
{ /* there are visibility entries */
|
|
for (connectIndex = 0; connectIndex < numIDs;
|
|
connectIndex++)
|
|
{ /* for each entry in the connection structure */
|
|
if (ZAS_FindVisibilityTrustee(genMsg, authBeast, NULL,
|
|
&IDs[connectIndex],
|
|
SLATCHED, &entry, &entryIndex, &beast, &dummyZid) != zOK)
|
|
{
|
|
goto error;
|
|
}
|
|
if (beast != NULL)
|
|
{
|
|
COMN_UnlatchAndRelease(&beast, SLATCHED);
|
|
}
|
|
if (entry != NULL)
|
|
{
|
|
UNS_LATCH(&authInfo->authLatch);
|
|
RTN_STATUS(zOK);
|
|
}
|
|
}
|
|
}
|
|
/* visibility not found */
|
|
#if NSS_DEBUG IS_ENABLED
|
|
DBG_DebugPrintf(LRED, MSGNot("Trustees in the connection structure:\n"));
|
|
for (connectIndex = 0; connectIndex < numIDs;
|
|
connectIndex++)
|
|
{
|
|
DBG_DebugPrintf(CYAN, MSGNot(" (%d) Trustee: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n"),
|
|
connectIndex,
|
|
IDs[connectIndex].timeLow,
|
|
IDs[connectIndex].timeMid,
|
|
IDs[connectIndex].timeHighAndVersion,
|
|
IDs[connectIndex].clockSeqHighAndReserved,
|
|
IDs[connectIndex].clockSeqLow,
|
|
IDs[connectIndex].node[0],
|
|
IDs[connectIndex].node[1],
|
|
IDs[connectIndex].node[2],
|
|
IDs[connectIndex].node[3],
|
|
IDs[connectIndex].node[4],
|
|
IDs[connectIndex].node[5]);
|
|
}
|
|
DEBUG_Display_Visibility(authBeast);
|
|
DBG_DebugPrintf(LRED, "\n");
|
|
#endif
|
|
error:
|
|
UNS_LATCH(&authInfo->authLatch);
|
|
RTN_STATUS(zFAILURE);
|
|
}
|
|
EXPORT_SYMBOL(ZAS_CheckInheritedVisibility);
|
|
|
|
/***************************************************************************
|
|
*
|
|
* This routine adds all of the ACLs in a beast to the visibility.
|
|
*
|
|
***************************************************************************/
|
|
STATUS ZAS_AddBeastVisibility(
|
|
GeneralMsg_s *genMsg,
|
|
AuthBeast_s *authBeast,
|
|
Zid_t parentZid,
|
|
BOOL includeVisEntries,
|
|
VisRebuildStats_s *stats,
|
|
BOOL checkForVisRebuild)
|
|
{
|
|
ZASAuthorizeInfo_s *authInfo;
|
|
Xaction_s *xaction;
|
|
NINT originalCount;
|
|
ACLEntry_s *allACLs = NULL;
|
|
UserID_t *trusteeID = NULL;
|
|
VisEntry_s *allVis = NULL;
|
|
NINT i;
|
|
STATUS status = zOK;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
|
|
/*
|
|
* Fix up the visibility inheritance
|
|
*/
|
|
authInfo = authBeast->AUTHauthInfo.zas;
|
|
|
|
if (authInfo->p.numTrusteesAssigned == 0)
|
|
{
|
|
if (includeVisEntries)
|
|
{
|
|
if (authInfo->p.numVisibilityTrusteesAssigned == 0)
|
|
{
|
|
return zOK;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return zOK;
|
|
}
|
|
}
|
|
|
|
X_LATCH(&authInfo->authLatch);
|
|
if (authInfo->p.numTrusteesAssigned != 0)
|
|
{
|
|
NINT trusteeCount;
|
|
|
|
if (ZAS_CountACLs(genMsg, authBeast, &originalCount) != zOK)
|
|
{
|
|
status = zFAILURE;
|
|
goto exit;
|
|
}
|
|
zASSERT(originalCount > 0);
|
|
|
|
if ((allACLs = malloc(originalCount * sizeof(ACLEntry_s))) == NULL)
|
|
{
|
|
SetErrno(genMsg, zERR_NO_MEMORY);
|
|
status = zFAILURE;
|
|
goto exit;
|
|
}
|
|
if ((trusteeID = malloc(originalCount * sizeof(UserID_t))) == NULL)
|
|
{
|
|
SetErrno(genMsg, zERR_NO_MEMORY);
|
|
status = zFAILURE;
|
|
goto exit;
|
|
}
|
|
if (ZAS_GetAllACLs(genMsg, authBeast, allACLs, originalCount) != zOK)
|
|
{
|
|
status = zFAILURE;
|
|
goto exit;
|
|
}
|
|
|
|
/*
|
|
* We do not want to add visibility if the trustee has no rights, so
|
|
* remove any entries where there are no rights.
|
|
*/
|
|
trusteeCount = 0;
|
|
for (i = 0; i < originalCount; i++)
|
|
{
|
|
trusteeID[trusteeCount] = allACLs[i].trusteeID;
|
|
if (allACLs[i].rights)
|
|
{
|
|
trusteeCount++;
|
|
}
|
|
}
|
|
|
|
if (trusteeCount != 0)
|
|
{
|
|
if (stats)
|
|
{
|
|
stats->VisNumTrusteesProcessed += trusteeCount;
|
|
}
|
|
|
|
/*
|
|
* Update the visibility entries up the tree
|
|
*/
|
|
xaction = COMN_BeginXLocal(authBeast);
|
|
|
|
ZAS_MakeItVisible(genMsg, xaction, authBeast, parentZid, trusteeID,
|
|
trusteeCount, checkForVisRebuild);
|
|
|
|
COMN_EndXLocal(authBeast, &xaction);
|
|
}
|
|
|
|
free(trusteeID);
|
|
trusteeID = NULL;
|
|
free(allACLs);
|
|
allACLs = NULL;
|
|
}
|
|
|
|
/*
|
|
* Fix up the visibility inheritance for exisiting visibility entries
|
|
*/
|
|
|
|
if (includeVisEntries && authInfo->p.numVisibilityTrusteesAssigned != 0)
|
|
{
|
|
if (ZAS_CountVis(genMsg, authBeast, &originalCount) != zOK)
|
|
{
|
|
status = zFAILURE;
|
|
goto exit;
|
|
}
|
|
zASSERT(originalCount > 0);
|
|
|
|
if ((allVis = malloc(originalCount * sizeof(VisEntry_s))) == NULL)
|
|
{
|
|
SetErrno(genMsg, zERR_NO_MEMORY);
|
|
status = zFAILURE;
|
|
goto exit;
|
|
}
|
|
if ((trusteeID = malloc(originalCount * sizeof(UserID_t))) == NULL)
|
|
{
|
|
SetErrno(genMsg, zERR_NO_MEMORY);
|
|
status = zFAILURE;
|
|
goto exit;
|
|
}
|
|
if (ZAS_GetAllVis(genMsg, authBeast, allVis, originalCount) != zOK)
|
|
{
|
|
status = zFAILURE;
|
|
goto exit;
|
|
}
|
|
|
|
/*
|
|
* Move an entry into the trustee array for each visibility entry
|
|
* to be added.
|
|
*/
|
|
for (i = 0; i < originalCount; i++)
|
|
{
|
|
trusteeID[i] = allVis[i].trusteeID;
|
|
}
|
|
|
|
/*
|
|
* Update the visibility entries up the tree
|
|
*/
|
|
xaction = COMN_BeginXLocal(authBeast);
|
|
|
|
ZAS_MakeItVisible(genMsg, xaction, authBeast, parentZid, trusteeID,
|
|
originalCount, checkForVisRebuild);
|
|
|
|
COMN_EndXLocal(authBeast, &xaction);
|
|
}
|
|
|
|
exit:
|
|
free(trusteeID);
|
|
free(allACLs);
|
|
UNX_LATCH(&authInfo->authLatch);
|
|
|
|
return status;
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
* This routine is called when a name is added to the name tree. It adds
|
|
* the trustees in the ACL to the visiblity list.
|
|
*
|
|
***************************************************************************/
|
|
STATUS VAUTH_AddAuthInfo(
|
|
GeneralMsg_s *genMsg,
|
|
AuthBeast_s *authBeast,
|
|
Zid_t parentZid,
|
|
Latch_s *parentLatch)
|
|
{
|
|
return ZAS_AddBeastVisibility(genMsg, authBeast, parentZid, TRUE, NULL, TRUE);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* This routine is called when a name is deleted from the name tree
|
|
*
|
|
***************************************************************************/
|
|
STATUS VAUTH_RemoveAuthInfo(
|
|
GeneralMsg_s *genMsg,
|
|
AuthBeast_s *authBeast,
|
|
Zid_t parentZid,
|
|
Xaction_s *xaction)
|
|
{
|
|
ZASAuthorizeInfo_s *authInfo;
|
|
NINT originalCount;
|
|
ACLEntry_s *allACLs = NULL;
|
|
VisEntry_s *allVis = NULL;
|
|
UserID_t *trusteeID = NULL;
|
|
NINT i;
|
|
STATUS status = zOK;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
ENTER(TAUTH, VAUTH_RemoveAuthInfo);
|
|
|
|
/*
|
|
* Fix up the visibility inheritance for ACLs
|
|
*/
|
|
authInfo = authBeast->AUTHauthInfo.zas;
|
|
|
|
if (authInfo->p.numTrusteesAssigned == 0 &&
|
|
authInfo->p.numVisibilityTrusteesAssigned == 0)
|
|
{ /* if there are no trustees assigned then just return */
|
|
RTN_STATUS(zOK);
|
|
}
|
|
|
|
X_LATCH(&authInfo->authLatch);
|
|
if (authInfo->p.numTrusteesAssigned != 0)
|
|
{
|
|
NINT trusteeCount;
|
|
|
|
if (ZAS_CountACLs(genMsg, authBeast, &originalCount) != zOK)
|
|
{
|
|
status = zFAILURE;
|
|
goto exit;
|
|
}
|
|
zASSERT(originalCount > 0);
|
|
|
|
if ((allACLs = malloc(originalCount * sizeof(ACLEntry_s))) == NULL)
|
|
{
|
|
SetErrno(genMsg, zERR_NO_MEMORY);
|
|
status = zFAILURE;
|
|
goto exit;
|
|
}
|
|
if ((trusteeID = malloc(originalCount * sizeof(UserID_t))) == NULL)
|
|
{
|
|
SetErrno(genMsg, zERR_NO_MEMORY);
|
|
status = zFAILURE;
|
|
goto exit;
|
|
}
|
|
if (ZAS_GetAllACLs(genMsg, authBeast, allACLs, originalCount) != zOK)
|
|
{
|
|
status = zFAILURE;
|
|
goto exit;
|
|
}
|
|
|
|
/*
|
|
* We do not want to remove visibility if the trustee has no rights, so
|
|
* remove any entries where there are no rights.
|
|
*/
|
|
trusteeCount = 0;
|
|
for (i = 0; i < originalCount; i++)
|
|
{
|
|
trusteeID[trusteeCount] = allACLs[i].trusteeID;
|
|
if (allACLs[i].rights)
|
|
{
|
|
trusteeCount++;
|
|
}
|
|
}
|
|
|
|
if (trusteeCount != 0)
|
|
{
|
|
/*
|
|
* Remove the visibility for the trustee from the entries up the tree
|
|
*/
|
|
ZAS_RemoveVisibility(genMsg, xaction, authBeast, parentZid, trusteeID,
|
|
trusteeCount, TRUE);
|
|
}
|
|
|
|
free(trusteeID);
|
|
trusteeID = NULL;
|
|
free(allACLs);
|
|
allACLs = NULL;
|
|
}
|
|
|
|
/*
|
|
* Fix up the visibility inheritance for exisiting visibility entries
|
|
*/
|
|
|
|
if (authInfo->p.numVisibilityTrusteesAssigned != 0)
|
|
{
|
|
if (ZAS_CountVis(genMsg, authBeast, &originalCount) != zOK)
|
|
{
|
|
status = zFAILURE;
|
|
goto exit;
|
|
}
|
|
zASSERT(originalCount > 0);
|
|
|
|
if ((allVis = malloc(originalCount * sizeof(VisEntry_s))) == NULL)
|
|
{
|
|
SetErrno(genMsg, zERR_NO_MEMORY);
|
|
status = zFAILURE;
|
|
goto exit;
|
|
}
|
|
if ((trusteeID = malloc(originalCount * sizeof(UserID_t))) == NULL)
|
|
{
|
|
SetErrno(genMsg, zERR_NO_MEMORY);
|
|
status = zFAILURE;
|
|
goto exit;
|
|
}
|
|
if (ZAS_GetAllVis(genMsg, authBeast, allVis, originalCount) != zOK)
|
|
{
|
|
status = zFAILURE;
|
|
goto exit;
|
|
}
|
|
|
|
/*
|
|
* Move an entry into the trustee array for each visibility entry
|
|
* to be added.
|
|
*/
|
|
for (i = 0; i < originalCount; i++)
|
|
{
|
|
trusteeID[i] = allVis[i].trusteeID;
|
|
}
|
|
|
|
/*
|
|
* Remove the visibility for the trustee from the entries up the tree
|
|
*/
|
|
ZAS_RemoveVisibility(genMsg, xaction, authBeast, parentZid, trusteeID,
|
|
originalCount, TRUE);
|
|
}
|
|
|
|
exit:
|
|
free(trusteeID);
|
|
free(allACLs);
|
|
free(allVis);
|
|
UNX_LATCH(&authInfo->authLatch);
|
|
|
|
RTN_STATUS(status);
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
* This routine is called when a file is actually deleted. It cleans up the
|
|
* associated overflow beasts.
|
|
*
|
|
***************************************************************************/
|
|
STATUS VAUTH_DeleteAuthInfo(
|
|
GeneralMsg_s *genMsg,
|
|
AuthBeast_s *authBeast,
|
|
Zid_t parentZid)
|
|
{
|
|
ZASAuthorizeInfo_s *authInfo;
|
|
Xaction_s *xaction;
|
|
ZasAclOverflowBeast_s *aclOverflowBeast;
|
|
ZasVisOverflowBeast_s *visOverflowBeast;
|
|
Zid_t overflowZid;
|
|
STATUS status;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
|
|
authInfo = authBeast->AUTHauthInfo.zas;
|
|
|
|
X_LATCH(&authInfo->authLatch);
|
|
|
|
/* Remove the ACL overflow beasts */
|
|
xaction = COMN_BeginXLocal(authBeast);
|
|
|
|
/* Remove all ACL overflow beasts */
|
|
overflowZid = authInfo->p.trusteeOverflow;
|
|
while (overflowZid != zINVALID_ZID)
|
|
{ /* find an overflow beast with an open entry */
|
|
aclOverflowBeast = ZAS_LookupOverflowBeast(genMsg, authBeast->AUTHvolume,
|
|
overflowZid, XLATCHED, zFTYPE_ZAS_ACL_OVERFLOW);
|
|
if (aclOverflowBeast == NULL)
|
|
{ /* error */
|
|
status = zFAILURE;
|
|
goto exit;
|
|
}
|
|
|
|
overflowZid = aclOverflowBeast->p.nextOverflowZid;
|
|
BST_delete(genMsg, NULL, aclOverflowBeast, NULL, NULL,
|
|
xaction, FALSE, TRUE);
|
|
COMN_UnlatchAndRelease(&aclOverflowBeast, XLATCHED);
|
|
}
|
|
status = zOK;
|
|
|
|
/* Remove all visibility overflow beasts */
|
|
overflowZid = authInfo->p.visibilityOverflow;
|
|
while (overflowZid != zINVALID_ZID)
|
|
{ /* find an overflow beast with an open entry */
|
|
visOverflowBeast = ZAS_LookupOverflowBeast(genMsg, authBeast->AUTHvolume,
|
|
overflowZid, XLATCHED, zFTYPE_ZAS_VIS_OVERFLOW);
|
|
if (visOverflowBeast == NULL)
|
|
{ /* error */
|
|
status = zFAILURE;
|
|
goto exit;
|
|
}
|
|
|
|
overflowZid = visOverflowBeast->p.nextOverflowZid;
|
|
BST_delete(genMsg, NULL, visOverflowBeast, NULL, NULL,
|
|
xaction, FALSE, TRUE);
|
|
COMN_UnlatchAndRelease(&visOverflowBeast, XLATCHED);
|
|
}
|
|
status = zOK;
|
|
|
|
exit:
|
|
COMN_EndXLocal(authBeast, &xaction);
|
|
|
|
UNX_LATCH(&authInfo->authLatch);
|
|
|
|
return status;
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
* This routine is called to determine if there is auth info that needs
|
|
* to be cleaned up. If so then it returns TRUE.
|
|
*
|
|
***************************************************************************/
|
|
BOOL VAUTH_IsAuthInfo(
|
|
GeneralMsg_s *genMsg,
|
|
AuthBeast_s *authBeast)
|
|
{
|
|
ZASAuthorizeInfo_s *authInfo;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
|
|
authInfo = authBeast->AUTHauthInfo.zas;
|
|
|
|
if (authInfo->p.numTrusteesAssigned != 0)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
if (authInfo->p.trusteeOverflow != zINVALID_ZID)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* This routine is used to initialize the authorization info for a newly
|
|
* created volume. It must only change items in the volume's rootdir.
|
|
* The caller will have the rootdir xlatched and will ensure that the
|
|
* rootdir gets written and the latch released on successful return. On
|
|
* error return the volume will not get created.
|
|
*****************************************************************************/
|
|
STATUS VAUTH_InitVolumeAuthInfo(
|
|
GeneralMsg_s *genMsg,
|
|
Volume_s *volBeast)
|
|
{
|
|
AuthBeast_s *rootdir = (AuthBeast_s *)volBeast->rootdir;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
ASSERT_XLATCH(&rootdir->AUTHbeastLatch);
|
|
|
|
/* allow no inheritance on rootdir */
|
|
rootdir->AUTHauthInfo.zas->p.inheritedRightsMask = 0;
|
|
return(zOK);
|
|
}
|
|
|
|
typedef struct SaveTrusteeEntry_s
|
|
{
|
|
NINT trusteeID;
|
|
NINT rights;
|
|
NINT attributes;
|
|
} SaveTrusteeEntry_s;
|
|
|
|
/****************************************************************************
|
|
*
|
|
* This routine removes a list of trustees from all objects in a given
|
|
* volume. Currently it is calling a routine that is also called from
|
|
* the authorization space for some symantic agent requests. The authorization
|
|
* space routine could have been placed directly in the ops tables, but since
|
|
* this is an infrequently used call I gave it its own routine to avoid
|
|
* confusion.
|
|
*
|
|
****************************************************************************/
|
|
STATUS VAUTH_RemoveIDsFromAVolume(
|
|
GeneralMsg_s *genMsg,
|
|
NamingMsg_s *nameMsg,
|
|
UserID_t *IDlist,
|
|
NINT IDcount)
|
|
{
|
|
ASSERT_MPKNSS_LOCK();
|
|
return VAUTH_PurgeACLEntriesFromTree(genMsg, nameMsg, IDlist, IDcount);
|
|
}
|
|
|
|
/****************************************************************************
|
|
*
|
|
* This function repairs a beast with a bad overflow zid
|
|
*
|
|
****************************************************************************/
|
|
void VAUTH_FixOverflowLink(
|
|
GeneralMsg_s *genMsg,
|
|
Volume_s *volume,
|
|
AuthBeast_s *beast,
|
|
Zid_t overflowZid)
|
|
{
|
|
ZasAclOverflowBeast_s *overflowBeast;
|
|
NINT unicodeLen;
|
|
unicode_t *name;
|
|
|
|
if (overflowZid == zINVALID_ZID)
|
|
{ /* The bad zid is in the file beast */
|
|
beast->AUTHauthInfo.zas->p.trusteeOverflow = zINVALID_ZID;
|
|
COMN_MARK_BEAST_DIRTY(&beast->AUTHroot);
|
|
}
|
|
else
|
|
{ /* The bad zid is in an overflow beast */
|
|
overflowBeast = ZAS_LookupOverflowBeast(genMsg, volume, overflowZid,
|
|
XLATCHED, zFTYPE_ZAS_ACL_OVERFLOW);
|
|
if (overflowBeast == NULL)
|
|
{
|
|
return;
|
|
}
|
|
overflowBeast->p.nextOverflowZid = zINVALID_ZID;
|
|
COMN_MARK_BEAST_DIRTY(&overflowBeast->ACLOroot);
|
|
COMN_UnlatchAndRelease(&overflowBeast, XLATCHED);
|
|
}
|
|
if (COMN_IsDerivedFrom(beast, zFTYPE_FILE))
|
|
{
|
|
name = malloc((zMAX_COMPONENT_NAME + 1) * sizeof(unicode_t));
|
|
if (name)
|
|
{
|
|
COMN_GetNameFromBeast(genMsg, (File_s *)beast, /* cnt zFNU_FIRST_PARENT,*/
|
|
zNSPACE_LONG, zMAX_COMPONENT_NAME, name, &unicodeLen);
|
|
name[unicodeLen] = L'\0';
|
|
aprintf(LRED, "Fixed bad authorization overflow link on file %U\n",
|
|
name);
|
|
free(name);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
aprintf(LRED, "Fixed bad authorization overflow link. Zid=%Lu",
|
|
beast->AUTHzid);
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
*
|
|
* This function adds the NDS object GUIDs to the User store for all
|
|
* structures in the ZAS auth model.
|
|
*
|
|
****************************************************************************/
|
|
STATUS VAUTH_CheckUserIDs(
|
|
GeneralMsg_s *genMsg,
|
|
Volume_s *volume,
|
|
AuthBeast_s *beast)
|
|
{
|
|
ZASAuthorizeInfo_s *authInfo;
|
|
NINT entry;
|
|
ZasAclOverflowBeast_s *overflowBeast;
|
|
Zid_t overflowZid;
|
|
BOOL isOK;
|
|
NINT numBadIDs;
|
|
Zid_t previousZid;
|
|
typedef struct Stack_s {
|
|
UserID_t badIDs[MAX_ACL_OVERFLOW_ENTRIES];
|
|
} Stack_s;
|
|
STACK_ALLOC();
|
|
|
|
authInfo = beast->AUTHauthInfo.zas;
|
|
X_LATCH(&authInfo->authLatch);
|
|
|
|
/* Check the trustees in the beast and the ACL overflow beasts */
|
|
for (entry=0; entry < authInfo->p.numTrusteesAssigned; entry++)
|
|
{
|
|
UserID_t userID = authInfo->p.ACL[entry].trusteeID;
|
|
|
|
if (CHK_VerifyID(genMsg, volume, &userID, &isOK) != zOK)
|
|
{
|
|
continue;
|
|
}
|
|
if (!isOK)
|
|
{
|
|
ZAS_RemoveLatchedACLEntry(genMsg, beast, &userID, TRUE, NULL);
|
|
}
|
|
}
|
|
|
|
/* check the overflow beasts for the entry */
|
|
overflowZid = authInfo->p.trusteeOverflow;
|
|
previousZid = zINVALID_ZID;
|
|
while (overflowZid != zINVALID_ZID)
|
|
{ /* find an overflow beast with an open entry */
|
|
overflowBeast = ZAS_LookupOverflowBeast(genMsg, volume, overflowZid,
|
|
SLATCHED, zFTYPE_ZAS_ACL_OVERFLOW);
|
|
if (overflowBeast == NULL)
|
|
{ /* error */
|
|
zASSERT("Error getting ACL overflow beast" == NULL);
|
|
VAUTH_FixOverflowLink(genMsg, volume, beast, previousZid);
|
|
break;
|
|
}
|
|
|
|
#if (CURRENT_BEAST_VERSION != BEAST_VERSION_3)
|
|
#error "Check to see if the beastVersion code below is still needed."
|
|
#endif
|
|
/* BEGINNING OF BEAST VERSION ONE CONVERSION CODE */
|
|
if (ZAS_ConvertACLFromVersionOne(genMsg, overflowBeast) != zOK)
|
|
{
|
|
COMN_UnlatchAndRelease(&overflowBeast, SLATCHED);
|
|
STACK_FREE();
|
|
return(zFAILURE);
|
|
}
|
|
/* END OF BEAST VERSION ONE CONVERSION CODE */
|
|
|
|
numBadIDs = 0;
|
|
for (entry = 0; entry < overflowBeast->p.numEntries; entry++)
|
|
{
|
|
if (CHK_VerifyID(genMsg, volume, &overflowBeast->acl[entry].trusteeID,
|
|
&isOK) != zOK)
|
|
{
|
|
continue;
|
|
}
|
|
if (!isOK)
|
|
{
|
|
aStack->badIDs[numBadIDs++] = overflowBeast->acl[entry].trusteeID;
|
|
}
|
|
}
|
|
UNS_LATCH(&overflowBeast->ACLObeastLatch);
|
|
|
|
/*
|
|
* We save up the bad IDs and remove them after the latch has been
|
|
* released so that we do not deadlock.
|
|
*/
|
|
while (numBadIDs > 0)
|
|
{
|
|
// DBG_DebugPrintf(LRED, "VAUTH_CheckUserIDs: removing user 0x%x\n", aStack->badIDs[numBadIDs - 1].timeLow);
|
|
ZAS_RemoveLatchedACLEntry(genMsg, beast,
|
|
&aStack->badIDs[--numBadIDs], TRUE, NULL);
|
|
}
|
|
previousZid = overflowZid;
|
|
overflowZid = overflowBeast->p.nextOverflowZid;
|
|
COMN_Release(&overflowBeast);
|
|
}
|
|
|
|
UNX_LATCH(&authInfo->authLatch);
|
|
STACK_FREE();
|
|
return zOK;
|
|
}
|
|
|
|
/****************************************************************************
|
|
*
|
|
* This function adds the NDS object GUIDs to the User store for all
|
|
* structures in the ZAS auth model.
|
|
*
|
|
****************************************************************************/
|
|
STATUS VAUTH_AddObjectNames(
|
|
GeneralMsg_s *genMsg,
|
|
Volume_s *volume,
|
|
AuthBeast_s *beast)
|
|
{
|
|
ZASAuthorizeInfo_s *authInfo;
|
|
NINT entry;
|
|
|
|
/* Add the trustees and visibility entries */
|
|
authInfo = beast->AUTHauthInfo.zas;
|
|
for (entry=0; entry < authInfo->p.numTrusteesAssigned; entry++)
|
|
{
|
|
OID_AddEntryIfNotThere(genMsg, volume,
|
|
&authInfo->p.ACL[entry].trusteeID);
|
|
}
|
|
for (entry=0; entry < authInfo->p.numVisibilityTrusteesAssigned;
|
|
entry++)
|
|
{
|
|
OID_AddEntryIfNotThere(genMsg, volume,
|
|
&authInfo->p.visibilityList[entry].trusteeID);
|
|
}
|
|
return zOK;
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
* This routine is called when the information for the authorization system
|
|
* (i.e. caching) may need to be invalidated.
|
|
*
|
|
***************************************************************************/
|
|
STATUS VAUTH_InvalidateAuthInfo(
|
|
GeneralMsg_s *genMsg)
|
|
{
|
|
return ZAS_InvalidateEntireEACLCache(genMsg, TRUE);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* This routine will count ACL entries for a file.
|
|
****************************************************************************/
|
|
STATUS ZAS_CountACLs(
|
|
GeneralMsg_s *genMsg,
|
|
AuthBeast_s *authBeast,
|
|
NINT *count)
|
|
{
|
|
ZASAuthorizeInfo_s *authInfo;
|
|
ZasAclOverflowBeast_s *overflowBeast;
|
|
Zid_t overflowZid;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
ENTER(TAUTH, ZAS_CountACLs);
|
|
|
|
authInfo = authBeast->AUTHauthInfo.zas;
|
|
ASSERT_LATCH(&authInfo->authLatch);
|
|
|
|
*count = authInfo->p.numTrusteesAssigned;
|
|
|
|
/* check the overflow beasts for the entry */
|
|
overflowZid = authInfo->p.trusteeOverflow;
|
|
while (overflowZid != zINVALID_ZID)
|
|
{ /* get the next overflow beast */
|
|
overflowBeast = ZAS_LookupOverflowBeast(genMsg, authBeast->AUTHvolume,
|
|
overflowZid, SLATCHED, zFTYPE_ZAS_ACL_OVERFLOW);
|
|
if (overflowBeast == NULL)
|
|
{ /* error */
|
|
RTN_STATUS(zFAILURE);
|
|
}
|
|
|
|
#if (CURRENT_BEAST_VERSION != BEAST_VERSION_3)
|
|
#error "Check to see if the beastVersion code below is still needed."
|
|
#endif
|
|
/* BEGINNING OF BEAST VERSION ONE CONVERSION CODE */
|
|
if (ZAS_ConvertACLFromVersionOne(genMsg, overflowBeast) != zOK)
|
|
{
|
|
COMN_UnlatchAndRelease(&overflowBeast, SLATCHED);
|
|
RTN_STATUS(zFAILURE);
|
|
}
|
|
/* END OF BEAST VERSION ONE CONVERSION CODE */
|
|
|
|
*count += overflowBeast->p.numEntries;
|
|
|
|
overflowZid = overflowBeast->p.nextOverflowZid;
|
|
COMN_UnlatchAndRelease(&overflowBeast, SLATCHED);
|
|
}
|
|
|
|
/* entry not found */
|
|
RTN_STATUS(zOK);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* This routine will count visibility entries for a file.
|
|
****************************************************************************/
|
|
STATUS ZAS_CountVis(
|
|
GeneralMsg_s *genMsg,
|
|
AuthBeast_s *authBeast,
|
|
NINT *count)
|
|
{
|
|
ZASAuthorizeInfo_s *authInfo;
|
|
ZasVisOverflowBeast_s *overflowBeast;
|
|
Zid_t overflowZid;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
|
|
authInfo = authBeast->AUTHauthInfo.zas;
|
|
ASSERT_LATCH(&authInfo->authLatch);
|
|
|
|
*count = authInfo->p.numVisibilityTrusteesAssigned;
|
|
|
|
/* check the overflow beasts for the entry */
|
|
overflowZid = authInfo->p.visibilityOverflow;
|
|
while (overflowZid != zINVALID_ZID)
|
|
{ /* get the next overflow beast */
|
|
overflowBeast = ZAS_LookupOverflowBeast(genMsg, authBeast->AUTHvolume,
|
|
overflowZid, SLATCHED, zFTYPE_ZAS_VIS_OVERFLOW);
|
|
if (overflowBeast == NULL)
|
|
{ /* error */
|
|
return zFAILURE;
|
|
}
|
|
|
|
#if (CURRENT_BEAST_VERSION != BEAST_VERSION_3)
|
|
#error "Check to see if the beastVersion code below is still needed."
|
|
#endif
|
|
/* BEGINNING OF BEAST VERSION ONE CONVERSION CODE */
|
|
if (ZAS_ConvertVisFromVersionOne(genMsg, NULL, authBeast) != zOK)
|
|
{
|
|
COMN_UnlatchAndRelease(&overflowBeast, SLATCHED);
|
|
return zFAILURE;
|
|
}
|
|
/* END OF BEAST VERSION ONE CONVERSION CODE */
|
|
|
|
*count += overflowBeast->p.numEntries;
|
|
|
|
overflowZid = overflowBeast->p.nextOverflowZid;
|
|
COMN_UnlatchAndRelease(&overflowBeast, SLATCHED);
|
|
}
|
|
|
|
/* entry not found */
|
|
return zOK;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* This routine will get an ACL entry for a file. If the sequence number is
|
|
* -1 or 0 then it gets the first entry, otherwise it gets the next one in
|
|
* the sequence. A returned sequence number of -1 means there are no more
|
|
* entries
|
|
****************************************************************************/
|
|
STATUS ZAS_GetAnACL(
|
|
GeneralMsg_s *genMsg,
|
|
AuthBeast_s *authBeast,
|
|
NINT *sequence,
|
|
UserID_t *trusteeID,
|
|
NINT *rights,
|
|
NINT *attributes)
|
|
{
|
|
ZASAuthorizeInfo_s *authInfo;
|
|
ZasAclOverflowBeast_s *overflowBeast;
|
|
Zid_t overflowZid;
|
|
NINT entry;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
ENTER(TAUTH, ZAS_GetAnACL);
|
|
|
|
if (*sequence == -1)
|
|
{ /* get the first entry */
|
|
*sequence = 0;
|
|
}
|
|
|
|
authInfo = authBeast->AUTHauthInfo.zas;
|
|
//FixFixFix: Need to think about this one:ASSERT_LATCH(&authInfo->authLatch);
|
|
|
|
entry = *sequence;
|
|
(*sequence)++;
|
|
|
|
/* check the main beast for the entry */
|
|
if (entry < authInfo->p.numTrusteesAssigned)
|
|
{ /* if the entry is in the main beast */
|
|
*trusteeID = authInfo->p.ACL[entry].trusteeID;
|
|
*rights = authInfo->p.ACL[entry].rights;
|
|
*attributes = authInfo->p.ACL[entry].attributes;
|
|
RTN_STATUS(zOK);
|
|
}
|
|
|
|
/* check the overflow beasts for the entry */
|
|
overflowZid = authInfo->p.trusteeOverflow;
|
|
entry -= authInfo->p.numTrusteesAssigned;
|
|
while (overflowZid != zINVALID_ZID)
|
|
{ /* find an overflow beast with an open entry */
|
|
overflowBeast = ZAS_LookupOverflowBeast(genMsg, authBeast->AUTHvolume,
|
|
overflowZid, SLATCHED, zFTYPE_ZAS_ACL_OVERFLOW);
|
|
if (overflowBeast == NULL)
|
|
{ /* error */
|
|
RTN_STATUS(zFAILURE);
|
|
}
|
|
|
|
#if (CURRENT_BEAST_VERSION != BEAST_VERSION_3)
|
|
#error "Check to see if the beastVersion code below is still needed."
|
|
#endif
|
|
/* BEGINNING OF BEAST VERSION ONE CONVERSION CODE */
|
|
if (ZAS_ConvertACLFromVersionOne(genMsg, overflowBeast) != zOK)
|
|
{
|
|
COMN_UnlatchAndRelease(&overflowBeast, SLATCHED);
|
|
RTN_STATUS(zFAILURE);
|
|
}
|
|
/* END OF BEAST VERSION ONE CONVERSION CODE */
|
|
|
|
if (entry < overflowBeast->p.numEntries)
|
|
{
|
|
*trusteeID = overflowBeast->acl[entry].trusteeID;
|
|
*rights = overflowBeast->acl[entry].rights;
|
|
*attributes = overflowBeast->acl[entry].attributes;
|
|
COMN_UnlatchAndRelease(&overflowBeast, SLATCHED);
|
|
RTN_STATUS(zOK);
|
|
}
|
|
overflowZid = overflowBeast->p.nextOverflowZid;
|
|
entry -= overflowBeast->p.numEntries;
|
|
COMN_UnlatchAndRelease(&overflowBeast, SLATCHED);
|
|
}
|
|
|
|
/* entry not found */
|
|
*sequence = -1;
|
|
RTN_STATUS(zOK);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* This routine will get all ACL entries for a file.
|
|
* trusteeID is a pointer to an array to fill in the trustee IDs.
|
|
* count is the size of the array.
|
|
****************************************************************************/
|
|
STATUS ZAS_GetAllACLs(
|
|
GeneralMsg_s *genMsg,
|
|
AuthBeast_s *authBeast,
|
|
ACLEntry_s *acl,
|
|
NINT count)
|
|
{
|
|
ZASAuthorizeInfo_s *authInfo;
|
|
ZasAclOverflowBeast_s *overflowBeast;
|
|
Zid_t overflowZid;
|
|
NINT entry;
|
|
NINT i;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
ENTER(TAUTH, ZAS_GetAllACLs);
|
|
|
|
authInfo = authBeast->AUTHauthInfo.zas;
|
|
ASSERT_LATCH(&authInfo->authLatch);
|
|
|
|
entry = 0;
|
|
|
|
/* check the main beast for the entry */
|
|
for (i = 0; ((i < authInfo->p.numTrusteesAssigned) && (entry < count));
|
|
entry++, i++)
|
|
{
|
|
acl[entry] = authInfo->p.ACL[i];
|
|
}
|
|
|
|
if (entry == count)
|
|
{
|
|
RTN_STATUS(zOK);
|
|
}
|
|
/* check the overflow beasts for the entry */
|
|
overflowZid = authInfo->p.trusteeOverflow;
|
|
while (overflowZid != zINVALID_ZID)
|
|
{ /* get the next overflow entry */
|
|
overflowBeast = ZAS_LookupOverflowBeast(genMsg, authBeast->AUTHvolume,
|
|
overflowZid, SLATCHED, zFTYPE_ZAS_ACL_OVERFLOW);
|
|
if (overflowBeast == NULL)
|
|
{ /* error */
|
|
RTN_STATUS(zFAILURE);
|
|
}
|
|
|
|
#if (CURRENT_BEAST_VERSION != BEAST_VERSION_3)
|
|
#error "Check to see if the beastVersion code below is still needed."
|
|
#endif
|
|
/* BEGINNING OF BEAST VERSION ONE CONVERSION CODE */
|
|
if (ZAS_ConvertACLFromVersionOne(genMsg, overflowBeast) != zOK)
|
|
{
|
|
COMN_UnlatchAndRelease(&overflowBeast, SLATCHED);
|
|
RTN_STATUS(zFAILURE);
|
|
}
|
|
/* END OF BEAST VERSION ONE CONVERSION CODE */
|
|
|
|
for (i = 0; ((i < overflowBeast->p.numEntries) && (entry < count));
|
|
entry++, i++)
|
|
{
|
|
acl[entry] = overflowBeast->acl[i];
|
|
}
|
|
overflowZid = overflowBeast->p.nextOverflowZid;
|
|
COMN_UnlatchAndRelease(&overflowBeast, SLATCHED);
|
|
if (entry == count)
|
|
{
|
|
RTN_STATUS(zOK);
|
|
}
|
|
}
|
|
|
|
zASSERT(entry == count);
|
|
RTN_STATUS(zOK);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* This routine will get all visibility entries for a file.
|
|
* trusteeID is a pointer to an array to fill in the trustee IDs.
|
|
* count is the size of the array.
|
|
****************************************************************************/
|
|
STATUS ZAS_GetAllVis(
|
|
GeneralMsg_s *genMsg,
|
|
AuthBeast_s *authBeast,
|
|
VisEntry_s *vis,
|
|
NINT count)
|
|
{
|
|
ZASAuthorizeInfo_s *authInfo;
|
|
ZasVisOverflowBeast_s *overflowBeast;
|
|
Zid_t overflowZid;
|
|
NINT entry = 0;
|
|
NINT i;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
|
|
authInfo = authBeast->AUTHauthInfo.zas;
|
|
ASSERT_LATCH(&authInfo->authLatch);
|
|
|
|
/* check the main beast for the entry */
|
|
for (i = 0; i < authInfo->p.numVisibilityTrusteesAssigned; i++)
|
|
{
|
|
zASSERT(entry < count);
|
|
if (entry < count)
|
|
{
|
|
vis[entry++] = authInfo->p.visibilityList[i];
|
|
}
|
|
}
|
|
|
|
/* check the overflow beasts for the entry */
|
|
overflowZid = authInfo->p.visibilityOverflow;
|
|
while (overflowZid != zINVALID_ZID)
|
|
{ /* get the next overflow beast */
|
|
overflowBeast = ZAS_LookupOverflowBeast(genMsg, authBeast->AUTHvolume,
|
|
overflowZid, SLATCHED, zFTYPE_ZAS_VIS_OVERFLOW);
|
|
if (overflowBeast == NULL)
|
|
{ /* error */
|
|
return zFAILURE;
|
|
}
|
|
|
|
#if (CURRENT_BEAST_VERSION != BEAST_VERSION_3)
|
|
#error "Check to see if the beastVersion code below is still needed."
|
|
#endif
|
|
/* BEGINNING OF BEAST VERSION ONE CONVERSION CODE */
|
|
if (ZAS_ConvertVisFromVersionOne(genMsg, NULL, authBeast) != zOK)
|
|
{
|
|
COMN_UnlatchAndRelease(&overflowBeast, SLATCHED);
|
|
return zFAILURE;
|
|
}
|
|
/* END OF BEAST VERSION ONE CONVERSION CODE */
|
|
|
|
for (i = 0; i < overflowBeast->p.numEntries; i++)
|
|
{
|
|
zASSERT(entry < count);
|
|
if (entry < count)
|
|
{
|
|
vis[entry++] = overflowBeast->vis[i];
|
|
}
|
|
}
|
|
|
|
overflowZid = overflowBeast->p.nextOverflowZid;
|
|
COMN_UnlatchAndRelease(&overflowBeast, SLATCHED);
|
|
}
|
|
|
|
zASSERT(entry == count);
|
|
return zOK;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* This routine will find a trustee and return a pointer to the trustee
|
|
* info and if it is in the overflow then a pointer the overflow beast is
|
|
* returned.
|
|
* If it is in the overflow then the overflow beast is returned open and
|
|
* latched.
|
|
****************************************************************************/
|
|
ACLEntry_s *ZAS_FindTrustee(
|
|
GeneralMsg_s *genMsg,
|
|
AuthBeast_s *authBeast,
|
|
UserID_t *trusteeID,
|
|
ZasAclOverflowBeast_s **returnBeast)
|
|
{
|
|
ZASAuthorizeInfo_s *authInfo;
|
|
ZasAclOverflowBeast_s *overflowBeast;
|
|
Zid_t overflowZid;
|
|
NINT entry;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
ENTER(TAUTH, ZAS_FindTrustee);
|
|
authInfo = authBeast->AUTHauthInfo.zas;
|
|
ASSERT_LATCH(&authInfo->authLatch);
|
|
*returnBeast = NULL;
|
|
|
|
/* search the main beast for the trustee */
|
|
for (entry=0; entry < authInfo->p.numTrusteesAssigned; entry++)
|
|
{
|
|
if (LB_GUIDCompare(&authInfo->p.ACL[entry].trusteeID, trusteeID) == 0)
|
|
{
|
|
RTN_PTR(&authInfo->p.ACL[entry]);
|
|
}
|
|
}
|
|
|
|
/* search the overflow beasts for the trustee */
|
|
overflowZid = authInfo->p.trusteeOverflow;
|
|
while (overflowZid != zINVALID_ZID)
|
|
{
|
|
overflowBeast = ZAS_LookupOverflowBeast(genMsg, authBeast->AUTHvolume,
|
|
overflowZid, XLATCHED, zFTYPE_ZAS_ACL_OVERFLOW);
|
|
if (overflowBeast == NULL)
|
|
{ /* error */
|
|
RTN_PTR(NULL);
|
|
}
|
|
|
|
#if (CURRENT_BEAST_VERSION != BEAST_VERSION_3)
|
|
#error "Check to see if the beastVersion code below is still needed."
|
|
#endif
|
|
/* BEGINNING OF BEAST VERSION ONE CONVERSION CODE */
|
|
if (ZAS_ConvertACLFromVersionOne(genMsg, overflowBeast) != zOK)
|
|
{
|
|
COMN_UnlatchAndRelease(&overflowBeast, XLATCHED);
|
|
RTN_PTR(NULL);
|
|
}
|
|
/* END OF BEAST VERSION ONE CONVERSION CODE */
|
|
|
|
for (entry=0; entry < overflowBeast->p.numEntries; entry++)
|
|
{
|
|
if (LB_GUIDCompare(&overflowBeast->acl[entry].trusteeID, trusteeID) == 0)
|
|
{
|
|
*returnBeast = overflowBeast;
|
|
RTN_PTR(&overflowBeast->acl[entry]);
|
|
}
|
|
}
|
|
overflowZid = overflowBeast->p.nextOverflowZid;
|
|
COMN_UnlatchAndRelease(&overflowBeast, XLATCHED);
|
|
}
|
|
RTN_PTR(NULL);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* This routine will add room for a trustee and return a pointer to the trustee
|
|
* info and a pointer to the overflow beast if it is added to the overflow.
|
|
* If it is in the overflow then the overflow beast is returned open and
|
|
* latched.
|
|
****************************************************************************/
|
|
ACLEntry_s *ZAS_AddTrustee(
|
|
GeneralMsg_s *genMsg,
|
|
AuthBeast_s *authBeast,
|
|
Xaction_s *xaction,
|
|
BOOL *writeMainBeast,
|
|
ZasAclOverflowBeast_s **returnBeast)
|
|
{
|
|
ACLEntry_s *aclEntry;
|
|
ZASAuthorizeInfo_s *authInfo;
|
|
Zid_t overflowZid;
|
|
ZasAclOverflowBeast_s *overflowBeast;
|
|
ZasAclOverflowBeast_s *oldOverflowBeast = NULL;
|
|
STATUS status;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
ENTER(TAUTH, ZAS_AddTrustee);
|
|
*writeMainBeast = FALSE;
|
|
authInfo = authBeast->AUTHauthInfo.zas;
|
|
ASSERT_LATCH(&authInfo->authLatch);
|
|
if (authInfo->p.numTrusteesAssigned < MAX_TRUSTEES_IN_BEAST)
|
|
{ /* if there is still space in the main beast */
|
|
aclEntry = &authInfo->p.ACL[authInfo->p.numTrusteesAssigned++];
|
|
*returnBeast = NULL;
|
|
*writeMainBeast = TRUE;
|
|
}
|
|
else
|
|
{ /* move to the overflow beasts */
|
|
overflowZid = authInfo->p.trusteeOverflow;
|
|
if (authInfo->p.trusteeOverflow != zINVALID_ZID)
|
|
{
|
|
for (;;)
|
|
{ /* find an overflow beast with an open entry */
|
|
overflowBeast = ZAS_LookupOverflowBeast(genMsg, authBeast->AUTHvolume,
|
|
overflowZid, XLATCHED, zFTYPE_ZAS_ACL_OVERFLOW);
|
|
if (overflowBeast == NULL)
|
|
{ /* error */
|
|
RTN_PTR(NULL);
|
|
}
|
|
|
|
#if (CURRENT_BEAST_VERSION != BEAST_VERSION_3)
|
|
#error "Check to see if the beastVersion code below is still needed."
|
|
#endif
|
|
/* BEGINNING OF BEAST VERSION ONE CONVERSION CODE */
|
|
if (ZAS_ConvertACLFromVersionOne(genMsg, overflowBeast) != zOK)
|
|
{
|
|
COMN_UnlatchAndRelease(&overflowBeast, XLATCHED);
|
|
RTN_PTR(NULL);
|
|
}
|
|
/* END OF BEAST VERSION ONE CONVERSION CODE */
|
|
|
|
if (overflowBeast->p.numEntries < MAX_ACL_OVERFLOW_ENTRIES)
|
|
{ /* if there is room in this node */
|
|
if (overflowBeast->p.numEntries >= overflowBeast->numAlloced)
|
|
{ /* if we need to make the memory structure bigger */
|
|
ACLEntry_s *acl;
|
|
overflowBeast->numAlloced += OVERFLOW_ALLOC_UNIT;
|
|
acl = realloc(overflowBeast->acl,
|
|
overflowBeast->numAlloced * sizeof (ACLEntry_s));
|
|
if (acl == NULL)
|
|
{
|
|
overflowBeast->numAlloced -= OVERFLOW_ALLOC_UNIT;
|
|
SetErrno(genMsg, zERR_NO_MEMORY);
|
|
COMN_UnlatchAndRelease(&overflowBeast, XLATCHED);
|
|
RTN_PTR(NULL);
|
|
}
|
|
overflowBeast->acl = acl;
|
|
}
|
|
aclEntry = &overflowBeast->acl[overflowBeast->p.numEntries++];
|
|
*returnBeast = overflowBeast;
|
|
RTN_PTR(aclEntry);
|
|
}
|
|
overflowZid = overflowBeast->p.nextOverflowZid;
|
|
oldOverflowBeast = overflowBeast;
|
|
if (overflowZid != zINVALID_ZID)
|
|
{
|
|
COMN_UnlatchAndRelease(&overflowBeast, XLATCHED);
|
|
oldOverflowBeast = NULL;
|
|
}
|
|
else
|
|
{ /* no open entries in the overflow beasts */
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Add a new overflow beast
|
|
*/
|
|
|
|
overflowBeast = (ZasAclOverflowBeast_s *)BST_create(genMsg,
|
|
zFTYPE_ZAS_ACL_OVERFLOW, authBeast->AUTHvolume, xaction);
|
|
if (overflowBeast == NULL)
|
|
{
|
|
if (oldOverflowBeast != NULL)
|
|
{
|
|
COMN_UnlatchAndRelease(&oldOverflowBeast, XLATCHED);
|
|
}
|
|
RTN_PTR(NULL);
|
|
}
|
|
|
|
/* link the new beast to the ones already there */
|
|
if (oldOverflowBeast == NULL)
|
|
{ /* link to main beast */
|
|
authInfo->p.trusteeOverflow = overflowBeast->ACLOzid;
|
|
*writeMainBeast = TRUE;
|
|
}
|
|
else
|
|
{ /* link to another overflow beast */
|
|
oldOverflowBeast->p.nextOverflowZid = overflowBeast->ACLOzid;
|
|
COMN_MARK_BEAST_XLOCAL(&oldOverflowBeast->ACLOroot, xaction);
|
|
status = COMN_ForceBeastWrite(genMsg, oldOverflowBeast, xaction);
|
|
COMN_UnlatchAndRelease(&oldOverflowBeast, XLATCHED);
|
|
if (status != zOK)
|
|
{
|
|
UNX_LATCH(&overflowBeast->ACLObeastLatch);
|
|
BST_free(overflowBeast);
|
|
RTN_PTR(NULL);
|
|
}
|
|
}
|
|
BEASTHASH_Insert(&overflowBeast->ACLOroot);
|
|
overflowBeast->ACLObstState |= BST_STATE_NEW;
|
|
overflowBeast->p.numEntries = 1;
|
|
aclEntry = &overflowBeast->acl[0];
|
|
*returnBeast = overflowBeast;
|
|
}
|
|
RTN_PTR(aclEntry);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* This routine will add a new trustee and rights to the given beast
|
|
****************************************************************************/
|
|
STATUS ZAS_AddACLEntry(
|
|
GeneralMsg_s *genMsg,
|
|
AuthBeast_s *authBeast,
|
|
UserID_t *trusteeID,
|
|
NINT rights,
|
|
NINT attributes)
|
|
{
|
|
ZASAuthorizeInfo_s *authInfo;
|
|
ACLEntry_s *ACLEntry;
|
|
ZasAclOverflowBeast_s *overflowBeast;
|
|
Xaction_s *xaction;
|
|
BOOL writeMainBeast = FALSE;
|
|
Zid_t hlZid;
|
|
HardLinkBeast_s *hlBeast;
|
|
BOOL modifyMetaDataTime = TRUE;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
ENTER(TAUTH, ZAS_AddACLEntry);
|
|
|
|
/* Defect #306666. We can't allow unlicensed connection access */
|
|
if (!ConnectionIsLoggedIn(genMsg->pssConn.id))
|
|
{
|
|
/* They are not logged in (LICENCED), so limit their access */
|
|
SetErrno(genMsg, zERR_NO_SET_PRIVILEGE);
|
|
goto cleanupError;
|
|
}
|
|
if (authBeast->AUTHvolume->VOLenabledAttributes & zATTR_READONLY)
|
|
{
|
|
SetErrno(genMsg, zERR_VOLUME_READ_ONLY);
|
|
return zFAILURE;
|
|
}
|
|
OID_SaveObjectID(authBeast->AUTHvolume, trusteeID);
|
|
|
|
authInfo = authBeast->AUTHauthInfo.zas;
|
|
X_LATCH(&authInfo->authLatch);
|
|
|
|
/* begin the transaction for adding an ACL */
|
|
xaction = COMN_BeginXLocal(authBeast);
|
|
if ((ACLEntry = ZAS_FindTrustee(genMsg, authBeast, trusteeID,
|
|
&overflowBeast)) == NULL)
|
|
{ /* could not find the trustee */
|
|
if ((ACLEntry = ZAS_AddTrustee(genMsg, authBeast, xaction,
|
|
&writeMainBeast, &overflowBeast)) == NULL)
|
|
{ /* error */
|
|
goto cleanupUnlatch;
|
|
}
|
|
ACLEntry->rights = 0;
|
|
|
|
if (!(authBeast->AUTHattributes & zFA_SUBDIRECTORY) ||
|
|
authBeast->AUTHcomnOps.BST_isDirectoryEmpty(genMsg, &authBeast->AUTHnamed, zNTYPE_FILE))
|
|
{ /* this object has no object below it */
|
|
ZAS_RemoveEACLCacheEntry(authInfo->p.cacheIndex, authInfo->p.signature);
|
|
}
|
|
else
|
|
{
|
|
ZAS_InvalidateEntireEACLCache(genMsg, TRUE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* we need to invalidate all entries because inheritance masking can
|
|
* cause a trustee ID to not be in a cache entry that would be
|
|
* affected if a right is added that is not masked out.
|
|
*/
|
|
if (ACLEntry->rights != rights)
|
|
{ /* if it is actually changing */
|
|
ZAS_InvalidateEntireEACLCache(genMsg, TRUE);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* If this is a hardlink primary beast, we need to add/remove visibility
|
|
* for all parents, not just the first parent.
|
|
*/
|
|
if ((authBeast->AUTHhardLinkZid != zINVALID_ZID) &&
|
|
!(authBeast->AUTHattributes & zFA_HARDLINK))
|
|
{
|
|
for (hlZid = authBeast->AUTHhardLinkZid; hlZid != zINVALID_ZID; )
|
|
{
|
|
hlBeast = COMN_LookupByZid(genMsg,authBeast->AUTHvolume,hlZid,
|
|
NOTLATCHED,TRUE);
|
|
if (hlBeast != NULL)
|
|
{
|
|
/*
|
|
* If rights are being given where there were none then update the
|
|
* visibility. If rights are being set to zero when they were non-zero
|
|
* before then remove the visibility. Entries that have a trustee that
|
|
* has no rights should not make directories above them visible.
|
|
*/
|
|
if (rights && !ACLEntry->rights)
|
|
{
|
|
/* FixFixFix6 -- need to do this for each parent */
|
|
ZAS_MakeItVisible(genMsg, xaction, authBeast,
|
|
hlBeast->HARDLfirstParentZid, trusteeID, 1, TRUE);
|
|
} else if (!rights && ACLEntry->rights)
|
|
{
|
|
/* FixFixFix6 -- need to remove visiblility on all parents */
|
|
ZAS_RemoveVisibility(genMsg, xaction, authBeast,
|
|
hlBeast->HARDLfirstParentZid, trusteeID, 1, TRUE);
|
|
}
|
|
|
|
hlZid = hlBeast->HARDLhardLinkZid;
|
|
COMN_Release(&hlBeast);
|
|
}
|
|
else
|
|
{
|
|
zASSERT("Broken hard link chain"==NULL);
|
|
hlZid = zINVALID_ZID;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
zASSERT(!(authBeast->AUTHattributes & zFA_HARDLINK));
|
|
|
|
/*
|
|
* If rights are being given where there were none then update the
|
|
* visibility. If rights are being set to zero when they were non-zero
|
|
* before then remove the visibility. Entries that have a trustee that
|
|
* has no rights should not make directories above them visible.
|
|
*/
|
|
if (rights && !ACLEntry->rights)
|
|
{
|
|
/* FixFixFix6 -- need to do this for each parent */
|
|
ZAS_MakeItVisible(genMsg, xaction, authBeast,
|
|
authBeast->AUTHfirstParentZid, trusteeID, 1, TRUE);
|
|
} else if (!rights && ACLEntry->rights)
|
|
{
|
|
/* FixFixFix6 -- need to remove visiblility on all parents */
|
|
ZAS_RemoveVisibility(genMsg, xaction, authBeast,
|
|
authBeast->AUTHfirstParentZid, trusteeID, 1, TRUE);
|
|
}
|
|
}
|
|
|
|
/* fill in the ACL */
|
|
ACLEntry->trusteeID = *trusteeID;
|
|
ACLEntry->rights = rights;
|
|
ACLEntry->attributes = attributes;
|
|
|
|
if (!(authBeast->AUTHattributes & zFA_ATTR_ARCHIVE))
|
|
{
|
|
authBeast->AUTHattributes |= zFA_ATTR_ARCHIVE;
|
|
writeMainBeast = TRUE;
|
|
}
|
|
|
|
if ((modifyMetaDataTime) && (COMN_IsDerivedFrom(authBeast, zFTYPE_FILE)))
|
|
{
|
|
File_s *file = (File_s *)authBeast;
|
|
file->FILEmetaDataModifiedTime = GetUTCTime();
|
|
writeMainBeast = TRUE;
|
|
}
|
|
|
|
if (writeMainBeast || (overflowBeast == NULL))
|
|
{ /* if the main beast is dirty */
|
|
authInfo->flags |= ZAS_ALLOW_FORCED_WRITE;
|
|
COMN_MARK_BEAST_XLOCAL(&authBeast->AUTHroot, xaction);
|
|
if (COMN_ForceBeastWrite(genMsg, authBeast, xaction) != zOK)
|
|
{
|
|
authInfo->flags &= ~ZAS_ALLOW_FORCED_WRITE;
|
|
goto cleanupUnlatch;
|
|
}
|
|
authInfo->flags &= ~ZAS_ALLOW_FORCED_WRITE;
|
|
}
|
|
|
|
if (overflowBeast != NULL)
|
|
{ /* if the entry is in the overflow beast */
|
|
COMN_MARK_BEAST_XLOCAL(&overflowBeast->ACLOroot, xaction);
|
|
if (COMN_ForceBeastWrite(genMsg, overflowBeast, xaction) != zOK)
|
|
{
|
|
goto cleanupUnlatch;
|
|
}
|
|
}
|
|
|
|
if (overflowBeast != NULL)
|
|
{
|
|
COMN_UnlatchAndRelease(&overflowBeast, XLATCHED);
|
|
}
|
|
|
|
authInfo->flags |= ZAS_ALLOW_FORCED_WRITE;
|
|
VOL_insertEFLEntry(genMsg, &authBeast->AUTHroot,
|
|
EFL_FILE_STATE_MODIFY_METADATA, NULL, xaction);
|
|
authInfo->flags &= ~ZAS_ALLOW_FORCED_WRITE;
|
|
|
|
UNX_LATCH(&authInfo->authLatch);
|
|
COMN_EndXLocal(authBeast, &xaction);
|
|
RTN_STATUS(zOK);
|
|
|
|
cleanupUnlatch:
|
|
if (overflowBeast != NULL)
|
|
{
|
|
COMN_UnlatchAndRelease(&overflowBeast, XLATCHED);
|
|
}
|
|
UNX_LATCH(&authInfo->authLatch);
|
|
COMN_EndXLocal(authBeast, &xaction);
|
|
|
|
cleanupError:
|
|
RTN_STATUS(zFAILURE);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Remove a beast and link the previous to the next.
|
|
****************************************************************************/
|
|
void ZAS_RemoveOverflowBeast(
|
|
GeneralMsg_s *genMsg,
|
|
ZasAclOverflowBeast_s *delBeast,
|
|
ZasAclOverflowBeast_s *prevBeast,
|
|
ZASAuthorizeInfo_s *authInfo,
|
|
BOOL *forceMainBeast,
|
|
Xaction_s *xaction)
|
|
{
|
|
if (prevBeast == NULL)
|
|
{ /* if linked from the main beast then unlink */
|
|
authInfo->p.trusteeOverflow = delBeast->p.nextOverflowZid;
|
|
*forceMainBeast = TRUE;
|
|
}
|
|
else
|
|
{
|
|
prevBeast->p.nextOverflowZid = delBeast->p.nextOverflowZid;
|
|
COMN_MARK_BEAST_XLOCAL(&prevBeast->ACLOroot, xaction);
|
|
COMN_ForceBeastWrite(genMsg, prevBeast, xaction);
|
|
zASSERT(GetErrno(genMsg) == zOK);
|
|
ClearErrno(genMsg);
|
|
}
|
|
BST_delete(genMsg, NULL, delBeast, NULL, NULL, xaction, FALSE, TRUE);
|
|
COMN_UnlatchAndRelease(&delBeast, XLATCHED);
|
|
zASSERT(GetErrno(genMsg) == zOK);
|
|
ClearErrno(genMsg);
|
|
return;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* This routine will remove a trustee from either the main beast or from
|
|
* an overflow beast.
|
|
****************************************************************************/
|
|
STATUS ZAS_RemoveTrustee(
|
|
GeneralMsg_s *genMsg,
|
|
AuthBeast_s *authBeast,
|
|
UserID_t *trusteeID,
|
|
NINT *rights,
|
|
Xaction_s *xaction)
|
|
{
|
|
ACLEntry_s *aclEntry;
|
|
Zid_t overflowZid;
|
|
Zid_t lastGoodZid = zINVALID_ZID;
|
|
ZASAuthorizeInfo_s *authInfo;
|
|
ZasAclOverflowBeast_s *deleteBeast = NULL;
|
|
ZasAclOverflowBeast_s *lastBeast = NULL;
|
|
ZasAclOverflowBeast_s *prevBeast = NULL;
|
|
STATUS status = zOK;
|
|
BOOL forceMainBeast = FALSE;
|
|
BOOL forceDeleteBeast = FALSE;
|
|
BOOL releasePrevious = FALSE;
|
|
NINT entry;
|
|
BOOL modifyMetaDataTime = TRUE;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
ENTER(TAUTH, ZAS_RemoveTrustee);
|
|
|
|
authInfo = authBeast->AUTHauthInfo.zas;
|
|
ASSERT_LATCH(&authInfo->authLatch);
|
|
|
|
/*
|
|
* Find the location where the trustee is to be deleted from.
|
|
*/
|
|
|
|
overflowZid = authInfo->p.trusteeOverflow;
|
|
|
|
/* search the main beast for the trustee */
|
|
for (entry=0; entry < authInfo->p.numTrusteesAssigned; entry++)
|
|
{
|
|
if (LB_GUIDCompare(&authInfo->p.ACL[entry].trusteeID, trusteeID) == 0)
|
|
{
|
|
aclEntry = &authInfo->p.ACL[entry];
|
|
forceMainBeast = TRUE;
|
|
goto findLast;
|
|
}
|
|
}
|
|
|
|
/* search the overflow beasts for the trustee */
|
|
while (overflowZid != zINVALID_ZID)
|
|
{ /* find an overflow beast with an open entry */
|
|
if (prevBeast != NULL && releasePrevious)
|
|
{
|
|
COMN_UnlatchAndRelease(&prevBeast, XLATCHED);
|
|
}
|
|
prevBeast = deleteBeast;
|
|
deleteBeast = ZAS_LookupOverflowBeast(genMsg, authBeast->AUTHvolume,
|
|
overflowZid, XLATCHED, zFTYPE_ZAS_ACL_OVERFLOW);
|
|
if (deleteBeast == NULL)
|
|
{ /* error */
|
|
status = zFAILURE;
|
|
goto cleanup;
|
|
}
|
|
lastGoodZid = overflowZid;
|
|
#if (CURRENT_BEAST_VERSION != BEAST_VERSION_3)
|
|
#error "Check to see if the beastVersion code below is still needed."
|
|
#endif
|
|
/* BEGINNING OF BEAST VERSION ONE CONVERSION CODE */
|
|
if (ZAS_ConvertACLFromVersionOne(genMsg, deleteBeast) != zOK)
|
|
{
|
|
COMN_UnlatchAndRelease(&deleteBeast, XLATCHED);
|
|
status = zFAILURE;
|
|
goto cleanup;
|
|
}
|
|
/* END OF BEAST VERSION ONE CONVERSION CODE */
|
|
|
|
overflowZid = deleteBeast->p.nextOverflowZid;
|
|
if (deleteBeast->p.numEntries == 0)
|
|
{
|
|
releasePrevious = FALSE;
|
|
ZAS_RemoveOverflowBeast(genMsg, deleteBeast, prevBeast, authInfo,
|
|
&forceMainBeast, xaction);
|
|
if (overflowZid != zINVALID_ZID)
|
|
{
|
|
deleteBeast = prevBeast;
|
|
}
|
|
else
|
|
{
|
|
deleteBeast = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
releasePrevious = TRUE;
|
|
for (entry=0; entry < deleteBeast->p.numEntries; entry++)
|
|
{
|
|
if (LB_GUIDCompare(&deleteBeast->acl[entry].trusteeID, trusteeID) == 0)
|
|
{
|
|
aclEntry = &deleteBeast->acl[entry];
|
|
forceDeleteBeast = TRUE;
|
|
goto findLast;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* could not find trustee */
|
|
SetErrno(genMsg, zERR_TRUSTEE_NOT_FOUND);
|
|
status = zFAILURE;
|
|
goto cleanup;
|
|
|
|
findLast:
|
|
/* return the rights for the trustee being deleted */
|
|
*rights = aclEntry->rights;
|
|
|
|
/*
|
|
* Find the last beast in the list of overflow beasts. The
|
|
* previous beast in the list must also be found in case we need to
|
|
* unlink it.
|
|
*/
|
|
lastBeast = deleteBeast;
|
|
while (overflowZid != zINVALID_ZID)
|
|
{ /* find the last beast */
|
|
BOOL sameBeast;
|
|
|
|
if (prevBeast != NULL && prevBeast != deleteBeast && releasePrevious)
|
|
{
|
|
COMN_UnlatchAndRelease(&prevBeast, XLATCHED);
|
|
sameBeast = FALSE;
|
|
}
|
|
else
|
|
{
|
|
sameBeast = TRUE;
|
|
}
|
|
prevBeast = lastBeast;
|
|
lastBeast = ZAS_LookupOverflowBeast(genMsg, authBeast->AUTHvolume,
|
|
overflowZid, XLATCHED, zFTYPE_ZAS_ACL_OVERFLOW);
|
|
if (lastBeast == NULL)
|
|
{ /* error */
|
|
/* Treat the last good beast as if it were the last beast */
|
|
if (lastGoodZid != zINVALID_ZID)
|
|
{
|
|
if (sameBeast)
|
|
{
|
|
lastBeast = deleteBeast;
|
|
}
|
|
else
|
|
{
|
|
lastBeast = COMN_LookupByZid(genMsg, authBeast->AUTHvolume,
|
|
lastGoodZid, XLATCHED, FALSE);
|
|
if (lastBeast == NULL)
|
|
{
|
|
/*
|
|
* This should never happen since we just found this beast on
|
|
* the last loop through.
|
|
*/
|
|
status = zFAILURE;
|
|
goto cleanup;
|
|
}
|
|
}
|
|
lastBeast->p.nextOverflowZid = zINVALID_ZID;
|
|
}
|
|
else
|
|
{
|
|
authInfo->p.trusteeOverflow = zINVALID_ZID;
|
|
}
|
|
overflowZid = zINVALID_ZID;
|
|
break;
|
|
}
|
|
lastGoodZid = overflowZid;
|
|
|
|
#if (CURRENT_BEAST_VERSION != BEAST_VERSION_3)
|
|
#error "Check to see if the beastVersion code below is still needed."
|
|
#endif
|
|
/* BEGINNING OF BEAST VERSION ONE CONVERSION CODE */
|
|
if (ZAS_ConvertACLFromVersionOne(genMsg, lastBeast) != zOK)
|
|
{
|
|
COMN_UnlatchAndRelease(&lastBeast, XLATCHED);
|
|
status = zFAILURE;
|
|
goto cleanup;
|
|
}
|
|
/* END OF BEAST VERSION ONE CONVERSION CODE */
|
|
|
|
overflowZid = lastBeast->p.nextOverflowZid;
|
|
if (lastBeast->p.numEntries == 0)
|
|
{
|
|
releasePrevious = FALSE;
|
|
ZAS_RemoveOverflowBeast(genMsg, lastBeast, prevBeast, authInfo,
|
|
&forceMainBeast, xaction);
|
|
lastBeast = prevBeast;
|
|
}
|
|
else
|
|
{
|
|
releasePrevious = TRUE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Delete the entry by taking the last entry in the last beast and moving
|
|
* it to the deleted location.
|
|
*/
|
|
|
|
if (deleteBeast == NULL && lastBeast == NULL)
|
|
{ /* if there are no overflow records - just working on main beast*/
|
|
ZAS_DELETE_ENTRY(authInfo->p.numTrusteesAssigned, aclEntry,
|
|
authInfo->p.ACL);
|
|
forceMainBeast = TRUE;
|
|
}
|
|
else
|
|
{ /* moving entry from overflow to main */
|
|
ZAS_DELETE_ENTRY(lastBeast->p.numEntries, aclEntry, lastBeast->acl);
|
|
/*
|
|
* If the last beast is empty then get rid of it unless it was already
|
|
* reset to the previous because the "old" last beast was removed
|
|
* because it had no entries. In this case the previous beast
|
|
* was used as the last beast and we have lost track of the beast
|
|
* previous to that so we cannot remove the "new" last beast.
|
|
*/
|
|
if ((lastBeast->p.numEntries == 0) &&
|
|
(lastBeast != prevBeast))
|
|
{ /* if the last beast is empty get rid of it. */
|
|
ZAS_RemoveOverflowBeast(genMsg, lastBeast, prevBeast, authInfo,
|
|
&forceMainBeast, xaction);
|
|
if (deleteBeast == lastBeast)
|
|
{
|
|
forceDeleteBeast = FALSE;
|
|
deleteBeast = NULL;
|
|
}
|
|
lastBeast = NULL;
|
|
}
|
|
else
|
|
{
|
|
if (deleteBeast != lastBeast)
|
|
{ /* if the beast we are deleting from and the last beast are not the same then write */
|
|
COMN_MARK_BEAST_XLOCAL(&lastBeast->ACLOroot, xaction);
|
|
if (COMN_ForceBeastWrite(genMsg, lastBeast, xaction) != zOK)
|
|
{
|
|
status = zFAILURE;
|
|
goto cleanup;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!(authBeast->AUTHattributes & zFA_ATTR_ARCHIVE))
|
|
{
|
|
authBeast->AUTHattributes |= zFA_ATTR_ARCHIVE;
|
|
forceMainBeast = TRUE;
|
|
}
|
|
|
|
if ((modifyMetaDataTime) && (COMN_IsDerivedFrom(authBeast, zFTYPE_FILE)))
|
|
{
|
|
File_s *file = (File_s *)authBeast;
|
|
file->FILEmetaDataModifiedTime = GetUTCTime();
|
|
forceMainBeast = TRUE;
|
|
}
|
|
|
|
if (forceMainBeast)
|
|
{
|
|
authInfo->flags |= ZAS_ALLOW_FORCED_WRITE;
|
|
COMN_MARK_BEAST_XLOCAL(&authBeast->AUTHroot, xaction);
|
|
if (COMN_ForceBeastWrite(genMsg, authBeast, xaction) != zOK)
|
|
{
|
|
status = zFAILURE;
|
|
authInfo->flags &= ~ZAS_ALLOW_FORCED_WRITE;
|
|
goto cleanup;
|
|
}
|
|
authInfo->flags &= ~ZAS_ALLOW_FORCED_WRITE;
|
|
}
|
|
if (forceDeleteBeast)
|
|
{
|
|
COMN_MARK_BEAST_XLOCAL(&deleteBeast->ACLOroot, xaction);
|
|
if (COMN_ForceBeastWrite(genMsg, deleteBeast, xaction) != zOK)
|
|
{
|
|
status = zFAILURE;
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
cleanup:
|
|
if (deleteBeast != NULL &&
|
|
deleteBeast != lastBeast &&
|
|
deleteBeast != prevBeast)
|
|
{
|
|
COMN_UnlatchAndRelease(&deleteBeast, XLATCHED);
|
|
}
|
|
if (lastBeast != NULL &&
|
|
lastBeast != prevBeast)
|
|
{
|
|
COMN_UnlatchAndRelease(&lastBeast, XLATCHED);
|
|
}
|
|
if (prevBeast != NULL)
|
|
{
|
|
COMN_UnlatchAndRelease(&prevBeast, XLATCHED);
|
|
}
|
|
RTN_STATUS(status);
|
|
}
|
|
|
|
/****************************************************************************
|
|
*
|
|
* This routine will remove trustee and rights from a file system object.
|
|
* This function assumes that auth latch is already held.
|
|
*
|
|
****************************************************************************/
|
|
STATUS ZAS_RemoveLatchedACLEntry(
|
|
GeneralMsg_s *genMsg,
|
|
AuthBeast_s *authBeast,
|
|
UserID_t *trusteeID,
|
|
NINT purgedFileFlag,
|
|
Xaction_s *xaction)
|
|
/* FixFixFix6 --
|
|
* need to do the right thing when files are going to salvage */
|
|
{
|
|
ZASAuthorizeInfo_s *authInfo;
|
|
Xaction_s *localXaction;
|
|
NINT rights;
|
|
Zid_t hlZid;
|
|
HardLinkBeast_s *hlBeast;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
authInfo = authBeast->AUTHauthInfo.zas;
|
|
|
|
/* begin the transaction for removing an ACL */
|
|
if (xaction == NULL)
|
|
{
|
|
zASSERT(!(authBeast->AUTHbstState & BST_STATE_XLOCAL));
|
|
localXaction = COMN_BeginXLocal(authBeast);
|
|
}
|
|
else
|
|
{
|
|
localXaction = xaction;
|
|
}
|
|
if (ZAS_RemoveTrustee(genMsg, authBeast, trusteeID, &rights,
|
|
localXaction) != zOK)
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
/*
|
|
* Remove visibility if the trustee was giving some type of rights.
|
|
*/
|
|
if (rights)
|
|
{
|
|
/*
|
|
* If this is a hardlink primary beast, we need to add/remove visibility
|
|
* for all parents, not just the first parent.
|
|
*/
|
|
if ((authBeast->AUTHhardLinkZid != zINVALID_ZID) &&
|
|
!(authBeast->AUTHattributes & zFA_HARDLINK))
|
|
{
|
|
for (hlZid = authBeast->AUTHhardLinkZid; hlZid != zINVALID_ZID; )
|
|
{
|
|
hlBeast = COMN_LookupByZid(genMsg,authBeast->AUTHvolume,hlZid,
|
|
NOTLATCHED,TRUE);
|
|
if (hlBeast != NULL)
|
|
{
|
|
ZAS_RemoveVisibility(genMsg, localXaction, authBeast,
|
|
hlBeast->HARDLfirstParentZid, trusteeID, 1, TRUE);
|
|
|
|
hlZid = hlBeast->HARDLhardLinkZid;
|
|
COMN_Release(&hlBeast);
|
|
}
|
|
else
|
|
{
|
|
zASSERT("Broken hard link chain"==NULL);
|
|
hlZid = zINVALID_ZID;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
zASSERT(!(authBeast->AUTHattributes & zFA_HARDLINK));
|
|
|
|
ZAS_RemoveVisibility(genMsg, localXaction, authBeast,
|
|
authBeast->AUTHfirstParentZid, trusteeID, 1, TRUE);
|
|
}
|
|
}
|
|
|
|
if (!(authBeast->AUTHattributes & zFA_SUBDIRECTORY) ||
|
|
authBeast->AUTHcomnOps.BST_isDirectoryEmpty(genMsg, &authBeast->AUTHnamed, zNTYPE_FILE))
|
|
{ /* this object has no objects below it */
|
|
authInfo->p.cacheIndex = INVALID_EACL_CACHE_INDEX; /* invalidate the cache pointer */
|
|
}
|
|
else
|
|
{
|
|
ZAS_InvalidateEACLCacheEntries(genMsg, trusteeID, TRUE);
|
|
}
|
|
authInfo->flags |= ZAS_ALLOW_FORCED_WRITE;
|
|
VOL_insertEFLEntry(genMsg, &authBeast->AUTHroot,
|
|
EFL_FILE_STATE_MODIFY_METADATA, NULL, localXaction);
|
|
authInfo->flags &= ~ZAS_ALLOW_FORCED_WRITE;
|
|
|
|
if (xaction == NULL)
|
|
{
|
|
COMN_EndXLocal(authBeast, &localXaction);
|
|
}
|
|
return zOK;
|
|
|
|
cleanup:
|
|
if (xaction == NULL)
|
|
{
|
|
COMN_EndXLocal(authBeast, &localXaction);
|
|
}
|
|
return zFAILURE;
|
|
}
|
|
|
|
/****************************************************************************
|
|
*
|
|
* This routine will remove trustee and rights from a file system object
|
|
*
|
|
****************************************************************************/
|
|
STATUS ZAS_RemoveACLEntry(
|
|
GeneralMsg_s *genMsg,
|
|
AuthBeast_s *authBeast,
|
|
UserID_t *trusteeID,
|
|
NINT purgedFileFlag)
|
|
/* FixFixFix6 --
|
|
* need to do the right thing when files are going to salvage */
|
|
{
|
|
ZASAuthorizeInfo_s *authInfo;
|
|
STATUS status = zFAILURE;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
ENTER(TAUTH, ZAS_RemoveACLEntry);
|
|
|
|
/* Defect #306666. We can't allow unlicensed connection access */
|
|
if (!ConnectionIsLoggedIn(genMsg->pssConn.id))
|
|
{
|
|
/* They are not logged in (LICENCED), so limit their access */
|
|
SetErrno(genMsg, zERR_NO_TRUSTEE_CHANGE_PRIVILEGE);
|
|
goto cleanupError;
|
|
}
|
|
|
|
if (authBeast->AUTHvolume->VOLenabledAttributes & zATTR_READONLY)
|
|
{
|
|
SetErrno(genMsg, zERR_VOLUME_READ_ONLY);
|
|
return zFAILURE;
|
|
}
|
|
|
|
authInfo = authBeast->AUTHauthInfo.zas;
|
|
X_LATCH(&authInfo->authLatch);
|
|
|
|
status = ZAS_RemoveLatchedACLEntry(genMsg, authBeast, trusteeID,
|
|
purgedFileFlag, NULL);
|
|
|
|
UNX_LATCH(&authInfo->authLatch);
|
|
|
|
cleanupError:
|
|
RTN_STATUS(status);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* This routine will return the effective rights for a beast using the
|
|
* IDs in the connection structure.
|
|
****************************************************************************/
|
|
STATUS ZAS_GetEffectiveRights(
|
|
GeneralMsg_s *genMsg,
|
|
AuthBeast_s *authBeast,
|
|
Zid_t parentZID,
|
|
NINT *effectiveRights)
|
|
{
|
|
NSSConnection_s *pssConn;
|
|
STATUS status;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
ENTER(TAUTH, ZAS_GetEffectiveRights);
|
|
|
|
if ((pssConn = CNCT_RESOLVE_CONNECTION(genMsg)) == NULL)
|
|
RTN_STATUS(zFAILURE);
|
|
|
|
// Removed because supervisor should not be able to see directories that are
|
|
// marked for connection zero only
|
|
//
|
|
// if (pssConn->privileges & SUPERVISOR)
|
|
// { /* if the connection has supervisor privilege allow all rights */
|
|
// *effectiveRights = -1;
|
|
// RTN_STATUS(zOK);
|
|
// }
|
|
|
|
/*
|
|
* NDS can call back into the file system while it is resolving a
|
|
* connection. In this case the authListLatch is already held and we
|
|
* will deadlock. To avoid this we check to see we are on connection
|
|
* zero and if the condition exist that would indicate we are trying
|
|
* to resolve this connection. If so we give it rights to continue.
|
|
*/
|
|
if ((genMsg->pssConn.id == zSYS_CONNECTION) &&
|
|
IS_XLATCHED(&pssConn->authInfo.authListLatch) &&
|
|
(CNCT_LatchingConnection == zSYS_CONNECTION))
|
|
{
|
|
*effectiveRights = zVALID_TRUSTEE_RIGHTS;
|
|
RTN_STATUS(zOK);
|
|
}
|
|
S_LATCH(&genMsg->pssConn.ptr->authInfo.authListLatch);
|
|
status = ZAS_GetEffectiveRightsByIDs(genMsg, authBeast, parentZID,
|
|
(genMsg->pssConn.ptr->flags & CNCTFL_SECURE_ACCESS) ? TRUE : FALSE,
|
|
IsSupervisor(genMsg->pssConn.id),
|
|
genMsg->pssConn.ptr->authInfo.numAuthenticatedIDs,
|
|
&genMsg->pssConn.ptr->authInfo.authenticatedIDs[0],
|
|
effectiveRights);
|
|
UNS_LATCH(&genMsg->pssConn.ptr->authInfo.authListLatch);
|
|
RTN_STATUS(status);
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* Re-create the visibility lists
|
|
****************************************************************************/
|
|
void ZAS_RebuildVisibilityLists(
|
|
GeneralMsg_s *genMsg,
|
|
Volume_s *vol,
|
|
Zid_t *zidArray,
|
|
NINT numArrayEntries,
|
|
VisRebuildStats_s *stats,
|
|
unicode_t *name)
|
|
{
|
|
Zid_t startingZid = 0;
|
|
NINT numReturnedZids;
|
|
RootBeast_s *beast;
|
|
NINT index;
|
|
QUAD totalBeasts;
|
|
STATUS status;
|
|
Zid_t hlZid;
|
|
HardLinkBeast_s *hlBeast;
|
|
|
|
/*
|
|
* Go through the entire beast tree and re-add all trustees
|
|
*/
|
|
aprintf(YELLOW,
|
|
MSG("Visbility rebuild: Rebuilding visiblity information on %U\n", 206),
|
|
name);
|
|
totalBeasts = 0;
|
|
vol->VOLzidInProcess = 0;
|
|
vol->v_statusFlag |= VOL_SF_CLEAN_VIS_REBUILD;
|
|
do
|
|
{
|
|
/*
|
|
* Check to see if someone is wanting to deactivate the volume.
|
|
* If so we stop our thread so the volume can be deactivated.
|
|
*/
|
|
if (vol->v_statusFlag & VOL_SF_LEAVING_ACTIVE_STATE_CLEANUP)
|
|
{
|
|
aprintf(LRED,
|
|
MSG("STOPPING VISIBILITY REBUILD ON %U BECAUSE OF VOLUME DEACTIVATE\n", 241),
|
|
name);
|
|
goto exit;
|
|
}
|
|
|
|
if (vol->VOLcomnVolOps.VOL_browseBeastsInVolume(genMsg,
|
|
vol, SELECT_BEASTS_ALL, numArrayEntries, &startingZid, zidArray,
|
|
&numReturnedZids) != zOK)
|
|
{
|
|
aprintf(LRED, MSG("Visibility rebuild on volume %U:\n"
|
|
"Error %d getting object list while adding visibility.\n", 244),
|
|
name, GetErrno(genMsg));
|
|
goto exit;
|
|
}
|
|
|
|
/* Process each entry */
|
|
for (index = 0; index < numReturnedZids; index++)
|
|
{
|
|
totalBeasts++;
|
|
if (!(totalBeasts % 10000))
|
|
{
|
|
aprintf(LGREEN,
|
|
"(%U) Visibility rebuild pass 2: %Ld objects processed\n",
|
|
name, totalBeasts);
|
|
}
|
|
vol->VOLzidInProcess = zidArray[index];
|
|
if ((beast = COMN_LookupByZid(genMsg, vol,
|
|
zidArray[index], SLATCHED, TRUE)) == NULL)
|
|
{
|
|
zASSERT(GetErrno(genMsg) != 20000);
|
|
/*
|
|
* Only report an error if it not one of errors we know
|
|
* can happen because of timing with beast delete.
|
|
*/
|
|
if (GetErrno(genMsg) != zERR_INVALID_BEAST_ID &&
|
|
GetErrno(genMsg) != zERR_INVALID_BEAST_ID)
|
|
{
|
|
aprintf(LRED, MSG("Visibility rebuild on volume %U:\n"
|
|
"Error %d looking up an object. ZID[%d]=%Ld\n", 247),
|
|
name, GetErrno(genMsg), index, zidArray[index]);
|
|
}
|
|
ClearErrno(genMsg);
|
|
continue;
|
|
}
|
|
|
|
/*
|
|
* If this is a normal file/dir then processes any trustees
|
|
*/
|
|
if ((COMN_IsDerivedFrom(beast, zFTYPE_FILE)) &&
|
|
(!(((File_s *)beast)->FILEattributes & zFA_HARDLINK)))
|
|
{
|
|
/*
|
|
* If this is a hardlink primary beast, we need to add/remove visibility
|
|
* for all parents, not just the first parent.
|
|
*/
|
|
if (((File_s *)beast)->FILEhardLinkZid != zINVALID_ZID)
|
|
{
|
|
for (hlZid = ((File_s *)beast)->FILEhardLinkZid; hlZid != zINVALID_ZID; )
|
|
{
|
|
hlBeast = COMN_LookupByZid(genMsg,beast->ROOTvolume,
|
|
hlZid,NOTLATCHED,TRUE);
|
|
if (hlBeast != NULL)
|
|
{
|
|
if ((status = ZAS_AddBeastVisibility(genMsg,
|
|
(AuthBeast_s *)beast, ((File_s *)hlBeast)->FILEfirstParentZid,
|
|
FALSE, stats, FALSE)) != zOK)
|
|
{
|
|
aprintf(LRED, MSG("Visibility rebuild on volume %U:\n"
|
|
"Error %d looking up an object while adding visibility.\n",249),
|
|
name, GetErrno(genMsg));
|
|
|
|
}
|
|
|
|
hlZid = hlBeast->HARDLhardLinkZid;
|
|
COMN_Release(&hlBeast);
|
|
}
|
|
else
|
|
{
|
|
zASSERT("Broken hard link chain"==NULL);
|
|
hlZid = zINVALID_ZID;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((status = ZAS_AddBeastVisibility(genMsg,
|
|
(AuthBeast_s *)beast, ((File_s *)beast)->FILEfirstParentZid,
|
|
FALSE, stats, FALSE)) != zOK)
|
|
{
|
|
aprintf(LRED, MSG("Visibility rebuild on volume %U:\n"
|
|
"Error %d looking up an object while adding visibility.\n", 249),
|
|
name, GetErrno(genMsg));
|
|
}
|
|
}
|
|
}
|
|
COMN_UnlatchAndRelease(&beast, SLATCHED);
|
|
}
|
|
} while (numReturnedZids > 0);
|
|
|
|
exit:
|
|
vol->v_statusFlag &= ~VOL_SF_CLEAN_VIS_REBUILD;
|
|
ClearErrno(genMsg);
|
|
return;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* The thread to rebuild the visibility list for the given volume
|
|
****************************************************************************/
|
|
void ZAS_VisibilityRebuildThread(
|
|
FsmLite_s *fsm,
|
|
VisRebParms_s *parms)
|
|
{
|
|
enum
|
|
{
|
|
NUM_REQUESTED_ZIDS = 100
|
|
};
|
|
|
|
GeneralMsg_s genMsg;
|
|
Zid_t startingZid = 0;
|
|
Zid_t *zidArray;
|
|
NINT numReturnedZids;
|
|
RootBeast_s *beast;
|
|
NINT index;
|
|
Xaction_s *xaction;
|
|
ZASAuthorizeInfo_s *authInfo;
|
|
VisRebuildStats_s stats;
|
|
QUAD totalBeasts;
|
|
Volume_s *vol = parms->vol;
|
|
|
|
COMN_SETUP_GENERAL_MSG_NOSA(&genMsg);
|
|
|
|
COMN_LockVolumeActive(&genMsg, vol, FALSE);
|
|
zidArray = malloc(NUM_REQUESTED_ZIDS * sizeof(Zid_t));
|
|
if (zidArray == NULL)
|
|
{
|
|
aprintf(LRED,
|
|
MSG("Visibility rebuild on volume %U:\n"
|
|
"Unable to get enough memory to complete the rebuild.\n", 250),
|
|
parms->name);
|
|
goto exit;
|
|
}
|
|
|
|
stats.VisNumBeasts = 0;
|
|
stats.VisNumOverflowRemoved = 0;
|
|
stats.VisNumFilesCleaned = 0;
|
|
stats.VisNumTrusteesProcessed = 0;
|
|
|
|
/*
|
|
* Go through the entire beast tree and remove all visibility information.
|
|
*/
|
|
aprintf(YELLOW,
|
|
MSG("Visibility rebuild: Removing visiblity information from %U\n", 251),
|
|
parms->name);
|
|
totalBeasts = 0;
|
|
do
|
|
{
|
|
/*
|
|
* Check to see if someone is wanting to deactivate the volume.
|
|
* If so we stop our thread so that the volume can be deactivated.
|
|
*/
|
|
if (vol->v_statusFlag & VOL_SF_LEAVING_ACTIVE_STATE_CLEANUP)
|
|
{
|
|
aprintf(LRED,
|
|
MSG("STOPPING VISIBILITY REBUILD ON %U BECAUSE OF VOLUME DEACTIVATE\n", 252),
|
|
parms->name);
|
|
goto exitStats;
|
|
}
|
|
if (vol->VOLcomnVolOps.VOL_browseBeastsInVolume(&genMsg,
|
|
vol, SELECT_BEASTS_ALL, NUM_REQUESTED_ZIDS,
|
|
&startingZid, zidArray, &numReturnedZids) != zOK)
|
|
{
|
|
aprintf(LRED,
|
|
MSG("Visibility rebuild on volume %U:\n"
|
|
"Error %d getting object list.\n", 253), parms->name,
|
|
GetErrno(&genMsg));
|
|
goto exitFreeMem;
|
|
}
|
|
/* Process each entry */
|
|
for (index = 0; index < numReturnedZids; index++)
|
|
{
|
|
totalBeasts++;
|
|
if (!(totalBeasts % 10000))
|
|
{
|
|
aprintf(LGREEN,
|
|
"(%U) Visibility rebuild pass 1: %Ld objects processed\n",
|
|
parms->name, totalBeasts);
|
|
}
|
|
if ((beast = COMN_LookupByZid(&genMsg, vol,
|
|
zidArray[index], XLATCHED, TRUE)) == NULL)
|
|
{
|
|
zASSERT(GetErrno(&genMsg) != 20000);
|
|
aprintf(LRED, MSG("Visibility rebuild on volume %U:\n"
|
|
"Error %d looking up an object. ZID[%d]=%Ld\n", 254),
|
|
parms->name, GetErrno(&genMsg), index, zidArray[index]);
|
|
ClearErrno(&genMsg);
|
|
continue;
|
|
}
|
|
|
|
stats.VisNumBeasts++;
|
|
|
|
/*
|
|
* If this is a visibility overflow beast then just get rid of it.
|
|
*/
|
|
if (beast->ROOTbeastClass->classID == zFTYPE_ZAS_VIS_OVERFLOW)
|
|
{
|
|
xaction = COMN_BeginXLocal(beast);
|
|
if (BST_delete(&genMsg, NULL, beast, NULL, NULL, xaction,
|
|
FALSE, TRUE) != zOK)
|
|
{
|
|
ClearErrno(&genMsg);
|
|
zASSERT("Failed to delete trustee overflow beast"==NULL);
|
|
}
|
|
COMN_EndXLocal(beast, &xaction);
|
|
COMN_UnlatchAndRelease(&beast, XLATCHED);
|
|
stats.VisNumOverflowRemoved++;
|
|
continue;
|
|
}
|
|
|
|
/*
|
|
* If this is a normal file/dir then get rid of the visibility
|
|
* information.
|
|
*/
|
|
if (COMN_IsDerivedFrom(beast, zFTYPE_FILE))
|
|
{
|
|
authInfo = ((AuthBeast_s *)beast)->AUTHauthInfo.zas;
|
|
/* If there are visibility entries then clear them */
|
|
if (authInfo->p.numVisibilityTrusteesAssigned ||
|
|
authInfo->p.visibilityOverflow)
|
|
{
|
|
zASSERT(!authInfo->p.visibilityOverflow ||
|
|
authInfo->p.numVisibilityTrusteesAssigned == 4);
|
|
authInfo->p.numVisibilityTrusteesAssigned = 0;
|
|
authInfo->p.visibilityOverflow = zINVALID_ZID;
|
|
xaction = COMN_BeginXLocal(beast);
|
|
COMN_MARK_BEAST_XLOCAL(beast, xaction);
|
|
COMN_ForceBeastWrite(&genMsg, beast, xaction);
|
|
COMN_EndXLocal(beast, &xaction);
|
|
stats.VisNumFilesCleaned++;
|
|
}
|
|
}
|
|
COMN_UnlatchAndRelease(&beast, XLATCHED);
|
|
}
|
|
} while (numReturnedZids > 0);
|
|
|
|
/* Rebuild the visibility lists */
|
|
ZAS_RebuildVisibilityLists(&genMsg, vol, zidArray, NUM_REQUESTED_ZIDS,
|
|
&stats, parms->name);
|
|
|
|
exitStats:
|
|
aprintf(LCYAN, MSG( "Visibility rebuild finished on volume %U\n"
|
|
"Objects examined: %Ld\n"
|
|
"Objects cleaned: %Ld\n"
|
|
"Overflow objects removed: %Ld\n"
|
|
"Trustees re-added: %Ld\n", 255),
|
|
parms->name,
|
|
stats.VisNumBeasts,
|
|
stats.VisNumFilesCleaned,
|
|
stats.VisNumOverflowRemoved,
|
|
stats.VisNumTrusteesProcessed);
|
|
|
|
exitFreeMem:
|
|
free(zidArray);
|
|
exit:
|
|
vol->v_statusFlag &= ~VOL_SF_CLEAN_VIS_SCHEDULED;
|
|
COMN_UnlockVolumeActive(vol, FALSE);
|
|
free(parms);
|
|
free(fsm);
|
|
return;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* Rebuild the visibility list for the given volume
|
|
****************************************************************************/
|
|
void ZAS_VisibilityRebuild(
|
|
GeneralMsg_s *genMsg,
|
|
Volume_s *vol,
|
|
unicode_t *name)
|
|
{
|
|
VisRebParms_s *parms;
|
|
FsmLite_s *fsm;
|
|
#if NSS_DEBUG IS_ENABLED
|
|
STATIC NINT fsmInstance = 0;
|
|
#endif
|
|
|
|
|
|
if (vol->state != zVOLSTATE_ACTIVE)
|
|
{
|
|
aprintf(LRED, MSG("Volume %U must be active to "
|
|
"rebuild visibility.\n", 297), name);
|
|
goto exit;
|
|
}
|
|
|
|
/* Check to see if thes volume has the ZAS auth model running on it */
|
|
|
|
if (vol->p.authModelID != zFTYPE_ZAS_AUTH_MODEL)
|
|
{
|
|
aprintf(LRED, MSG("Volume %U does not use visibility lists\n", 298),
|
|
name);
|
|
goto exit;
|
|
}
|
|
|
|
/* Check to see if it is already running */
|
|
if (vol->VOLv_statusFlag & VOL_SF_CLEAN_VIS_SCHEDULED)
|
|
{ /* There is already one running */
|
|
aprintf(LRED, MSG("Volume %U is already rebuilding visibility.\n", 299),
|
|
name);
|
|
goto exit;
|
|
}
|
|
vol->v_statusFlag |= VOL_SF_CLEAN_VIS_SCHEDULED;
|
|
|
|
/* Start up a seperate thread to do the processing */
|
|
fsm = malloc(sizeof(FsmLite_s));
|
|
if (fsm == NULL)
|
|
{
|
|
aprintf(LRED, MSG("Not enough memory to start visibility rebuild\n",
|
|
300));
|
|
vol->v_statusFlag &= ~VOL_SF_CLEAN_VIS_SCHEDULED;
|
|
goto exit;
|
|
}
|
|
|
|
/* Setup parameters for thread */
|
|
parms = malloc(sizeof(VisRebParms_s));
|
|
if (parms == NULL)
|
|
{
|
|
aprintf(LRED, MSG("Not enough memory to start visibility rebuild\n",
|
|
301));
|
|
vol->v_statusFlag &= ~VOL_SF_CLEAN_VIS_SCHEDULED;
|
|
free(fsm);
|
|
goto exit;
|
|
}
|
|
|
|
parms->vol = vol;
|
|
unicpy(parms->name, name);
|
|
|
|
FSMLITE_INIT(fsm, "FSM for visibility rebuild ", ++fsmInstance);
|
|
WORK_Schedule(fsm, ZAS_VisibilityRebuildThread, (ADDR)parms);
|
|
aprintf(WHITE,
|
|
MSG("Visibility rebuild started on volume \"%U\".\n",302), name);
|
|
|
|
exit:
|
|
ClearErrno(genMsg);
|
|
return;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Process command line to start rebuilding of a volumes visibility list.
|
|
****************************************************************************/
|
|
void ZAS_VisibilityRebuildByName(
|
|
GeneralMsg_s *genMsg,
|
|
unicode_t *name)
|
|
{
|
|
Volume_s *vol;
|
|
Volume_s *adminVol;
|
|
typedef struct Stack_s {
|
|
unicode_t volName[zMAX_COMPONENT_NAME];
|
|
} Stack_s;
|
|
STACK_ALLOC();
|
|
|
|
adminVol = COMN_GetAdminVolume();
|
|
/*
|
|
* See if doing ALL volumes
|
|
*/
|
|
if (uniicmp(name, MSGNot(L"all")) == 0)
|
|
{
|
|
DQ_FOREACH(&NSSMasterVolumeList, vol, Volume_s, masterVolLink)
|
|
{
|
|
if (vol != adminVol) /* skip the ADMIN volume */
|
|
{
|
|
COMN_GetVolumeName(genMsg, vol, aStack->volName, sizeof(aStack->volName));
|
|
COMN_USE_BEAST(&vol->VOLroot);
|
|
(void)ZAS_VisibilityRebuild(genMsg, vol, aStack->volName);
|
|
BST_UNUSE_BEAST(&vol->VOLroot);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Change the given volume
|
|
*/
|
|
vol = COMN_VolumeNameLookup(genMsg, name, FALSE, NULL);
|
|
if (vol == NULL)
|
|
{
|
|
errPrintf(WHERE, Module, 0,
|
|
MSG("Volume %U not found. Check your spelling and type NSS /volumes.\n", 303), name);
|
|
STACK_FREE();
|
|
return;
|
|
}
|
|
|
|
|
|
if (vol == adminVol)
|
|
{
|
|
BST_UNUSE_BEAST(&vol->VOLroot);
|
|
STACK_FREE();
|
|
return;
|
|
}
|
|
|
|
ZAS_VisibilityRebuild(genMsg, vol, name);
|
|
BST_UNUSE_BEAST(&vol->VOLroot); /* remove useCount added by lookup*/
|
|
}
|
|
STACK_FREE();
|
|
return;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* This routine will return the effective rights for a beast using the
|
|
* IDs in the connection structure.
|
|
****************************************************************************/
|
|
STATUS ZAS_GetParentsEffectiveRights(
|
|
GeneralMsg_s *genMsg,
|
|
AuthBeast_s *authBeast,
|
|
Zid_t parentZID,
|
|
NINT *effectiveRights)
|
|
{
|
|
NSSConnection_s *pssConn;
|
|
AuthBeast_s *parentBeast;
|
|
STATUS status;
|
|
|
|
ENTER(TAUTH, ZAS_GetEffectiveRights);
|
|
|
|
if ((pssConn = CNCT_RESOLVE_CONNECTION(genMsg)) == NULL)
|
|
{
|
|
RTN_STATUS(zFAILURE);
|
|
}
|
|
|
|
// Removed because supervisor should not be able to see directories that are
|
|
// marked for connection zero only
|
|
//
|
|
// if ( IsSupervisor(genMsg->pssConn.id)
|
|
// { /* if the connection has supervisor privilege allow all rights */
|
|
// *effectiveRights = -1;
|
|
// RTN_STATUS(zOK);
|
|
// }
|
|
|
|
/* Open the parent */
|
|
if (parentZID != zINVALID_ZID)
|
|
{
|
|
parentBeast = (AuthBeast_s *)BEASTHASH_LookupByZid(genMsg,
|
|
authBeast->AUTHvolume, parentZID, NOTLATCHED);
|
|
if (parentBeast == NULL)
|
|
{
|
|
RTN_STATUS(zFAILURE);
|
|
}
|
|
}
|
|
else
|
|
{ /* at the root */
|
|
effectiveRights = 0; /* the root's parent has no rights */
|
|
RTN_STATUS(zOK);
|
|
}
|
|
parentZID = parentBeast->AUTHfirstParentZid;
|
|
|
|
/*
|
|
* NDS can call back into the file system while it is resolving a
|
|
* connection. In this case the authListLatch is already held and we
|
|
* will deadlock. To avoid this we check to see we are on connection
|
|
* zero and if the condition exist that would indicate we are trying
|
|
* to resolve this connection. If so we give it rights to continue.
|
|
*/
|
|
|
|
if ((genMsg->pssConn.id == zSYS_CONNECTION) &&
|
|
IS_XLATCHED(&pssConn->authInfo.authListLatch) &&
|
|
(CNCT_LatchingConnection == zSYS_CONNECTION))
|
|
{
|
|
*effectiveRights = zVALID_TRUSTEE_RIGHTS;
|
|
RTN_STATUS(zOK);
|
|
}
|
|
S_LATCH(&genMsg->pssConn.ptr->authInfo.authListLatch);
|
|
status = ZAS_GetEffectiveRightsByIDs(genMsg, parentBeast, parentZID,
|
|
(genMsg->pssConn.ptr->flags & CNCTFL_SECURE_ACCESS) ? TRUE : FALSE,
|
|
IsSupervisor(genMsg->pssConn.id),
|
|
genMsg->pssConn.ptr->authInfo.numAuthenticatedIDs,
|
|
&genMsg->pssConn.ptr->authInfo.authenticatedIDs[0],
|
|
effectiveRights);
|
|
UNS_LATCH(&genMsg->pssConn.ptr->authInfo.authListLatch);
|
|
COMN_Release(&parentBeast);
|
|
RTN_STATUS(status);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* This routine will return all the effective rights for a beast. If it is
|
|
* successful it returns a malloc'ed structure that must be freed by the caller.
|
|
****************************************************************************/
|
|
STATUS ZAS_GetEffectiveACL(
|
|
GeneralMsg_s *genMsg,
|
|
AuthBeast_s *authBeast,
|
|
Zid_t parentZID,
|
|
AuthCacheNode_s **effectiveACL,
|
|
BOOL canBlock,
|
|
BOOL *freeEACL)
|
|
{
|
|
AuthCacheNode_s *computedEACL;
|
|
AuthCacheNode_s *newEACL;
|
|
AuthCacheNode_s *newerEACL;
|
|
AuthBeast_s *beastMemory[BEAST_STACK_ALLOC_SIZE];
|
|
AuthBeast_s *(*beastStack)[];
|
|
STATUS status;
|
|
AuthBeast_s *parentBeast;
|
|
AuthBeast_s *originalBeast;
|
|
NINT stackPtr = 0;
|
|
NINT tempStackPtr;
|
|
NINT sequence;
|
|
UserID_t trusteeID;
|
|
NINT rights;
|
|
NINT attributes;
|
|
NINT index;
|
|
NINT numACLs;
|
|
NINT numACLslots;
|
|
NINT maxStackEntries = BEAST_STACK_ALLOC_SIZE;
|
|
NINT originalResetCount = 999;
|
|
BOOL freeEACLFlag = FALSE;
|
|
BOOL cacheLatched = FALSE;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
|
|
#if NSS_DEBUG IS_ENABLED
|
|
AuthERRequests++;
|
|
#endif
|
|
|
|
*effectiveACL = NULL;
|
|
*freeEACL = FALSE;
|
|
|
|
/*
|
|
* If this beast comes from the persistent admin volume but its zid
|
|
* is too low then we are getting its parent from the regular admin
|
|
* volume. Change the parent to the first parent of the beast.
|
|
*/
|
|
|
|
if ((authBeast->AUTHvolume == PersistAdminVolume) && (parentZID <
|
|
AVOL_FIRST_PERSISTENT_ZID))
|
|
{
|
|
parentZID = authBeast->AUTHfirstParentZid;
|
|
}
|
|
|
|
/*
|
|
* The beast must be latched when coming into this routine. It may be
|
|
* uplatched during part of the routine, but it will be returned to the
|
|
* same latch state it started at.
|
|
*/
|
|
|
|
beastStack = &beastMemory;
|
|
|
|
COMN_USE_BEAST(&authBeast->AUTHroot);
|
|
|
|
originalBeast = authBeast;
|
|
|
|
/*
|
|
* Search the full path (backwards) for the first beast with a valid
|
|
* effective ACL. If there is no effective ACL in a beast then push
|
|
* its ZID on the stack and keep looking.
|
|
*/
|
|
|
|
for(;;)
|
|
{
|
|
//X_LATCH(&authBeast->AUTHauthInfo.zas->authLatch);
|
|
X_LATCH(&AuthCache.latch);
|
|
originalResetCount = AuthCache.resetCount;
|
|
|
|
/*
|
|
* As a performance enhancement we first check if the
|
|
* beast's restartCount is still valid. If the Beast
|
|
* does not match the the activation count then the
|
|
* beast is 'old' and must not be in the cache.
|
|
*/
|
|
|
|
if ( authBeast->AUTHvolume->v_restartCount ==
|
|
authBeast->AUTHauthInfo.zas->p.restartCount )
|
|
{ /* Beast is at correct activation count so see if auth info is
|
|
* in the cache. */
|
|
computedEACL = ZAS_GetEACLCacheEntry(
|
|
authBeast->AUTHauthInfo.zas->p.cacheIndex,
|
|
authBeast->AUTHauthInfo.zas->p.signature);
|
|
}
|
|
else
|
|
{ /* Must init because this is used twice more */
|
|
computedEACL = NULL;
|
|
}
|
|
|
|
if (computedEACL != NULL)
|
|
{ /* found an effective ACL */
|
|
#if NSS_DEBUG IS_ENABLED
|
|
AuthERHits++;
|
|
#endif
|
|
//UNX_LATCH(&authBeast->AUTHauthInfo.zas->authLatch);
|
|
/*
|
|
* We can avoid doing this latch as long as we can be sure that
|
|
* we will not block while using computedEACL. Since the code
|
|
* that requires the latch is in the loop for processing
|
|
* stack entries, we should be able to avoid the latch if we are
|
|
* not going into that loop.
|
|
*/
|
|
// if (stackPtr > 0)
|
|
// {
|
|
// X_LATCH(&AuthCache.latch);
|
|
// cacheLatched = TRUE;
|
|
// }
|
|
COMN_Release(&authBeast);
|
|
cacheLatched = TRUE;
|
|
break; /* exit the loop */
|
|
}
|
|
UNX_LATCH(&AuthCache.latch);
|
|
//X_LATCH(&authBeast->AUTHauthInfo.zas->authLatch);
|
|
|
|
/* no EACL in the cache -- add to the stack */
|
|
ZAS_PUSH_BEAST(status, errorSet, authBeast, stackPtr, maxStackEntries,
|
|
beastMemory, beastStack);
|
|
|
|
if (parentZID != zINVALID_ZID)
|
|
{
|
|
parentBeast = (AuthBeast_s *)BEASTHASH_LookupByZid(genMsg,
|
|
authBeast->AUTHvolume, parentZID, NOTLATCHED);
|
|
if (parentBeast == NULL)
|
|
{
|
|
status = zERR_UNABLE_TO_OPEN_BEAST;
|
|
goto errorSet;
|
|
}
|
|
}
|
|
else
|
|
{ /* at the root */
|
|
zASSERT(authBeast->AUTHfirstParentZid == zINVALID_ZID ||
|
|
COMN_IsDerivedFrom(&authBeast->AUTHroot, zFTYPE_VOLUME));
|
|
break;
|
|
}
|
|
authBeast = parentBeast;
|
|
parentZID = authBeast->AUTHfirstParentZid;
|
|
}
|
|
|
|
/* compute effective ACLs for each beast on the stack and put them in
|
|
* the cache. */
|
|
|
|
tempStackPtr = stackPtr;
|
|
while (tempStackPtr > 0)
|
|
{ /* while there are entries on the ZID stack */
|
|
authBeast = (*beastStack)[--tempStackPtr];
|
|
numACLs = 0;
|
|
|
|
/* allocate a buffer for a new cache entry */
|
|
if (computedEACL == NULL)
|
|
{ /* did not find EACL -- don't put anything in the new one */
|
|
newEACL = malloc(sizeof(AuthCacheNode_s));
|
|
if (newEACL == NULL)
|
|
{ /* out of memory */
|
|
status = zERR_NO_MEMORY;
|
|
goto errorSet;
|
|
}
|
|
numACLslots = 1;
|
|
}
|
|
else
|
|
{
|
|
numACLslots = computedEACL->EACL.numEntries;
|
|
newEACL = (AuthCacheNode_s *)malloc(EACL_SIZE(numACLslots));
|
|
if (newEACL == NULL)
|
|
{ /* out of memory */
|
|
status = zERR_NO_MEMORY;
|
|
goto errorSet;
|
|
}
|
|
memcpy(newEACL, computedEACL, sizeof(AuthCacheNode_s) - sizeof(EffectiveACL_s));
|
|
|
|
/* apply the inherited rights mask and inheritance flags*/
|
|
for (index = 0; index < computedEACL->EACL.numEntries; index++)
|
|
{
|
|
if (computedEACL->EACL.entry[index].attributes &
|
|
zAUTHORIZE_INHERIT_DOWN)
|
|
{
|
|
newEACL->EACL.entry[numACLs].rights =
|
|
(computedEACL->EACL.entry[index].rights &
|
|
authBeast->AUTHauthInfo.zas->p.inheritedRightsMask) &
|
|
zVALID_TRUSTEE_RIGHTS; /* strip off special rights as well*/
|
|
if (newEACL->EACL.entry[numACLs].rights != 0)
|
|
{ /* if there are rights assigned */
|
|
newEACL->EACL.entry[numACLs].trusteeID =
|
|
computedEACL->EACL.entry[index].trusteeID;
|
|
newEACL->EACL.entry[numACLs].attributes =
|
|
computedEACL->EACL.entry[index].attributes;
|
|
numACLs++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (freeEACLFlag)
|
|
{ /* if the computed EACL has not been assigned to the cache then free it */
|
|
free(computedEACL);
|
|
freeEACLFlag = FALSE;
|
|
}
|
|
|
|
if (cacheLatched)
|
|
{
|
|
UNX_LATCH(&AuthCache.latch);
|
|
cacheLatched = FALSE;
|
|
}
|
|
|
|
newEACL->EACL.numEntries = numACLs;
|
|
/* FixFixFix6 -- check on multi-domain NDS considerations */
|
|
newEACL->domainID = 0;
|
|
|
|
/* merge in the ACLs from this beast */
|
|
/* FixFixFix6 -- have not considered negative ACLs */
|
|
sequence = 0;
|
|
while (sequence != -1)
|
|
{ /* while there are still ACL entries */
|
|
if (ZAS_GetAnACL(genMsg, authBeast, &sequence, &trusteeID, &rights,
|
|
&attributes) != zOK)
|
|
{
|
|
status = GetErrno(genMsg);
|
|
goto errorSet;
|
|
}
|
|
if (sequence == -1)
|
|
{ /* no more entries */
|
|
break;
|
|
}
|
|
/*
|
|
* If this is the special secure user then setup special rights.
|
|
*/
|
|
if (LB_GUIDCompare(&trusteeID, &zSECURE_CONNECTION_USERID) == 0)
|
|
{
|
|
rights |= (zAUTHORIZE_ACCESS_CONTROL | zAUTHORIZE_SECURE);
|
|
free(newEACL);
|
|
newEACL = malloc(sizeof(AuthCacheNode_s));
|
|
if (newEACL == NULL)
|
|
{ /* out of memory */
|
|
status = zERR_NO_MEMORY;
|
|
goto errorSet;
|
|
}
|
|
numACLs = 0;
|
|
index = 0;
|
|
numACLslots = 1;
|
|
sequence = -1; /* don't do any more */
|
|
}
|
|
else
|
|
{
|
|
for (index = 0; index < numACLs; index++)
|
|
{ /* search the current EACL entries */
|
|
if (LB_GUIDCompare(&newEACL->EACL.entry[index].trusteeID, &trusteeID) == 0)
|
|
{ /* The trustee is already in the effective ACL */
|
|
/* Don't lose supervisor rights */
|
|
newEACL->EACL.entry[index].rights &= zAUTHORIZE_SUPERVISOR;
|
|
newEACL->EACL.entry[index].rights |= rights;
|
|
newEACL->EACL.entry[index].attributes = attributes;
|
|
goto nextEntry;
|
|
}
|
|
else if (LB_GUIDCompare(&newEACL->EACL.entry[index].trusteeID, &trusteeID) > 0)
|
|
{ /* need to insert a new entry */
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**/
|
|
/* insert a new entry */
|
|
/**/
|
|
|
|
/* make more room to insert a new entry -- if we need to */
|
|
if (numACLs == numACLslots)
|
|
{
|
|
newerEACL = realloc(newEACL,
|
|
EACL_SIZE(numACLs + EACL_GROW_AMOUNT));
|
|
if (newerEACL == NULL)
|
|
{
|
|
free(newEACL);
|
|
status = zERR_NO_MEMORY;
|
|
goto errorSet;
|
|
}
|
|
newEACL = newerEACL;
|
|
numACLslots = numACLs + EACL_GROW_AMOUNT;
|
|
}
|
|
|
|
/* keep in sorted order */
|
|
if (index < numACLs)
|
|
{ /* need to insert, so shift the entries up by one */
|
|
memmove(&newEACL->EACL.entry[index+1],
|
|
&newEACL->EACL.entry[index],
|
|
sizeof(ACLEntry_s)*(numACLs-index));
|
|
}
|
|
newEACL->EACL.entry[index].trusteeID = trusteeID;
|
|
newEACL->EACL.entry[index].rights = rights;
|
|
newEACL->EACL.entry[index].attributes = attributes;
|
|
numACLs++;
|
|
nextEntry:
|
|
continue;
|
|
}
|
|
|
|
|
|
if (numACLs < numACLslots)
|
|
{
|
|
if (numACLs > 0)
|
|
{ /* if there are still some EACL entries */
|
|
/* resize the EACL to the needed size */
|
|
newerEACL = realloc(newEACL, EACL_SIZE(numACLs));
|
|
if (newerEACL == 0)
|
|
{
|
|
status = zERR_NO_MEMORY;
|
|
goto errorSet;
|
|
}
|
|
newEACL = newerEACL;
|
|
}
|
|
}
|
|
newEACL->EACL.numEntries = numACLs;
|
|
|
|
X_LATCH(&AuthCache.latch);
|
|
cacheLatched = TRUE;
|
|
if ((newerEACL = ZAS_AddEACLCacheEntry(newEACL, originalResetCount,
|
|
&authBeast->AUTHauthInfo.zas->p.cacheIndex)) != NULL)
|
|
{
|
|
authBeast->AUTHauthInfo.zas->p.signature = newerEACL->signature;
|
|
authBeast->AUTHauthInfo.zas->p.restartCount =
|
|
authBeast->AUTHvolume->v_restartCount;
|
|
freeEACLFlag = FALSE;
|
|
computedEACL = newerEACL;
|
|
}
|
|
else
|
|
{
|
|
authBeast->AUTHauthInfo.zas->p.cacheIndex = INVALID_EACL_CACHE_INDEX;
|
|
freeEACLFlag = TRUE;
|
|
computedEACL = newEACL;
|
|
}
|
|
}
|
|
if (cacheLatched)
|
|
{
|
|
#if NSS_DEBUG IS_ENABLED
|
|
AuthERImmediateHits++;
|
|
#endif
|
|
UNX_LATCH(&AuthCache.latch);
|
|
cacheLatched = FALSE;
|
|
}
|
|
|
|
/*
|
|
* If the computed EACL has not been assigned to cache then pass it
|
|
* back to the caller. If it is assigned to the cache and the caller
|
|
* can block before using it then we need to make a copy because it can
|
|
* be released from the cache as soon as we yield.
|
|
*/
|
|
if (freeEACLFlag)
|
|
{
|
|
*effectiveACL = computedEACL;
|
|
*freeEACL = TRUE;
|
|
freeEACLFlag = FALSE;
|
|
}
|
|
else
|
|
{ /* It has been assigned to the cache */
|
|
if (canBlock)
|
|
{
|
|
int size = EACL_SIZE(computedEACL->EACL.numEntries);
|
|
*effectiveACL = malloc(size);
|
|
if (*effectiveACL == NULL)
|
|
{ /* out of memory */
|
|
status = zERR_NO_MEMORY;
|
|
goto errorSet;
|
|
}
|
|
memcpy(*effectiveACL, computedEACL, size);
|
|
*freeEACL = TRUE;
|
|
}
|
|
else
|
|
{
|
|
*effectiveACL = computedEACL;
|
|
*freeEACL = FALSE;
|
|
}
|
|
}
|
|
status = zOK;
|
|
|
|
exit:
|
|
ZAS_CLEANUP_BEAST_STACK(stackPtr, maxStackEntries, beastStack);
|
|
if (freeEACLFlag)
|
|
{ /* if the computed EACL has not been assigned to the cache or is
|
|
* not being returned to the caller then free it */
|
|
free(computedEACL);
|
|
}
|
|
if (cacheLatched)
|
|
{
|
|
UNX_LATCH(&AuthCache.latch);
|
|
cacheLatched = FALSE;
|
|
}
|
|
return status;
|
|
|
|
errorSet:
|
|
SetErrno(genMsg, status);
|
|
status = zFAILURE;
|
|
goto exit;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* This routine will return the effective rights for a beast given an array
|
|
* of authenticated IDs.
|
|
****************************************************************************/
|
|
STATUS ZAS_GetEffectiveRightsByIDs(
|
|
GeneralMsg_s *genMsg,
|
|
AuthBeast_s *authBeast,
|
|
Zid_t parentZID,
|
|
BOOL secureAccess,
|
|
BOOL supervisor,
|
|
NINT numIDs,
|
|
UserID_t *IDs,
|
|
NINT *effectiveRights)
|
|
{
|
|
AuthCacheNode_s *computedEACL;
|
|
NINT numEntries;
|
|
NINT index;
|
|
NINT connectIndex;
|
|
SNINT compare;
|
|
BOOL freeEACL;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
ENTER(TAUTH, ZAS_GetEffectiveRightsByIDs);
|
|
|
|
/*
|
|
* IMPORTANT: Do not block after calling this function. The returned
|
|
* computed EACL can be in the cache and the cache is not latched at this
|
|
* point in time.
|
|
*/
|
|
if (ZAS_GetEffectiveACL(genMsg, authBeast, parentZID, &computedEACL, FALSE,
|
|
&freeEACL) != zOK)
|
|
{
|
|
goto error;
|
|
}
|
|
numEntries = computedEACL->EACL.numEntries;
|
|
|
|
if (supervisor)
|
|
{
|
|
*effectiveRights = zVALID_TRUSTEE_RIGHTS;
|
|
}
|
|
else
|
|
{
|
|
*effectiveRights = 0;
|
|
}
|
|
if (numEntries > 0)
|
|
{ /* if there are any entries in the effective ACL */
|
|
|
|
/*
|
|
* If the first entry in the EACL is the special connection zero
|
|
* trustee then it takes precedence over all other entries. It
|
|
* means only connection zero access is allowed and given the
|
|
* specified rights.
|
|
*/
|
|
if (LB_GUIDCompare(&computedEACL->EACL.entry[0].trusteeID,
|
|
&zSECURE_CONNECTION_USERID) == 0)
|
|
{
|
|
if (secureAccess || (genMsg->flags & ALLOW_SECURE_ACCESS))
|
|
{
|
|
*effectiveRights = computedEACL->EACL.entry[0].rights;
|
|
}
|
|
else
|
|
{
|
|
*effectiveRights = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Compute rights in the normal case
|
|
*/
|
|
for (connectIndex = 0; connectIndex < numIDs; connectIndex++)
|
|
{ /* for each entry in the connection structure */
|
|
for (index = 0; index < numEntries;
|
|
index++)
|
|
{ /* for each entry in the effective ACL */
|
|
compare = LB_GUIDCompare(
|
|
&computedEACL->EACL.entry[index].trusteeID,
|
|
&IDs[connectIndex]);
|
|
if (compare == 0)
|
|
{
|
|
/* FixFixFix6 -- not checking for negative rights */
|
|
*effectiveRights |=
|
|
computedEACL->EACL.entry[index].rights;
|
|
break;
|
|
}
|
|
else if (compare > 0)
|
|
{ /* already past possible match */
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (*effectiveRights & zAUTHORIZE_SUPERVISOR)
|
|
{
|
|
*effectiveRights |= zVALID_TRUSTEE_RIGHTS;
|
|
}
|
|
if (computedEACL && freeEACL)
|
|
{
|
|
free(computedEACL);
|
|
}
|
|
|
|
RTN_STATUS(zOK);
|
|
|
|
error:
|
|
RTN_STATUS(zFAILURE);
|
|
}
|
|
|
|
/*===========================================================================
|
|
*===========================================================================
|
|
*===========================================================================
|
|
*
|
|
* ZAS ACL OVERFLOW BEAST
|
|
*
|
|
*===========================================================================
|
|
*===========================================================================
|
|
*===========================================================================*/
|
|
|
|
/***************************************************************************
|
|
* This routine is called when an overflow beast is allocated in memory
|
|
***************************************************************************/
|
|
STATUS ACLO_ConstructBeast(
|
|
GeneralMsg_s *genMsg,
|
|
void *overflowBeast_LX)
|
|
{
|
|
ZasAclOverflowBeast_s *overflowBeast =
|
|
(ZasAclOverflowBeast_s *) overflowBeast_LX;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
ENTER(TAUTH, ACLO_ConstructBeast);
|
|
overflowBeast->acl = malloc(OVERFLOW_ALLOC_UNIT * sizeof(ACLEntry_s));
|
|
if (overflowBeast->acl == NULL)
|
|
{
|
|
SetErrno(genMsg, zERR_NO_MEMORY);
|
|
RTN_STATUS(zFAILURE);
|
|
}
|
|
overflowBeast->numAlloced = OVERFLOW_ALLOC_UNIT;
|
|
overflowBeast->p.nextOverflowZid = zINVALID_ZID;
|
|
overflowBeast->p.numEntries = 0;
|
|
RTN_STATUS(zOK);
|
|
}
|
|
|
|
/***************************************************************************
|
|
* This routine is called when an overflow beast is freed from memory
|
|
***************************************************************************/
|
|
void ACLO_DestructBeast(
|
|
void *overflowBeast_LX)
|
|
{
|
|
ZasAclOverflowBeast_s *overflowBeast =
|
|
(ZasAclOverflowBeast_s *) overflowBeast_LX;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
ENTER(TAUTH, ACLO_DestructBeast);
|
|
if (overflowBeast->acl != NULL)
|
|
{
|
|
free(overflowBeast->acl);
|
|
}
|
|
RTN_VOID();
|
|
}
|
|
|
|
/****************************************************************************
|
|
* ZAS OVERFLOW BEAST COMMON OPERATIONS definition
|
|
*****************************************************************************/
|
|
|
|
CommonBeastOps_s ACLO_ComnBeastOps =
|
|
{
|
|
ACLO_ConstructBeast, /* construct */
|
|
ACLO_DestructBeast, /* destruct */
|
|
|
|
// cnt NULL, /* BST_getNameUniquifier */
|
|
NULL, /* BST_setupNameTypeSpecificInfo */
|
|
NULL, /* BST_lookupByNameInDirectory*/
|
|
NULL, /* BST_isDirectoryEmpty*/
|
|
NULL, /* BST_addNameToDirectory*/
|
|
NULL, /* BST_removeNameFromDirectory*/
|
|
NULL, /* BST_modifyNameSpaceMaskInDirectory*/
|
|
NULL, /* BST_setMatchAttributesInDirectory*/
|
|
NULL, /* BST_wildcardLookup*/
|
|
|
|
NULL, /* BST_truncateFile*/
|
|
NULL, /* BST_getStorageInfo*/
|
|
NULL, /* BST_getExtentList*/
|
|
NULL, /* BST_getPhysicalExtent*/
|
|
NULL, /* BST_isBlockInBeast*/
|
|
|
|
NULL, /* BST_asyncReadFileBlk*/
|
|
NULL, /* BST_getFileBlk*/
|
|
NULL, /* BST_dfsReadUnits*/
|
|
NULL, /* BST_dfsWriteUnits*/
|
|
|
|
NULL, /* BST_getZID*/
|
|
NULL, /* BST_beastNotify*/
|
|
NULL, /* BST_getInfo*/
|
|
NULL, /* BST_modifyInfo*/
|
|
NULL, /* BST_getInfoXML*/
|
|
NULL /* BST_modifyInfoXML*/
|
|
};
|
|
|
|
///***************************************************************************
|
|
// * This routine is called when an overflow beast is written to storage
|
|
// ***************************************************************************/
|
|
//NINT ACLO_PackedSize(
|
|
// ZasAclOverflowBeast_s *overflowBeast)
|
|
//{
|
|
// ENTER(TAUTH, ACLO_PackedSize);
|
|
// RTN_NINT (sizeof(PersistentZasAclOverflowBeast_s) +
|
|
// (overflowBeast->p.numEntries * sizeof(ACLEntry_s)));
|
|
//}
|
|
//
|
|
///***************************************************************************
|
|
// * This routine is called when an overflow beast is written to storage
|
|
// ***************************************************************************/
|
|
//BYTE *ACLO_PackBeast(
|
|
// ZasAclOverflowBeast_s *overflowBeast,
|
|
// BYTE *storeBuffer)
|
|
//{
|
|
// NINT len;
|
|
//
|
|
// ENTER(TAUTH, ACLO_PackBeast);
|
|
// len = overflowBeast->p.numEntries * sizeof(ACLEntry_s);
|
|
// memcpy(storeBuffer, &overflowBeast->p, sizeof(PersistentZasAclOverflowBeast_s));
|
|
// storeBuffer += sizeof(PersistentZasAclOverflowBeast_s);
|
|
// zASSERT(overflowBeast->acl != NULL);
|
|
// memcpy(storeBuffer, overflowBeast->acl, len);
|
|
// RTN_PTR(storeBuffer + len);
|
|
//}
|
|
//
|
|
///***************************************************************************
|
|
// * This routine is called when an overflow beast is read from storage
|
|
// ***************************************************************************/
|
|
//BYTE *ACLO_UnpackBeast(
|
|
// GeneralMsg_s *genMsg,
|
|
// ZasAclOverflowBeast_s *overflowBeast,
|
|
// BYTE *storeBuffer)
|
|
//{
|
|
// NINT len;
|
|
//
|
|
// ENTER(TAUTH, ACLO_UnpackBeast);
|
|
// memcpy(&overflowBeast->p, storeBuffer, sizeof(PersistentZasAclOverflowBeast_s));
|
|
// storeBuffer += sizeof(PersistentZasAclOverflowBeast_s);
|
|
// len = overflowBeast->p.numEntries * sizeof(ACLEntry_s);
|
|
// zASSERT(len != 0);
|
|
// overflowBeast->acl = realloc(overflowBeast->acl, len);
|
|
// overflowBeast->numAlloced = overflowBeast->p.numEntries;
|
|
// if (overflowBeast->acl == NULL)
|
|
// {
|
|
// SetErrno(genMsg, zERR_NO_MEMORY);
|
|
// RTN_PTR(NULL);
|
|
// }
|
|
// memcpy(overflowBeast->acl, storeBuffer, len);
|
|
// RTN_PTR(storeBuffer + len);
|
|
//}
|
|
//
|
|
///*---------------------------------------------------------------------------
|
|
// * beast STORAGE ops definition
|
|
// *---------------------------------------------------------------------------*/
|
|
//StoragePoolBeastOps_s ACLO_StoragePoolOps[] =
|
|
//{
|
|
// {zFTYPE_ZFS_POOL, ACLO_PackedSize, ACLO_PackBeast, ACLO_UnpackBeast},
|
|
// /*{zFTYPE_ZFS_MEMPOOL, ACLO_PackedSize, ACLO_PackBeast, ACLO_UnpackBeast},*/
|
|
// {zFTYPE_INVALID}
|
|
//};
|
|
|
|
|
|
/*===========================================================================
|
|
*===========================================================================
|
|
*===========================================================================
|
|
*
|
|
* ZAS VISIBILITY OVERFLOW BEAST
|
|
*
|
|
*===========================================================================
|
|
*===========================================================================
|
|
*===========================================================================*/
|
|
|
|
/***************************************************************************
|
|
* This routine is called when an overflow beast is allocated in memory
|
|
***************************************************************************/
|
|
STATUS VISO_ConstructBeast(
|
|
GeneralMsg_s *genMsg,
|
|
void *overflowBeast_LX)
|
|
{
|
|
ZasVisOverflowBeast_s *overflowBeast =
|
|
(ZasVisOverflowBeast_s *) overflowBeast_LX;
|
|
|
|
ASSERT_MPKNSS_LOCK();
|
|
ENTER(TAUTH, VISO_ConstructBeast);
|
|
overflowBeast->vis = malloc(OVERFLOW_ALLOC_UNIT * sizeof(VisEntry_s));
|
|
if (overflowBeast->vis == NULL)
|
|
{
|
|
SetErrno(genMsg, zERR_NO_MEMORY);
|
|
RTN_STATUS(zFAILURE);
|
|
}
|
|
overflowBeast->numAlloced = OVERFLOW_ALLOC_UNIT;
|
|
overflowBeast->p.nextOverflowZid = zINVALID_ZID;
|
|
overflowBeast->p.numEntries = 0;
|
|
RTN_STATUS(zOK);
|
|
}
|
|
|
|
/***************************************************************************
|
|
* This routine is called when an overflow beast is freed from memory
|
|
***************************************************************************/
|
|
void VISO_DestructBeast(
|
|
void *overflowBeast_LX)
|
|
{
|
|
ZasVisOverflowBeast_s *overflowBeast =
|
|
(ZasVisOverflowBeast_s *) overflowBeast_LX;
|
|
ASSERT_MPKNSS_LOCK();
|
|
ENTER(TAUTH, VISO_DestructBeast);
|
|
if (overflowBeast->vis != NULL)
|
|
{
|
|
free(overflowBeast->vis);
|
|
}
|
|
RTN_VOID();
|
|
}
|
|
|
|
/****************************************************************************
|
|
* ZAS OVERFLOW BEAST COMMON OPERATIONS definition
|
|
*****************************************************************************/
|
|
|
|
CommonBeastOps_s VISO_ComnBeastOps =
|
|
{
|
|
VISO_ConstructBeast, /* construct */
|
|
VISO_DestructBeast, /* destruct */
|
|
|
|
// cnt NULL, /* BST_getNameUniquifier */
|
|
NULL, /* BST_setupNameTypeSpecificInfo */
|
|
NULL, /* BST_lookupByNameInDirectory*/
|
|
NULL, /* BST_isDirectoryEmpty*/
|
|
NULL, /* BST_addNameToDirectory*/
|
|
NULL, /* BST_removeNameFromDirectory*/
|
|
NULL, /* BST_modifyNameSpaceMaskInDirectory*/
|
|
NULL, /* BST_setMatchAttributesInDirectory*/
|
|
NULL, /* BST_wildcardLookup*/
|
|
|
|
NULL, /* BST_truncateFile*/
|
|
NULL, /* BST_getStorageInfo*/
|
|
NULL, /* BST_getExtentList*/
|
|
NULL, /* BST_isBlockInBeast*/
|
|
|
|
NULL, /* BST_asyncReadFileBlk*/
|
|
NULL, /* BST_getFileBlk*/
|
|
NULL, /* BST_dfsReadUnits*/
|
|
NULL, /* BST_dfsWriteUnits*/
|
|
|
|
NULL, /* BST_getZID*/
|
|
NULL, /* BST_beastNotify*/
|
|
NULL, /* BST_getInfo*/
|
|
NULL, /* BST_getInfoXML*/
|
|
NULL, /* BST_modifyInfo*/
|
|
NULL /* BST_modifyInfoXML*/
|
|
};
|
|
|
|
///***************************************************************************
|
|
// * This routine is called when an overflow beast is written to storage
|
|
// ***************************************************************************/
|
|
//NINT VISO_PackedSize(
|
|
// ZasVisOverflowBeast_s *overflowBeast)
|
|
//{
|
|
// ENTER(TAUTH, VISO_PackedSize);
|
|
// RTN_NINT(sizeof(PersistentZasVisOverflowBeast_s) +
|
|
// (overflowBeast->p.numEntries * sizeof(VisEntry_s)));
|
|
//}
|
|
//
|
|
///***************************************************************************
|
|
// * This routine is called when an overflow beast is written to storage
|
|
// ***************************************************************************/
|
|
//BYTE *VISO_PackBeast(
|
|
// ZasVisOverflowBeast_s *overflowBeast,
|
|
// BYTE *storeBuffer)
|
|
//{
|
|
// NINT len;
|
|
//
|
|
// ENTER(TAUTH, VISO_PackBeast);
|
|
// len = overflowBeast->p.numEntries * sizeof(VisEntry_s);
|
|
// memcpy(storeBuffer, &overflowBeast->p, sizeof(PersistentZasVisOverflowBeast_s));
|
|
// storeBuffer += sizeof(PersistentZasVisOverflowBeast_s);
|
|
// zASSERT(overflowBeast->vis != NULL);
|
|
// memcpy(storeBuffer, overflowBeast->vis, len);
|
|
// RTN_PTR(storeBuffer + len);
|
|
//}
|
|
//
|
|
///***************************************************************************
|
|
// * This routine is called when an overflow beast is read from storage
|
|
// ***************************************************************************/
|
|
//BYTE *VISO_UnpackBeast(
|
|
// GeneralMsg_s *genMsg,
|
|
// ZasVisOverflowBeast_s *overflowBeast,
|
|
// BYTE *storeBuffer)
|
|
//{
|
|
// NINT len;
|
|
//
|
|
// ENTER(TAUTH, VISO_UnpackBeast);
|
|
// memcpy(&overflowBeast->p, storeBuffer, sizeof(PersistentZasVisOverflowBeast_s));
|
|
// storeBuffer += sizeof(PersistentZasVisOverflowBeast_s);
|
|
// len = overflowBeast->p.numEntries * sizeof(VisEntry_s);
|
|
// overflowBeast->vis = realloc(overflowBeast->vis, len);
|
|
// overflowBeast->numAlloced = overflowBeast->p.numEntries;
|
|
// if (overflowBeast->vis == NULL)
|
|
// {
|
|
// SetErrno(genMsg, zERR_NO_MEMORY);
|
|
// RTN_PTR(NULL);
|
|
// }
|
|
// memcpy(overflowBeast->vis, storeBuffer, len);
|
|
// RTN_PTR(storeBuffer + len);
|
|
//}
|
|
//
|
|
///*---------------------------------------------------------------------------
|
|
// * beast STORAGE ops definition
|
|
// *---------------------------------------------------------------------------*/
|
|
//StoragePoolBeastOps_s VISO_StoragePoolOps[] =
|
|
//{
|
|
// {zFTYPE_ZFS_POOL, VISO_PackedSize, VISO_PackBeast, VISO_UnpackBeast},
|
|
// /*{zFTYPE_ZFS_MEMPOOL, VISO_PackedSize, VISO_PackBeast, VISO_UnpackBeast},*/
|
|
// {zFTYPE_INVALID}
|
|
//};
|