📄 dbx_misc.c
字号:
if( cryptStatusOK( status ) )
status = dbmsStaticUpdate(
"CREATE UNIQUE INDEX certIDIdx ON certificates(certID)" );
if( cryptStatusOK( status ) )
status = dbmsStaticUpdate(
"CREATE UNIQUE INDEX crlIssuerIDIdx ON CRLs (issuerID)" );
if( cryptStatusOK( status ) && isCertStore( dbmsInfo ) )
status = dbmsStaticUpdate(
"CREATE UNIQUE INDEX crlCertIDIdx ON CRLs (certID)" );
if( cryptStatusOK( status ) && isCertStore( dbmsInfo ) )
status = dbmsStaticUpdate(
"CREATE UNIQUE INDEX userKeyIDIdx ON pkiUsers (keyID)" );
if( cryptStatusOK( status ) && isCertStore( dbmsInfo ) )
status = dbmsStaticUpdate(
"CREATE UNIQUE INDEX userNameIDIdx ON pkiUsers (nameID)" );
if( cryptStatusOK( status ) && isCertStore( dbmsInfo ) )
status = dbmsStaticUpdate(
"CREATE UNIQUE INDEX logCertIDIdx ON certLog (certID)" );
if( cryptStatusOK( status ) && isCertStore( dbmsInfo ) )
{
char dummyCertID[ DBXKEYID_BUFFER_SIZE ];
/* Create a special dummy certID with an out-of-band value to mark
the first entry in the log */
memset( dummyCertID, '-', MAX_ENCODED_DBXKEYID_SIZE );
dummyCertID[ MAX_ENCODED_DBXKEYID_SIZE ] = '\0';
/* Add the initial log entry recording the creation of the log */
status = updateCertLog( dbmsInfo, CRYPT_CERTACTION_CREATE,
dummyCertID, NULL, NULL, NULL, 0,
DBMS_UPDATE_NORMAL );
}
if( cryptStatusError( status ) )
{
/* Undo the creation of the various tables */
dbmsStaticUpdate( "DROP TABLE certificates" );
dbmsStaticUpdate( "DROP TABLE CRLs" );
if( isCertStore( dbmsInfo ) )
{
dbmsStaticUpdate( "DROP TABLE pkiUsers" );
dbmsStaticUpdate( "DROP TABLE certRequests" );
dbmsStaticUpdate( "DROP TABLE certLog" );
}
return( CRYPT_ERROR_WRITE );
}
/* If the back-end doesn't support access permissions (generally only
toy ones like Access and Paradox), or it's not a CA cert store,
we're done */
if( !hasPermissions || !isCertStore( dbmsInfo ) )
return( CRYPT_OK );
/* Set access controls for the cert store tables:
Users CAs
certRequests: - INS,SEL,DEL
certificates: SEL INS,SEL,DEL
CRLs: - INS,SEL,DEL
pkiUsers: - INS,SEL,DEL
certLog: - INS,SEL
Once role-based access controls are enabled, we can allow only the CA
user to update the certstore tables, and allow others only read
access to the certs table. In addition the revocation should be
phrased as REVOKE ALL, GRANT <permitted> rather than revoking specific
privileges, since each database vendor has their own nonstandard
additional privileges that a specific revoke won't cover.
Unfortunately configuring this will be somewhat difficult since it
requires that cryptlib users create database user roles, which in turn
requires that they read the manual */
#if 1
dbmsStaticUpdate( "REVOKE UPDATE ON certificates FROM PUBLIC" );
dbmsStaticUpdate( "REVOKE UPDATE ON CRLs FROM PUBLIC" );
dbmsStaticUpdate( "REVOKE UPDATE ON pkiUsers FROM PUBLIC" );
dbmsStaticUpdate( "REVOKE UPDATE ON certRequests FROM PUBLIC" );
dbmsStaticUpdate( "REVOKE DELETE,UPDATE ON certLog FROM PUBLIC" );
#else
dbmsStaticUpdate( "REVOKE ALL ON certificates FROM PUBLIC" );
dbmsStaticUpdate( "GRANT INSERT,SELECT,DELETE ON certificates TO ca" );
dbmsStaticUpdate( "GRANT SELECT ON certificates TO PUBLIC" );
dbmsStaticUpdate( "REVOKE ALL ON CRLs FROM PUBLIC" );
dbmsStaticUpdate( "GRANT INSERT,SELECT,DELETE ON CRLs TO ca" );
dbmsStaticUpdate( "REVOKE ALL ON pkiUsers FROM PUBLIC" );
dbmsStaticUpdate( "GRANT INSERT,SELECT,DELETE ON pkiUsers TO ca" );
dbmsStaticUpdate( "REVOKE ALL ON certRequests FROM PUBLIC" );
dbmsStaticUpdate( "GRANT INSERT,SELECT,DELETE ON certRequests TO ca" );
dbmsStaticUpdate( "REVOKE ALL ON certLog FROM PUBLIC" );
dbmsStaticUpdate( "GRANT INSERT,SELECT ON certLog TO ca" );
#endif /* 1 */
return( CRYPT_OK );
}
/* Return status info for the keyset */
static BOOLEAN isBusyFunction( KEYSET_INFO *keysetInfo )
{
return( ( keysetInfo->keysetDBMS->flags & \
( DBMS_FLAG_UPDATEACTIVE | DBMS_FLAG_QUERYACTIVE ) ) ? \
TRUE : FALSE );
}
/* Open a connection to a database */
static int initFunction( KEYSET_INFO *keysetInfo, const char *name,
const CRYPT_KEYOPT_TYPE options )
{
DBMS_INFO *dbmsInfo = keysetInfo->keysetDBMS;
int featureFlags, status;
/* Perform a database back-end specific open */
status = dbmsOpen( name, ( options == CRYPT_KEYOPT_READONLY ) ? \
options : CRYPT_KEYOPT_NONE, &featureFlags );
if( cryptStatusError( status ) )
{
endDbxSession( keysetInfo );
return( status );
}
/* If the back-end is read-only (which would be extremely unusual,
usually related to misconfigured DBMS access permissions) and we're
not opening it in read-only mode, signal an error */
if( ( featureFlags & DBMS_HAS_NOWRITE ) && \
options != CRYPT_KEYOPT_READONLY )
{
endDbxSession( keysetInfo );
return( CRYPT_ERROR_PERMISSION );
}
/* If we're being asked to create a new database, create it and exit */
if( options == CRYPT_KEYOPT_CREATE )
{
status = createDatabase( dbmsInfo,
( featureFlags & DBMS_HAS_PRIVILEGES ) ? \
TRUE : FALSE );
if( cryptStatusOK( status ) && isCertStore( dbmsInfo ) )
status = updateCertLog( dbmsInfo, CRYPT_CERTACTION_CONNECT,
NULL, NULL, NULL, NULL, 0,
DBMS_UPDATE_NORMAL );
if( cryptStatusError( status ) )
{
dbmsClose();
endDbxSession( keysetInfo );
}
return( status );
}
/* Check to see whether it's a cert store. We do this by checking for
the presence of the cert store creation entry in the log, this is
always present with an action value of CRYPT_CERTACTION_CREATE */
status = dbmsStaticQuery(
"SELECT certData FROM certLog WHERE action = "
TEXT_CERTACTION_CREATE,
DBMS_CACHEDQUERY_NONE, DBMS_QUERY_CHECK );
if( cryptStatusOK( status ) )
{
/* It's a cert store, if we're opening it as a non-cert-store it has
to be in read-only mode. We return an error rather than quietly
changing the access mode to read-only both to make it explicit to
the user at open time that they can't make changes and because we
need to have the read-only flag set when we open the database to
optimise the buffering and locking strategy, setting it at this
point is too late */
if( !isCertStore( dbmsInfo ) )
{
if( options != CRYPT_KEYOPT_READONLY )
{
dbmsClose();
endDbxSession( keysetInfo );
status = CRYPT_ERROR_PERMISSION;
}
/* Remember that even though it's not functioning as a cert
store, we can still perform some extended queries on it based
on fields that are only present in cert stores */
dbmsInfo->flags |= DBMS_FLAG_CERTSTORE_FIELDS;
return( status );
}
/* If this isn't a read-only open then record a connection to the
store */
if( options != CRYPT_KEYOPT_READONLY )
{
status = updateCertLog( dbmsInfo, CRYPT_CERTACTION_CONNECT,
NULL, NULL, NULL, NULL, 0,
DBMS_UPDATE_NORMAL );
if( cryptStatusError( status ) )
{
dbmsClose();
endDbxSession( keysetInfo );
}
}
return( status );
}
/* It's not a cert store, if we're expecting to open it as one tell the
caller */
if( isCertStore( dbmsInfo ) )
{
dbmsClose();
endDbxSession( keysetInfo );
return( CRYPT_ARGERROR_NUM1 );
}
/* Since the failure of the query above will set the extended error
information, we have to explicitly clear it here to avoid making the
(invisible) query side-effects visible to the user */
dbmsInfo->errorCode = 0;
memset( dbmsInfo->errorMessage, 0, MAX_ERRMSG_SIZE );
return( CRYPT_OK );
}
/* Close the connection to a database */
static void shutdownFunction( KEYSET_INFO *keysetInfo )
{
DBMS_INFO *dbmsInfo = keysetInfo->keysetDBMS;
/* If it's a cert store opened in read/write mode, record a closed
connection to the store */
if( isCertStore( dbmsInfo ) && \
keysetInfo->options != CRYPT_KEYOPT_READONLY )
updateCertLog( dbmsInfo, CRYPT_CERTACTION_DISCONNECT, NULL, NULL,
NULL, NULL, 0, DBMS_UPDATE_NORMAL );
/* If we're in the middle of a query, cancel it. We always use
DBMS_CACHEDQUERY_NONE because this is the only query type that can
remain active outside the keyset object */
if( dbmsInfo->flags & DBMS_FLAG_QUERYACTIVE )
dbmsStaticQuery( NULL, DBMS_CACHEDQUERY_NONE, DBMS_QUERY_CANCEL );
dbmsClose();
endDbxSession( keysetInfo );
}
/****************************************************************************
* *
* Database Access Routines *
* *
****************************************************************************/
/* Set up the function pointers to the keyset methods */
int setAccessMethodDBMS( KEYSET_INFO *keysetInfo,
const CRYPT_KEYSET_TYPE type )
{
int status = CRYPT_ERROR;
assert( DBMS_CACHEDQUERY_LAST == NO_CACHED_QUERIES );
/* Set up the lower-level interface functions */
status = initDbxSession( keysetInfo, type );
if( cryptStatusError( status ) )
return( status );
/* Set the access method pointers */
keysetInfo->initFunction = initFunction;
keysetInfo->shutdownFunction = shutdownFunction;
initDBMSread( keysetInfo );
initDBMSwrite( keysetInfo );
if( type == CRYPT_KEYSET_ODBC_STORE || \
type == CRYPT_KEYSET_DATABASE_STORE || \
type == CRYPT_KEYSET_PLUGIN_STORE )
initDBMSCA( keysetInfo );
keysetInfo->isBusyFunction = isBusyFunction;
return( CRYPT_OK );
}
#endif /* USE_DBMS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -