In addition to the significant built-in capabilities of
Lua, we have written or integrated many extension libraries which make
script writing more powerful and convenient. These libraries (sometimes called modules) are compiled if necessary and installed along with
Nmap. They have their own directory, nselib, which
is installed in the configured Nmap data directory. Scripts need only
require
the default libraries in order to use them.
Adding C Modules to Nselib
A few of the modules included in nselib are written in C or C++
rather than Lua. Two examples are bit
and pcre. We recommend that modules
be written in Lua if possible, but C and C++ may be more
appropriate if performance is critical or (as with
the pcre and openssl
modules) you are linking to an existing C library. This section
describes how to write your own compiled extensions to nselib.
The Lua C API is described at length in
Programming in Lua, Second Edition,
so this is a short summary. C modules consist of functions that
follow the protocol of the
lua_CFunction
type. The functions are registered with Lua and assembled into a
library by calling the
luaL_register
function. A special initialization function provides the interface
between the module and the rest of the NSE code. By convention the
initialization function is named in the form
luaopen_<module>.
The smallest compiled module that comes with NSE is
bit,
and one of the most straightforward is
openssl.
These modules serve as good examples for a beginning module
writer. The
source code for bit is found in
nse_bit.cc and
nse_bit.h, while the
openssl source is in nse_openssl.cc and
nse_openssl.h. Most of the other compiled modules
follow this nse_<module name>.cc naming convention.
Reviewing the openssl module shows that one of the
functions in nse_openssl.cc is
l_md5, which calculates an MD5 digest. Its
function prototype is:
static int l_md5(lua_State *L);
The prototype shows that l_md5 matches the
lua_CFunction type. The function is static because it
does not have to be visible to other compiled code. Only an address is required
to register it with Lua. Later in the file,
l_md5 is entered into an array of type
luaL_reg and associated with the name
md5:
static const struct luaL_reg openssllib[] = {
{ "md5", l_md5 },
{ NULL, NULL }
};
This function will now be known as md5 to NSE. Next the library is registered with a call to
luaL_register inside the initialization
function luaopen_openssl, as shown
next. Some lines relating to the registration of
OpenSSL BIGNUM types have been omitted:
LUALIB_API int luaopen_openssl(lua_State *L) {
luaL_register(L, OPENSSLLIBNAME, openssllib);
return 1;
}
The function luaopen_openssl
is the only function in the file that is exposed in
nse_openssl.h. OPENSSLLIBNAME is simply the string
"openssl".
After a compiled module is written, it must be added to NSE by including
it in the list of standard libraries in
nse_init.cc. Then the module's
source file names must be added to
Makefile.in in the appropriate places. For both these tasks you can
simply follow the example of the other C modules. For the
Windows build, the new source files must be added to the
mswin32/nmap.vcproj project file using MS Visual Studio (see the section called “Compile from Source Code”).