本文整理汇总了C++中BAIL_ON_VMDIR_ERROR函数的典型用法代码示例。如果您正苦于以下问题:C++ BAIL_ON_VMDIR_ERROR函数的具体用法?C++ BAIL_ON_VMDIR_ERROR怎么用?C++ BAIL_ON_VMDIR_ERROR使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了BAIL_ON_VMDIR_ERROR函数的20个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于我们的系统推荐出更棒的C++代码示例。
示例1: _VmDirSchemaReorderObjectClassAttr
/*
* reorder value of objectclass in pOCAttr->vals
* 1. structureOC->parentOC->parentOC->....->TOP(not included)
* expand parent objectclass if not supplied.
* 2. aux OCs
* We then store its values in this order in backend.
*/
static
DWORD
_VmDirSchemaReorderObjectClassAttr(
PVDIR_ATTRIBUTE pOCAttr,
PVDIR_SCHEMA_OC_DESC pStructureOCDesc,
PVDIR_SCHEMA_OC_DESC* ppAuxOCDesc)
{
DWORD dwError = 0;
int iCnt = 0;
int iAUXCnt = 0;
int iTotal = 0;
PVDIR_BERVALUE pBerv = NULL;
PVDIR_SCHEMA_OC_DESC pLocalDesc = pStructureOCDesc;
if ( !pOCAttr || !pStructureOCDesc )
{
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_VMDIR_ERROR(dwError);
}
// number of structure objectclass (except top)
for (iCnt = 0; pLocalDesc != NULL; pLocalDesc = pLocalDesc->pStructSupOC, iCnt++) {}
// number of aux objectclass
for (iAUXCnt = 0; ppAuxOCDesc && ppAuxOCDesc[iAUXCnt] != NULL; iAUXCnt++) {};
iTotal = iCnt + iAUXCnt;
dwError = VmDirAllocateMemory( sizeof(VDIR_BERVALUE) * (iTotal + 1),
(PVOID*)&pBerv);
BAIL_ON_VMDIR_ERROR(dwError);
// start with leaf structure objectclass and walk up the tree to top (NOT included)
for (iCnt = 0, pLocalDesc = pStructureOCDesc;
pLocalDesc != NULL;
pLocalDesc = pLocalDesc->pStructSupOC, iCnt++)
{
PCSTR pszOrgName = NULL;
unsigned int iTmp = 0;
for (iTmp = 0; iTmp < pOCAttr->numVals; iTmp++)
{
if (VmDirStringCompareA( pLocalDesc->pszName,
pOCAttr->vals[iTmp].lberbv_val,
FALSE) == 0)
{ // keep whatever value provided from clients
pszOrgName = pOCAttr->vals[iTmp].lberbv_val;
break;
}
}
dwError = VmDirAllocateStringA( pszOrgName ? pszOrgName : pLocalDesc->pszName,
&(pBerv[iCnt].lberbv_val) );
BAIL_ON_VMDIR_ERROR(dwError);
pBerv[iCnt].lberbv_len = VmDirStringLenA(pBerv[iCnt].lberbv_val);
pBerv[iCnt].bOwnBvVal = TRUE;
// TODO, Do we need to normalize value here?
}
// append aux objectclasses after structure objectclasses
for (iAUXCnt = 0; ppAuxOCDesc && ppAuxOCDesc[iAUXCnt] != NULL; iAUXCnt++, iCnt++)
{
PCSTR pszOrgName = NULL;
unsigned int iTmp = 0;
for (iTmp = 0; iTmp < pOCAttr->numVals; iTmp++)
{
if (VmDirStringCompareA( ppAuxOCDesc[iAUXCnt]->pszName,
pOCAttr->vals[iTmp].lberbv_val,
FALSE) == 0)
{ // keep whatever value provided from clients
pszOrgName = pOCAttr->vals[iTmp].lberbv_val;
break;
}
}
dwError = VmDirAllocateStringA( pszOrgName ? pszOrgName : ppAuxOCDesc[iAUXCnt]->pszName,
&(pBerv[iCnt].lberbv_val) );
BAIL_ON_VMDIR_ERROR(dwError);
pBerv[iCnt].lberbv_len = VmDirStringLenA(pBerv[iCnt].lberbv_val);
pBerv[iCnt].bOwnBvVal = TRUE;
// TODO, Do we need to normalize value here?
}
VmDirFreeBervalArrayContent( pOCAttr->vals, pOCAttr->numVals );
VMDIR_SAFE_FREE_MEMORY( pOCAttr->vals );
pOCAttr->vals = pBerv;
pOCAttr->numVals = iTotal;
cleanup:
return dwError;
//.........这里部分代码省略.........
开发者ID:Dan-McGee,项目名称:lightwave,代码行数:101,代码来源:check.c
示例2: _VmDirReadOneDefFromFile
/*
* read one schema element definition from file and normalize its definition.
*/
static
DWORD
_VmDirReadOneDefFromFile(
FILE* fp,
PVMDIR_STRING_LIST pStrList
)
{
DWORD dwError = 0;
size_t iSize = VMDIR_SIZE_9216, iLen = 0;
CHAR pDescBuf[VMDIR_SIZE_9216+1] = {0};
CHAR pbuf[VMDIR_SIZE_4096] = {0};
PCSTR pPrefix = "( ";
size_t iPrefixLen = VmDirStringLenA(pPrefix);
PSTR pOut = NULL;
dwError = VmDirStringNCatA(
pDescBuf+iLen, iSize-iLen, pPrefix, iPrefixLen);
BAIL_ON_VMDIR_ERROR(dwError);
iLen += iPrefixLen;
while (fgets(pbuf, sizeof(pbuf), fp) != NULL)
{
size_t len = VmDirStringLenA(pbuf) - 1;
if (pbuf[len] == '\n')
{
pbuf[len] = '\0';
}
if ( pbuf[0] == '#')
{
continue;
}
if ( pbuf[0] == ' ')
{
dwError = VmDirStringNCatA(
pDescBuf+iLen, iSize-iLen, pbuf, VmDirStringLenA(pbuf));
BAIL_ON_VMDIR_ERROR(dwError);
iLen += VmDirStringLenA(pbuf);
}
else
{
break;
}
}
if (pDescBuf[0] != '\0')
{
VmdDirNormalizeString(pDescBuf);
dwError = VmDirAllocateStringA(pDescBuf, &pOut);
BAIL_ON_VMDIR_ERROR(dwError);
dwError = VmDirStringListAdd(pStrList, pOut);
BAIL_ON_VMDIR_ERROR(dwError);
pOut = NULL;
}
cleanup:
return dwError;
error:
VMDIR_SAFE_FREE_MEMORY(pOut);
goto cleanup;
}
开发者ID:nks5295,项目名称:lightwave,代码行数:67,代码来源:file.c
示例3: VmDirSchemaInitializeViaEntry
/*
* Create a new schema cache via pEntry, then active this cache.
*/
DWORD
VmDirSchemaInitializeViaEntry(
PVDIR_ENTRY pEntry
)
{
BOOLEAN bLoadOk = TRUE;
BOOLEAN bInLock = FALSE;
DWORD dwError = 0;
PVDIR_SCHEMA_CTX pLiveCtx = NULL;
PVDIR_SCHEMA_INSTANCE pInstance = NULL;
PVDIR_SCHEMA_INSTANCE pLiveInstance = NULL;
VMDIR_LOCK_MUTEX(bInLock, gVdirSchemaGlobals.mutex);
// get reference to current schema, to clean up later
pLiveInstance = gVdirSchemaGlobals.pSchema;
pLiveCtx = gVdirSchemaGlobals.pCtx;
// instantiate a schema cache - pInstance
dwError = VdirSchemaInstanceInitViaEntry(
pEntry,
&pInstance);
BAIL_ON_VMDIR_ERROR(dwError);
gVdirSchemaGlobals.pSchema = pInstance;
dwError = VdirSchemaCtxAcquireInLock(TRUE, &gVdirSchemaGlobals.pCtx); // add self reference
BAIL_ON_VMDIR_ERROR(dwError);
assert(gVdirSchemaGlobals.pCtx);
VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "Startup schema instance (%p)", gVdirSchemaGlobals.pSchema);
VMDIR_UNLOCK_MUTEX(bInLock, gVdirSchemaGlobals.mutex);
cleanup:
if (bLoadOk)
{
VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL,
"Schema - AttributeTypes:(size=%d, nextid=%d) Objectclasses:(size=%d)",
pEntry->pSchemaCtx->pSchema->ats.usNumATs,
pEntry->pSchemaCtx->pSchema->ats.usNextId,
pEntry->pSchemaCtx->pSchema->ocs.usNumOCs);
}
VMDIR_UNLOCK_MUTEX(bInLock, gVdirSchemaGlobals.mutex);
if (pLiveCtx)
{
VmDirSchemaCtxRelease(pLiveCtx);
}
return dwError;
error:
if (pInstance)
{
VdirSchemaInstanceFree(pInstance);
}
gVdirSchemaGlobals.pSchema = pLiveInstance;
gVdirSchemaGlobals.pCtx = pLiveCtx;
pLiveCtx = NULL;
bLoadOk = FALSE;
goto cleanup;
}
开发者ID:Dan-McGee,项目名称:lightwave,代码行数:74,代码来源:libmain.c
示例4: VmDirLocalAPIHandler
DWORD
VmDirLocalAPIHandler(
PVM_DIR_SECURITY_CONTEXT pSecurityContext,
PBYTE pRequest,
DWORD dwRequestSize,
PBYTE * ppResponse,
DWORD * pdwResponseSize
)
{
DWORD dwError = 0;
UINT32 uApiType = 0;
PBYTE pResponse = NULL;
DWORD dwResponseSize = 0;
if (dwRequestSize < sizeof(UINT32))
{
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_VMDIR_ERROR (dwError);
}
if (!pSecurityContext)
{
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_VMDIR_ERROR (dwError);
}
uApiType = *((PUINT32)pRequest);
switch(uApiType)
{
case VMDIR_IPC_INITIALIZE_HOST:
dwError = VmDirIpcInitializeHost(
pSecurityContext,
pRequest,
dwRequestSize,
&pResponse,
&dwResponseSize
);
break;
case VMDIR_IPC_INITIALIZE_TENANT:
dwError = VmDirIpcInitializeTenant(
pSecurityContext,
pRequest,
dwRequestSize,
&pResponse,
&dwResponseSize
);
break;
case VMDIR_IPC_FORCE_RESET_PASSWORD:
dwError = VmDirIpcForceResetPassword(
pSecurityContext,
pRequest,
dwRequestSize,
&pResponse,
&dwResponseSize
);
break;
case VMDIR_IPC_GET_SRP_SECRET:
dwError = VmDirIpcGetSRPSecret(
pSecurityContext,
pRequest,
dwRequestSize,
&pResponse,
&dwResponseSize
);
break;
case VMDIR_IPC_SET_SRP_SECRET:
dwError = VmDirIpcSetSRPSecret(
pSecurityContext,
pRequest,
dwRequestSize,
&pResponse,
&dwResponseSize
);
break;
case VMDIR_IPC_GENERATE_PASSWORD:
dwError = VmDirIpcGeneratePassword(
pSecurityContext,
pRequest,
dwRequestSize,
&pResponse,
&dwResponseSize
);
break;
case VMDIR_IPC_GET_SERVER_STATE:
dwError = VmDirIpcGetServerState(
pSecurityContext,
pRequest,
//.........这里部分代码省略.........
开发者ID:nks5295,项目名称:lightwave,代码行数:101,代码来源:ipcapihandler.c
示例5: VmDirNormalizeDN
/*
* This is NOT RFC 4514 compliance.
*
* 1. separate into RDNs
* 2. for each RDN, normalize value based on its syntax
* (does not handle multi-value RDN case)
* remove all leading/trailing spaces
* 3. reconstruct DN based on RDNs
*/
DWORD
VmDirNormalizeDN(
PVDIR_BERVALUE pBerv,
PVDIR_SCHEMA_CTX pSchemaCtx
)
{
DWORD dwError = 0;
PSTR pszTmpDN = NULL;
PSTR* ppszRDNs = NULL;
PSTR* ppszNormRDNs = NULL;
int iNumRDNs = 0;
int iCnt = 0;
size_t iNormDNSize = 0;
PVDIR_SCHEMA_CTX pCtx = pSchemaCtx;
if (!pBerv || !pBerv->lberbv.bv_val)
{
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_VMDIR_ERROR(dwError);
}
// Already normalized. => Nothing to be done.
if ( pBerv->bvnorm_val != NULL )
{
dwError = 0;
goto cleanup;
}
// Nothing to be normalized for the ROOT DN
if (pBerv->lberbv.bv_len == 0)
{
pBerv->bvnorm_val = pBerv->lberbv.bv_val;
pBerv->bvnorm_len = 0;
dwError = 0;
goto cleanup;
}
if (pCtx == NULL)
{
dwError = VmDirSchemaCtxAcquire(&pCtx);
BAIL_ON_VMDIR_ERROR(dwError);
}
// make a local copy
dwError = VmDirAllocateStringA(
pBerv->lberbv.bv_val,
&pszTmpDN);
BAIL_ON_VMDIR_ERROR(dwError);
dwError = VdirSchemaInPlaceDN2RDNs(
pszTmpDN,
&ppszRDNs,
&iNumRDNs);
BAIL_ON_VMDIR_ERROR(dwError);
dwError = VmDirAllocateMemory(
sizeof(PSTR) * (iNumRDNs + 1),
(PVOID)&ppszNormRDNs);
BAIL_ON_VMDIR_ERROR(dwError);
for (iCnt=0; ppszRDNs[iCnt] && iCnt < iNumRDNs; iCnt++)
{
size_t iNameLen = 0 ;
VDIR_BERVALUE berval = VDIR_BERVALUE_INIT;
PVDIR_SCHEMA_AT_DESC pATDesc = NULL;
char* pChar = VmDirStringChrA(ppszRDNs[iCnt], '=');
if (!pChar)
{
dwError = ERROR_INVALID_DN;
BAIL_ON_VMDIR_ERROR(dwError);
}
*pChar = '\0';
iNameLen = VmDirStringLenA(ppszRDNs[iCnt]);
// attribute name - remove all leading/trailing spaces
while (ppszRDNs[iCnt][iNameLen-1] == ' ')
{
ppszRDNs[iCnt][iNameLen-1] = '\0';
iNameLen--;
assert(iNameLen > 0); // MIN 1 char for name
}
while (ppszRDNs[iCnt][0] == ' ')
{
ppszRDNs[iCnt]++;
}
pATDesc = VmDirSchemaAttrNameToDesc(pCtx, ppszRDNs[iCnt]);
if (!pATDesc)
{
//.........这里部分代码省略.........
开发者ID:nks5295,项目名称:lightwave,代码行数:101,代码来源:matchingrule.c
示例6: VmDirMDBGetNextUSN
/*
* Get the next available USN number.
*/
DWORD
VmDirMDBGetNextUSN(
PVDIR_BACKEND_CTX pBECtx,
USN * pUsn)
{
DWORD dwError = 0;
PVDIR_DB_TXN pTxn = NULL;
PVDIR_DB_TXN pLocalTxn = NULL;
VDIR_DB_DBT key = {0};
VDIR_DB_DBT value = {0};
unsigned char USNKeyBytes[sizeof( USN )] = {0};
unsigned char USNValueBytes[sizeof( USN )] = {0};
USN localUSN = 0;
BOOLEAN bRevertUSN = FALSE;
BOOLEAN bUnsetMaxUSN = TRUE;
assert( pBECtx && pUsn );
pTxn = (PVDIR_DB_TXN)pBECtx->pBEPrivate;
if (pTxn)
{
pLocalTxn = pTxn;
}
else
{
dwError = mdb_txn_begin( gVdirMdbGlobals.mdbEnv, BE_DB_PARENT_TXN_NULL, BE_DB_FLAGS_ZERO, &pLocalTxn );
BAIL_ON_VMDIR_ERROR(dwError);
}
key.mv_data = &USNKeyBytes[0];
MDBEntryIdToDBT(BE_MDB_USN_SEQ_KEY, &key);
dwError = mdb_get(pLocalTxn, gVdirMdbGlobals.mdbSeqDBi, &key, &value);
BAIL_ON_VMDIR_ERROR(dwError);
assert( value.mv_size == sizeof(USN) );
localUSN = *((USN*)value.mv_data);
*((USN*)&USNValueBytes[0]) = localUSN + 1;
value.mv_size = sizeof(USN);
value.mv_data = &USNValueBytes[0];
dwError = mdb_put(pLocalTxn, gVdirMdbGlobals.mdbSeqDBi, &key, &value, BE_DB_FLAGS_ZERO);
BAIL_ON_VMDIR_ERROR(dwError);
if (pBECtx->wTxnUSN == 0)
{ // capture and set outstanding USN within txn scope
pBECtx->wTxnUSN = localUSN;
dwError = VmDirBackendAddOutstandingUSN( pBECtx );
BAIL_ON_VMDIR_ERROR(dwError);
bRevertUSN = TRUE;
}
else
{ // if BECtx has wTxnUSN already (nested txn), it should be smaller than new USN here.
if (pBECtx->wTxnUSN >= localUSN)
{
VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "nested OP/TXN USN ordering logic error: (%ld)(%ld)",
pBECtx->wTxnUSN, localUSN );
dwError = LDAP_OPERATIONS_ERROR;
BAIL_ON_VMDIR_ERROR(dwError);
}
VmDirBackendSetMaxOutstandingUSN(pBECtx, localUSN);
bUnsetMaxUSN = TRUE;
}
if (pLocalTxn != pTxn)
{
dwError = mdb_txn_commit(pLocalTxn);
pLocalTxn = NULL;
BAIL_ON_VMDIR_ERROR(dwError);
}
*pUsn = localUSN;
cleanup:
return dwError;
error:
if (bUnsetMaxUSN)
{
VmDirBackendSetMaxOutstandingUSN(pBECtx, localUSN - 1);
}
if (bRevertUSN)
{
VmDirBackendRemoveOutstandingUSN( pBECtx );
pBECtx->wTxnUSN = 0;
}
if (pLocalTxn && pLocalTxn != pTxn)
{
mdb_txn_abort(pLocalTxn);
}
//.........这里部分代码省略.........
开发者ID:Dan-McGee,项目名称:lightwave,代码行数:101,代码来源:entry.c
示例7: VmDirMDBEIdToEntry
/* MdbEIdToEntry: For a given entry ID, reads an entry from the entry DB.
*
* Returns: BE error - BACKEND_ERROR, BACKEND OPERATIONS, BACKEND_ENTRY_NOTFOUND
*
*/
DWORD
VmDirMDBEIdToEntry(
PVDIR_BACKEND_CTX pBECtx,
PVDIR_SCHEMA_CTX pSchemaCtx,
ENTRYID eId,
PVDIR_ENTRY pEntry,
VDIR_BACKEND_ENTRY_LOCKTYPE entryLockType)
{
DWORD dwError = 0;
VDIR_DB mdbDBi = 0;
PVDIR_DB_TXN pTxn = NULL;
VDIR_DB_DBT key = {0};
VDIR_DB_DBT value = {0};
unsigned char eIdBytes[sizeof( ENTRYID )] = {0};
unsigned char* pszBlob = NULL;
assert(pBECtx && pBECtx->pBEPrivate && pSchemaCtx && pEntry);
pTxn = (PVDIR_DB_TXN)pBECtx->pBEPrivate;
mdbDBi = gVdirMdbGlobals.mdbEntryDB.pMdbDataFiles[0].mdbDBi;
// Set key
key.mv_data = &eIdBytes[0];
MDBEntryIdToDBT(eId, &key);
if ((dwError = mdb_get(pTxn, mdbDBi, &key, &value) ) != 0)
{
dwError = MDBToBackendError(dwError, MDB_NOTFOUND, ERROR_BACKEND_ENTRY_NOTFOUND, pBECtx, "EIDToEntry");
BAIL_ON_VMDIR_ERROR( dwError );
}
if ((dwError = VmDirAllocateMemory( value.mv_size, (PVOID *)&pszBlob)) != 0)
{
dwError = ERROR_BACKEND_OPERATIONS;
BAIL_ON_VMDIR_ERROR( dwError );
}
if ((dwError = VmDirCopyMemory(pszBlob, value.mv_size, value.mv_data, value.mv_size)) != 0)
{
dwError = ERROR_BACKEND_OPERATIONS;
BAIL_ON_VMDIR_ERROR( dwError );
}
// encodedEntry takes over pszBlob
pEntry->encodedEntry = pszBlob;
pszBlob = NULL;
pEntry->eId = eId;
dwError = VmDirDecodeEntry(pSchemaCtx, pEntry );
BAIL_ON_VMDIR_ERROR(dwError);
cleanup:
return dwError;
error:
VMDIR_LOG_ERROR( LDAP_DEBUG_BACKEND, "VmDirMDBEIdToEntry, eid(%u) failed (%u)", eId, dwError);
VMDIR_SAFE_FREE_MEMORY(pszBlob);
VmDirFreeEntryContent( pEntry );
VMDIR_SET_BACKEND_ERROR(dwError); // if dwError no in BE space, set to ERROR_BACKEND_ERROR
goto cleanup;
}
开发者ID:Dan-McGee,项目名称:lightwave,代码行数:72,代码来源:entry.c
示例8: VmDirSASLSRPBindExt1
DWORD
VmDirSASLSRPBindExt1(
LDAP** ppLd,
PCSTR pszURI,
PCSTR pszUPN,
PCSTR pszPass,
int iTimeout
)
{
DWORD dwError = 0;
int retVal = 0;
PSTR pszLowerCaseUPN = NULL;
LDAP* pLd = NULL;
const int ldapVer = LDAP_VERSION3;
const int iSaslNoCanon = 1;
VMDIR_SASL_INTERACTIVE_DEFAULT srpDefault = {0};
int iCnt = 0;
struct timeval optTimeout={0};
optTimeout.tv_usec = 0;
optTimeout.tv_sec = iTimeout;
if ( ppLd == NULL || pszURI == NULL || pszUPN == NULL || pszPass == NULL )
{
dwError = VMDIR_ERROR_INVALID_PARAMETER;
BAIL_ON_VMDIR_ERROR(dwError);
}
dwError = VmDirAllocASCIIUpperToLower( pszUPN, &pszLowerCaseUPN );
BAIL_ON_VMDIR_ERROR(dwError);
srpDefault.pszAuthName = pszLowerCaseUPN;
srpDefault.pszPass = pszPass;
for (iCnt=0; iCnt<2; iCnt++)
{
retVal = ldap_initialize( &pLd, pszURI);
BAIL_ON_SIMPLE_LDAP_ERROR(retVal);
retVal = ldap_set_option(pLd, LDAP_OPT_PROTOCOL_VERSION, &ldapVer);
BAIL_ON_SIMPLE_LDAP_ERROR(retVal);
// turn off SASL hostname canonicalization for SRP mech
retVal = ldap_set_option(pLd, LDAP_OPT_X_SASL_NOCANON, &iSaslNoCanon);
BAIL_ON_SIMPLE_LDAP_ERROR(retVal);
if (iTimeout > 0)
{
// timeout connect
retVal = ldap_set_option(pLd, LDAP_OPT_NETWORK_TIMEOUT, (void *)&optTimeout);
BAIL_ON_SIMPLE_LDAP_ERROR(retVal);
}
retVal = ldap_sasl_interactive_bind_s( pLd,
NULL,
"SRP",
NULL,
NULL,
LDAP_SASL_QUIET,
_VmDirSASLSRPInteraction,
&srpDefault);
if (retVal == LDAP_SERVER_DOWN || retVal == LDAP_TIMEOUT)
{
VmDirSleep(50); // pause 50 ms
if ( pLd )
{
ldap_unbind_ext_s(pLd, NULL, NULL);
pLd = NULL;
}
continue; // if transient network error, retry once.
}
else
{
break;
}
}
BAIL_ON_SIMPLE_LDAP_ERROR(retVal); // bail ldap_sasl_interactive_bind_s failure.
*ppLd = pLd;
cleanup:
VMDIR_SAFE_FREE_MEMORY(pszLowerCaseUPN);
return dwError;
ldaperror:
VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "_VmDirSASLSRPBind failed. (%d)(%s)",
retVal, ldap_err2string(retVal) );
dwError = VmDirMapLdapError(retVal);
error:
if (retVal == 0)
{
VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "_VmDirSASLSRPBind failed. (%u)", dwError);
}
if ( pLd )
{
//.........这里部分代码省略.........
开发者ID:vmware,项目名称:lightwave,代码行数:101,代码来源:ldapbind.c
示例9: VmDirSSLBind
/*
* Bind to a LDAP server via SSL port.
* Require server certificate verification.
*
* In 5.5. mix mode, replication goes through ldaps port.
*/
DWORD
VmDirSSLBind(
LDAP** ppLd,
PCSTR pszURI,
PCSTR pszDN,
PCSTR pszPassword
)
{
DWORD dwError = 0;
int retVal = 0;
LDAP* pLd = NULL;
BerValue ldapBindPwd = {0};
const int ldapVer = LDAP_VERSION3;
int iTLSDEMAND = LDAP_OPT_X_TLS_DEMAND;
int iTLSMin = LDAP_OPT_X_TLS_PROTOCOL_TLS1_0;
PSTR pszTrustCertFile = NULL;
SSL_CTX* pSslCtx = NULL;
if ( ppLd == NULL || pszURI == NULL )
{
dwError = VMDIR_ERROR_INVALID_PARAMETER;
BAIL_ON_VMDIR_ERROR(dwError);
}
// only allow ldaps traffic over SSL port
if ( VmDirStringNCompareA( pszURI, VMDIR_LDAPS_PROTOCOL, 5, FALSE) != 0 )
{
dwError = VMDIR_ERROR_ACCESS_DENIED;
BAIL_ON_VMDIR_ERROR(dwError);
}
dwError = VmDirPrepareOpensslClientCtx( &pSslCtx, &pszTrustCertFile, pszURI );
BAIL_ON_VMDIR_ERROR(dwError);
retVal = ldap_set_option( NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &iTLSDEMAND);
BAIL_ON_SIMPLE_LDAP_ERROR(retVal);
retVal = ldap_set_option(NULL, LDAP_OPT_X_TLS_PROTOCOL_MIN, &iTLSMin);
BAIL_ON_SIMPLE_LDAP_ERROR(retVal);
retVal = ldap_initialize(&pLd, pszURI);
BAIL_ON_SIMPLE_LDAP_ERROR(retVal);
retVal = ldap_set_option(pLd, LDAP_OPT_PROTOCOL_VERSION, &ldapVer);
BAIL_ON_SIMPLE_LDAP_ERROR(retVal);
retVal = ldap_set_option( pLd, LDAP_OPT_X_TLS_CTX, pSslCtx);
BAIL_ON_SIMPLE_LDAP_ERROR(retVal);
ldapBindPwd.bv_val = 0;
ldapBindPwd.bv_len = 0;
if (pszPassword)
{
ldapBindPwd.bv_val = (PSTR) pszPassword;
ldapBindPwd.bv_len = (ULONG) VmDirStringLenA(pszPassword);
}
retVal = ldap_sasl_bind_s( pLd,
pszDN,
LDAP_SASL_SIMPLE,
&ldapBindPwd, // ldaps with credentials
NULL,
NULL,
NULL);
BAIL_ON_SIMPLE_LDAP_ERROR(retVal);
*ppLd = pLd;
cleanup:
if (pSslCtx)
{
SSL_CTX_free(pSslCtx);
}
VMDIR_SAFE_FREE_MEMORY(pszTrustCertFile);
return dwError;
ldaperror:
VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "VmDirSSLBind failed for %s %s. (%d)(%s)",
pszURI, pszDN,
retVal, ldap_err2string(retVal));
dwError = VmDirMapLdapError(retVal);
error:
if (retVal == 0)
{
VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "_VmDirSSLBind failed. (%u)", dwError);
}
if ( pLd )
{
ldap_unbind_ext_s( pLd, NULL, NULL);
}
//.........这里部分代码省略.........
开发者ID:vmware,项目名称:lightwave,代码行数:101,代码来源:ldapbind.c
示例10: _VmDirSchemaCheckEntryStructure
/*
* 1. entry must have one and only one structure object class (from same oc tree)
* 2. auxiliary object class content rule compliance
* 3. entry must have all MUST attributes
* 4. entry may have allowed MAY attributes
*/
static
DWORD
_VmDirSchemaCheckEntryStructure(
PVDIR_SCHEMA_CTX pCtx,
PVDIR_ENTRY pEntry,
PVDIR_ATTRIBUTE pOCAttr,
BOOLEAN* pbPresentList
)
{
DWORD dwError = 0;
unsigned int iCnt = 0;
int iNumAuxOCs = 0;
BOOLEAN bHasStructuralOC = FALSE;
PVDIR_SCHEMA_OC_DESC pStructOCDesc = NULL; // leaf structural OC
PVDIR_SCHEMA_OC_DESC* ppAuxOCDesc = NULL;
assert(pCtx && pEntry && pOCAttr && pbPresentList);
dwError = VmDirAllocateMemory(
sizeof(PVDIR_SCHEMA_OC_DESC*) * (pOCAttr->numVals),
(PVOID)&ppAuxOCDesc);
BAIL_ON_VMDIR_ERROR(dwError);
// walk through objectclass value to collect structure and aux ocs info
for (iCnt = 0; iCnt < pOCAttr->numVals; iCnt++)
{
PVDIR_SCHEMA_OC_DESC pOCDesc =
_VmDirSchemaCheckOCDescLookup(pCtx, pOCAttr->vals[iCnt].lberbv.bv_val);
if (!pOCDesc)
{
VMDIR_SAFE_FREE_MEMORY(pCtx->pszErrorMsg);
VmDirAllocateStringAVsnprintf(
&pCtx->pszErrorMsg,
"Objectclass (%s) is not defined in schema",
VDIR_SAFE_STRING(pOCAttr->vals[iCnt].lberbv.bv_val));
VmDirLog( LDAP_DEBUG_ANY, "schemaCheckStructure: (%s)", VDIR_SAFE_STRING(pCtx->pszErrorMsg));
dwError = pCtx->dwErrorCode = ERROR_INVALID_ENTRY;
BAIL_ON_VMDIR_ERROR(dwError);
}
switch (pOCDesc->type)
{
case VDIR_OC_STRUCTURAL:
bHasStructuralOC = TRUE;
if (!pStructOCDesc)
{
pStructOCDesc = pOCDesc;
pEntry->pszStructureOC = pOCAttr->vals[iCnt].lberbv.bv_val;
}
else
{ // make sure they are from the same structure tree
PVDIR_SCHEMA_OC_DESC pTmpOCDesc = pStructOCDesc;
for (; pTmpOCDesc; pTmpOCDesc = pTmpOCDesc->pStructSupOC)
{
if (pTmpOCDesc == pOCDesc) { break; }
}
if (!pTmpOCDesc) // pOCDesc is NOT ancestor of pStructOCDesc
{
for (pTmpOCDesc = pOCDesc; pTmpOCDesc; pTmpOCDesc = pTmpOCDesc->pStructSupOC)
{
if (pTmpOCDesc == pStructOCDesc)
{
// reset pStructOCDesc
pStructOCDesc = pOCDesc;
pEntry->pszStructureOC = pOCAttr->vals[iCnt].lberbv.bv_val;
break;
}
}
}
if (!pTmpOCDesc)
{
VMDIR_SAFE_FREE_MEMORY(pCtx->pszErrorMsg);
VmDirAllocateStringAVsnprintf(
&pCtx->pszErrorMsg,
"Entry can have only one structure objectclass.",
VDIR_SAFE_STRING(pOCDesc->pszName));
dwError = pCtx->dwErrorCode = ERROR_INVALID_ENTRY;
BAIL_ON_VMDIR_ERROR(dwError);
}
}
break;
case VDIR_OC_AUXILIARY:
ppAuxOCDesc[iNumAuxOCs] = pOCDesc;
iNumAuxOCs++;
break;
//.........这里部分代码省略.........
开发者ID:Dan-McGee,项目名称:lightwave,代码行数:101,代码来源:check.c
示例11: _VmDirSchemaCheckStructure
/*
* 1. must have objectclass value
* 2. must have structural objectclass (done in schemaCheckStructure)
* 3. must match contentrule allowed auxiliary objectclass definition
* 4. must have all MUST attributes
* 5. may have allowed MAY attributes
*/
static
DWORD
_VmDirSchemaCheckStructure(
PVDIR_SCHEMA_CTX pCtx,
PVDIR_ENTRY pEntry
)
{
DWORD dwError = 0;
USHORT usCnt = 0;
BOOLEAN* pbPresentList = NULL;
DWORD numAttrs = 0;
PVDIR_ATTRIBUTE pTmpAttr = NULL;
VDIR_ATTRIBUTE* pOCAttr = NULL;
for (pTmpAttr = pEntry->attrs; pTmpAttr != NULL; pTmpAttr = pTmpAttr->next)
{
numAttrs++;
}
if (numAttrs == 0)
{
pCtx->dwErrorCode = ERROR_INVALID_ENTRY;
VMDIR_SAFE_FREE_MEMORY(pCtx->pszErrorMsg);
dwError = VmDirAllocateStringA(
"Entry has no attributes",
&pCtx->pszErrorMsg);
dwError = ERROR_INVALID_ENTRY;
BAIL_ON_VMDIR_ERROR(dwError);
}
dwError = VmDirAllocateMemory(
sizeof(BOOLEAN) * numAttrs,
(PVOID*)&pbPresentList);
BAIL_ON_VMDIR_ERROR(dwError);
pOCAttr = _VmDirchemaCheckFindObjectClass(pCtx, pEntry);
if (!pOCAttr || pOCAttr->numVals < 1)
{
pCtx->dwErrorCode = ERROR_INVALID_ENTRY;
VMDIR_SAFE_FREE_MEMORY(pCtx->pszErrorMsg);
dwError = VmDirAllocateStringA("Entry has no objectclass",&pCtx->pszErrorMsg);
dwError = ERROR_INVALID_ENTRY;
BAIL_ON_VMDIR_ERROR(dwError);
}
dwError = _VmDirSchemaCheckEntryStructure(
pCtx,
pEntry,
pOCAttr,
pbPresentList);
BAIL_ON_VMDIR_ERROR(dwError);
{ // all VDIR_ATTRIBUTE_USER_APPLICATION attribute should be marked
PVDIR_ATTRIBUTE pAttr = NULL;
for (usCnt = 0, pAttr = pEntry->attrs;
usCnt < numAttrs;
usCnt++, pAttr = pAttr->next)
{
if (!pbPresentList[usCnt] && pAttr->pATDesc->usage == VDIR_ATTRIBUTETYPE_USER_APPLICATIONS)
{
VMDIR_SAFE_FREE_MEMORY(pCtx->pszErrorMsg);
dwError = VmDirAllocateStringAVsnprintf(
&pCtx->pszErrorMsg,
"Attribute (%s) not allowed",
VDIR_SAFE_STRING(pAttr->type.lberbv.bv_val));
dwError = pCtx->dwErrorCode = ERROR_INVALID_ENTRY;
BAIL_ON_VMDIR_ERROR(dwError);
}
}
}
cleanup:
VMDIR_SAFE_FREE_MEMORY(pbPresentList);
return dwError;
error:
goto cleanup;
}
开发者ID:Dan-McGee,项目名称:lightwave,代码行数:94,代码来源:check.c
示例12: _VmDirSchemaCheckContentRuleAuxOC
/*
* Per structure objectclass, verify contentrule auxiliary object class
*/
static
DWORD
_VmDirSchemaCheckContentRuleAuxOC(
PVDIR_SCHEMA_CTX pCtx,
PVDIR_SCHEMA_OC_DESC pStructureOCDesc,
PVDIR_SCHEMA_OC_DESC* ppAuxOCDesc
)
{
DWORD dwError = 0;
int iCnt = 0;
BOOLEAN bHasAllowedAuxOC = FALSE;
assert(pCtx && pStructureOCDesc && ppAuxOCDesc);
if (pCtx->pSchema->contentRules.usNumContents == 0)
{
// schema no content rule support
goto cleanup;
}
bHasAllowedAuxOC = pStructureOCDesc->ppAllowedAuxOCs ? TRUE : FALSE;
if (!bHasAllowedAuxOC && ppAuxOCDesc[0])
{ // entry structure oc has NO allowedAuxOCs but entry now has aux ocs
dwError = ERROR_INVALID_ENTRY;
BAIL_ON_VMDIR_ERROR(dwError);
}
for (; ppAuxOCDesc[iCnt]; iCnt++)
{
int iIdx = 0;
for (;pStructureOCDesc->ppAllowedAuxOCs[iIdx]; iIdx++)
{
if (pStructureOCDesc->ppAllowedAuxOCs[iIdx] == ppAuxOCDesc[iCnt])
{
break;
}
}
if (pStructureOCDesc->ppAllowedAuxOCs[iIdx] == NULL)
{ // entry aux oc not found in allowed list from content rule
dwError = ERROR_INVALID_ENTRY;
BAIL_ON_VMDIR_ERROR(dwError);
}
}
cleanup:
return dwError;
error:
pCtx->dwErrorCode = ERROR_INVALID_ENTRY;
VMDIR_SAFE_FREE_MEMORY(pCtx->pszErrorMsg);
VmDirAllocateStringAVsnprintf(
&pCtx->pszErrorMsg,
"Aux objectclass (%s) is not allowed.",
VDIR_SAFE_STRING(ppAuxOCDesc[iCnt]->pszName));
VmDirLog( LDAP_DEBUG_ANY, "%s", VDIR_SAFE_STRING(pCtx->pszErrorMsg));
goto cleanup;
}
开发者ID:Dan-McGee,项目名称:lightwave,代码行数:66,代码来源:check.c
示例13: _VmDirSchemaCheckSyntaxAndDimension
static
DWORD
_VmDirSchemaCheckSyntaxAndDimension(
PVDIR_SCHEMA_CTX pCtx,
PVDIR_ENTRY pEntry
)
{
DWORD dwError = 0;
VDIR_ATTRIBUTE* pAttr = NULL;
for (pAttr = pEntry->attrs; pAttr; pAttr = pAttr->next)
{
USHORT usCnt = 0;
if (pAttr->pATDesc->bSingleValue && pAttr->numVals != 1)
{
pCtx->dwErrorCode = ERROR_INVALID_ENTRY;
VMDIR_SAFE_FREE_MEMORY(pCtx->pszErrorMsg);
dwError = VmDirAllocateStringAVsnprintf(
&pCtx->pszErrorMsg,
"Attribute (%s) can have at most one value",
VDIR_SAFE_STRING(pAttr->type.lberbv.bv_val));
dwError = ERROR_INVALID_ENTRY;
BAIL_ON_VMDIR_ERROR(dwError);
}
for (usCnt = 0; usCnt < pAttr->numVals; usCnt++)
{
if (pAttr->pATDesc->uiMaxSize > 0)
{
//TODO, for server control/manipulate attribute, we should exclude this restriction
// as they no longer in their original form. (e.g. userPassword)
if (pAttr->vals[usCnt].lberbv.bv_len > pAttr->pATDesc->uiMaxSize)
{
VMDIR_SAFE_FREE_MEMORY(pCtx->pszErrorMsg);
VmDirAllocateStringAVsnprintf( // ignore error
&pCtx->pszErrorMsg,
"Attribute (%s) value too long, max (%d) allowed.",
VDIR_SAFE_STRING(pAttr->type.lberbv.bv_val),
pAttr->pATDesc->uiMaxSize);
dwError = pCtx->dwErrorCode = LDAP_CONSTRAINT_VIOLATION;
BAIL_ON_VMDIR_ERROR(dwError);
}
}
dwError = VmDirSchemaBervalSyntaxCheck(
pCtx,
pAttr->pATDesc,
&pAttr->vals[usCnt]);
BAIL_ON_VMDIR_ERROR(dwError);
}
}
cleanup:
return dwError;
error:
VmDirLog( LDAP_DEBUG_ANY, "%s", VDIR_SAFE_STRING(pCtx->pszErrorMsg));
goto cleanup;
}
开发者ID:Dan-McGee,项目名称:lightwave,代码行数:66,代码来源:check.c
示例14: VmDirSchemaCheckDITStructure
/*
* Entry schema check dit structure rule
*/
DWORD
VmDirSchemaCheckDITStructure(
PVDIR_SCHEMA_CTX pCtx,
PVDIR_ENTRY pParentEntry,
PVDIR_ENTRY pEntry
)
{
DWORD dwError = 0;
unsigned int iCnt = 0;
BOOLEAN bParentAllowed = FALSE;
PVDIR_ATTRIBUTE pParentOCAttr = NULL;
PVDIR_SCHEMA_OC_DESC pStructureOCDesc = NULL;
VDIR_SCHEMA_OC_DESC ocKey = {0};
assert(pCtx && pEntry);
// BUBBUG - bypass checking until we define castle structure rules
goto cleanup;
if (pCtx->pSchema->structureRules.usNumStructures == 0)
{
// schema has no structure rule defined
goto cleanup;
}
if (!pEntry->pszStructureOC)
{
VMDIR_SAFE_FREE_MEMORY(pCtx->pszErrorMsg);
dwError = VmDirAllocateStringAVsnprintf(
&pCtx->pszErrorMsg,
"Entry has no structure objectclass/pszStructureOC.");
dwError = pCtx->dwErrorCode = ERROR_INVALID_ENTRY;
BAIL_ON_VMDIR_ERROR(dwError);
}
ocKey.pszName = pEntry->pszStructureOC;
pStructureOCDesc = (PVDIR_SCHEMA_OC_DESC) bsearch(
&ocKey,
pCtx->pSchema->ocs.pOCSortName,
pCtx->pSchema->ocs.usNumOCs,
sizeof(VDIR_SCHEMA_OC_DESC),
VdirSchemaPOCNameCmp);
if (!pStructureOCDesc)
{
VMDIR_SAFE_FREE_MEMORY(pCtx->pszErrorMsg);
dwError = VmDirAllocateStringAVsnprintf(
&pCtx->pszErrorMsg,
"Structure oc (%s) not defined.",
VDIR_SAFE_STRING(pEntry->pszStructureOC));
dwError = pCtx->dwErrorCode = ERROR_INVALID_ENTRY;
BAIL_ON_VMDIR_ERROR(dwError);
}
if (pParentEntry)
{
pParentOCAttr = _VmDirchemaCheckFindObjectClass(pCtx, pParentEntry);
}
if (pParentOCAttr)
{
if (pStructureOCDesc->ppszAllowedParentOCs)
{
// loop through parent object class to check allowedParentsOCs
//TODO, we can arrange structure object class to be the first to eliminate loop.
for (iCnt = 0; iCnt < pParentOCAttr->numVals; iCnt++)
{
int iIdx = 0;
for (;pStructureOCDesc->ppszAllowedParentOCs[iIdx]; iIdx++)
{
if (VmDirStringCompareA(pParentOCAttr->vals[iCnt].lberbv.bv_val,
pStructureOCDesc->ppszAllowedParentOCs[iIdx],
FALSE) == 0)
{
// allowed under this parent
bParentAllowed = TRUE;
break;
}
}
if (pStructureOCDesc->ppszAllowedParentOCs[iIdx] != NULL)
{
break;
}
}
}
}
else
{
if (pStructureOCDesc->bAllowedParentRoot == TRUE)
{ // allowed under root
bParentAllowed = TRUE;
}
}
//.........这里部分代码省略.........
开发者ID:Dan-McGee,项目名称:lightwave,代码行数:101,代码来源:check.c
示例15: VdcadminTestSASLClient
VOID
VdcadminTestSASLClient(
VOID
)
{
DWORD dwError = 0;
char pszServerHost[SIZE_256] = {0};
char pszServerPort[SIZE_256] = {0};
char pszServerSSLPort[SIZE_256] = {0};
char pszBindDN[SIZE_256] = {0};
char pszBindUPN[SIZE_256] = {0};
char pszPassword[SIZE_256] = {0};
PSTR pszLDAPURI = NULL;
PSTR pszLDAPSURI = NULL;
VmDirReadString(
"Please enter LDAP server host: ",
pszServerHost,
SIZE_256,
FALSE);
VmDirReadString(
"Please enter LDAP server port: ",
pszServerPort,
SIZE_256,
FALSE);
VmDirReadString(
"Please enter LDAP server SSL port: ",
pszServerSSLPort,
SIZE_256,
FALSE);
VmDirReadString(
"Please enter LDAP Bind DN: ",
pszBindDN,
SIZE_256,
FALSE);
VmDirReadString(
"Please enter LDAP Bind UPN: ",
pszBindUPN,
SIZE_256,
FALSE);
VmDirReadString(
"Please enter LDAP Bind password: ",
pszPassword,
SIZE_256,
TRUE);
printf("\n");
dwError = VmDirAllocateStringAVsnprintf( &pszLDAPURI,
"ldap://%s:%s",
pszServerHost[0] != '\0' ? pszServerHost : "localhost",
pszServerPort);
BAIL_ON_VMDIR_ERROR(dwError);
dwError = VmDirAllocateStringAVsnprintf( &pszLDAPSURI,
"ldaps://%s:%s",
pszServerHost[0] != '\0' ? pszServerHost : "localhost",
pszServerSSLPort);
BAIL_ON_VMDIR_ERROR(dwError);
_VdcadminClientTestSimpleBind( pszLDAPURI, pszBindDN, pszPassword );
_VdcadminClientTestSimpleSSLBind( pszLDAPSURI, pszBindDN, pszPassword );
_VdcadminClientTestSRPBind( pszLDAPURI, pszBindUPN, pszPassword );
_VdcadminClientTestGSSAPIBind( pszLDAPURI );
cleanup:
memset(pszPassword, 0, sizeof(pszPassword));
VMDIR_SAFE_FREE_MEMORY(pszLDAPURI);
VMDIR_SAFE_FREE_MEMORY(pszLDAPSURI);
return;
error:
printf("TestVdcadminSASLClient failed. (%d)\n", dwError);
goto cleanup;
}
开发者ID:Dan-McGee,项目名称:lightwave,代码行数:88,代码来源:ldapbindclient.c
示例16: VmDirSafeLDAPBindToPort
DWORD
VmDirSafeLDAPBindToPort(
LDAP** ppLd,
PCSTR pszHost,
DWORD dwPort,
PCSTR pszUPN,
PCSTR pszPassword,
int iTimeout
)
{
DWORD dwError = 0;
LDAP* pLd = NULL;
char ldapURI[VMDIR_MAX_LDAP_URI_LEN + 1] = {0};
DWORD dwLdapPort = DEFAULT_LDAP_PORT_NUM;
DWORD dwTmpLdapPort = 0;
if (ppLd == NULL || pszHost == NULL || pszUPN == NULL || pszPassword == NULL)
{
dwError = VMDIR_ERROR_INVALID_PARAMETER;
BAIL_ON_VMDIR_ERROR(dwError);
}
if (dwPort)
{
dwLdapPort = dwPort;
}
else if (VmDirGetRegKeyValueDword(
VMDIR_CONFIG_PARAMETER_V1_KEY_PATH,
VMDIR_REG_KEY_LDAP_PORT,
&dwTmpLdapPort,
DEFAULT_LDAP_PORT_NUM) == ERROR_SUCCESS)
{
dwLdapPort = dwTmpLdapPort;
}
if ( VmDirIsIPV6AddrFormat( pszHost ) )
{
dwError = VmDirStringPrintFA( ldapURI, sizeof(ldapURI)-1, "%s://[%s]:%d",
VMDIR_LDAP_PROTOCOL, pszHost, dwLdapPort);
}
else
{
dwError = VmDirStringPrintFA( ldapURI, sizeof(ldapURI)-1, "%s://%s:%d",
VMDIR_LDAP_PROTOCOL, pszHost, dwLdapPort);
}
BAIL_ON_VMDIR_ERROR(dwError);
dwError = VmDirSASLSRPBindExt1( &pLd, &(ldapURI[0]), pszUPN, pszPassword, iTimeout);
BAIL_ON_VMDIR_ERROR(dwError);
*ppLd = pLd;
cleanup:
return dwError;
error:
VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s to (%s) failed. SRP(%d)",
__FUNCTION__, ldapURI, dwError );
if ( pLd )
{
ldap_unbind_ext_s( pLd, NULL, NULL);
}
goto cleanup;
}
开发者ID:vmware,项目名称:lightwave,代码行数:69,代码来源:ldapbind.c
示例17: VmDirSchemaCacheModifyPrepare
|
请发表评论