Code access security (CAS) is a mechanism designed to
protect systems from dangerous APIs that are invoked by untrusted code.
CAS has nothing to do with user authentication or authorization; it is a
mechanism allowing two pieces of code to communicate in an
uncompromisable manner.
In the Dynamics
AX implementation of CAS, trusted code is defined as code from the AOT
running on the Application Object Server (AOS). The first part of the
definition ensures that the code is written by a trusted X++ developer.
Developer privileges are the highest level of privileges in Dynamics AX
and should be granted only to trusted personnel. The second part of the
definition ensures the code the trusted developer has written hasn’t
been tampered with. If the code executes outside the AOS—on a client,
for example—it can’t be trusted because of the possibility that it was
altered on the client side before execution. Untrusted code also
includes code that is executed via the runBuf and evalBuf methods. These methods are typically used to execute code generated at run time based on user input.
CAS enables a
secure handshake between an API and its consumer. Only consumers who
provide the right handshake can invoke the API. Any other invocation
raises an exception.
The secure handshake is established through the CodeAccessPermission class or one of its specializations. The consumer must request permission to call the API, which is done by calling CodeAccessPermission.assert. The API verifies that the consumer has the right permissions by calling CodeAccessPermission.demand. The demand
method searches the call stack for a matching assertion. If untrusted
code exists on the call stack before the matching assert, an exception
is raised. This process is illustrated in Figure 1.
Here is an example of a dangerous API protected by CAS and a consumer providing the right permissions to invoke the API.
{ // Delete any given file on the server public server static boolean deleteFile(Filename _fileName) { FileIOPermission fileIOPerm; ; // Check file I/O permission fileIOPerm = new FileIOPermission(_fileName, 'w'); fileIOPerm.demand();
// Delete the file System.IO.File::Delete(_filename); } }
class Consumer { // Delete the temporary file on the server public server static void deleteTmpFile() { FileIOPermission fileIOPerm; FileName filename = @"c:\tmp\file.tmp"; ; // Request file I/O permission fileIOPerm = new FileIOPermission(filename, 'w'); fileIOPerm.assert();
// Use CAS protected API to delete the file WinApiServer::deleteFile(filename); } }
|
WinAPIServer::deleteFile is considered a dangerous API because it exposes the .NET API System.IO.File::Delete(string fileName).
Exposing this API on the server is dangerous because it allows the user
to remotely delete any file on the server, possibly bringing the server
down. In the example, WinApiServer::deleteFile
demands that the caller has asserted that the input filename is valid.
The demand prevents use of the API from the client tier and from any
code not stored in the AOT.
Caution
When using assert, make sure that you don’t create a new API that is just as dangerous as the one CAS has secured. When you call assert,
you are asserting that your code doesn’t expose the same vulnerability
that required the protection of CAS. For example, had the deleteTmpFile method in the foregoing example taken the filename as a parameter, it could have been used to bypass the CAS protection of WinApi::deleteFile and delete any file on the server. |