Nmap Development mailing list archives

Re: [NSE][PATCH] OpenSSL bindings for NSE


From: David Fifield <david () bamsoftware com>
Date: Wed, 3 Sep 2008 15:03:03 -0600

On Sun, Aug 31, 2008 at 02:33:11PM +0200, Sven Klemm wrote:
I've updated the openssl bindings. The module is now built as a static  
module. The module is built when OpenSSL is available and Lua is enabled.

The module currently includes all the functions I needed for writing the 
SSH hostkey script, which are mostly bignum functions. I've also added 
documentation for the included functions.

I checked out your nse_openssl branch and built it with
--without-openssl. Then I ran

        nmap --script=SSH-hostkey -p ssh goomba.bamsoftware.com --script-args=ssh_hostkey=all

I got the error

        SCRIPT ENGINE: Initiating script scanning.
        SCRIPT ENGINE: Script scanning mail.bamsoftware.com (64.81.99.73).
        SCRIPT ENGINE: error while initializing script rules:
        ./scripts/SSH-hostkey.nse:34: module 'openssl' not found:
                no field package.preload['openssl']
                no file './nselib/openssl.lua'
                no file './openssl.lua'
                no file '/usr/local/share/lua/5.1/openssl.lua'
                no file '/usr/local/share/lua/5.1/openssl/init.lua'
                no file '/usr/local/lib/lua/5.1/openssl.lua'
                no file '/usr/local/lib/lua/5.1/openssl/init.lua'
                no file './nselib-bin/openssl.so'
                no file './openssl.so'
                no file '/usr/local/lib/lua/5.1/openssl.so'
                no file '/usr/local/lib/lua/5.1/loadall.so'
        stack traceback:
                [C]: in function 'require'
                ./scripts/SSH-hostkey.nse:34: in main chunk
                [C]: ?
                [C]: ?

        SCRIPT ENGINE: Script scanning completed.
        SCRIPT ENGINE: Aborting script scan.

I agree that the OpenSSL library could be useful. Is there a way to
handle this situation gracefully? As it is it halts all script scanning
when the openssl module can't be loaded.

Can you explain the "BIGNUM" metatable? It appears to be used for type
checking or arguments:

  bignum_data_t * a = (bignum_data_t *) luaL_checkudata(L, 1, "BIGNUM");

but aren't metatable methods supposed to have names like __add and
__sub? The "BIGNUM" table has the OpenSSL names num_bits, num_bytes,
etc.

Any opinions about integrating this into nmap?

Cheers,
Sven

-- 
Sven Klemm
http://cthulhu.c3d2.de/~sven/


Index: Makefile.in
===================================================================
--- Makefile.in       (.../nmap)      (revision 9880)
+++ Makefile.in       (.../nmap-exp/sven/nse_openssl) (revision 9880)
@@ -63,6 +63,11 @@
 NSE_HDRS=nse_main.h nse_nsock.h nse_init.h nse_fs.h nse_nmaplib.h nse_debug.h nse_macros.h nse_pcrelib.h 
nse_binlib.h nse_hash.h nse_bit.h
 NSE_OBJS=nse_main.o nse_nsock.o nse_init.o nse_fs.o nse_nmaplib.o nse_debug.o nse_pcrelib.o nse_binlib.o nse_hash.o 
nse_bit.o
 NSESTDLIB=nsestdlib
+ifneq (@OPENSSL_LIBS@,)
+NSE_SRC+=nse_openssl.cc
+NSE_HDRS+=nse_openssl.h
+NSE_OBJS+=nse_openssl.o
+endif
 endif
 
 export SRCS = main.cc nmap.cc targets.cc tcpip.cc nmap_error.cc utils.cc idle_scan.cc osscan.cc osscan2.cc output.cc 
scan_engine.cc timing.cc charpool.cc services.cc protocols.cc nmap_rpc.cc portlist.cc NmapOps.cc TargetGroup.cc 
Target.cc FingerPrintResults.cc service_scan.cc NmapOutputTable.cc MACLookup.cc nmap_tty.cc nmap_dns.cc traceroute.cc 
portreasons.cc $(NSE_SRC) @COMPAT_SRCS@
Index: nse_init.cc
===================================================================
--- nse_init.cc       (.../nmap)      (revision 9880)
+++ nse_init.cc       (.../nmap-exp/sven/nse_openssl) (revision 9880)
@@ -8,6 +8,10 @@
 #include "nse_pcrelib.h"
 #include "nse_bit.h"
 
+#ifdef HAVE_OPENSSL
+#include "nse_openssl.h"
+#endif
+
 #include "nse_binlib.h"
 #include "nse_hash.h"
 
@@ -223,6 +227,9 @@
     {NSE_BINLIBNAME, luaopen_binlib},
     {NSE_HASHLIBNAME, luaopen_hashlib},
     {BITLIBNAME, luaopen_bit}, // bit library
+#ifdef HAVE_OPENSSL
+    {OPENSSLLIBNAME, luaopen_openssl}, // openssl bindings
+#endif
   };
 
   luaL_openlibs(L); // opens all standard libraries
Index: docs/scripting.xml
===================================================================
--- docs/scripting.xml        (.../nmap)      (revision 9880)
+++ docs/scripting.xml        (.../nmap-exp/sven/nse_openssl) (revision 9880)
@@ -1143,6 +1143,149 @@
         <indexterm class="endofrange" startref="nse-pcre-indexterm"/>
     </sect2>
      
+      <sect2 id="nse-openssl">
+        <indexterm class="startofrange" id="nse-openssl-indexterm"><primary><varname>openssl</varname> NSE 
module</primary></indexterm>
+        <indexterm><primary>OpenSSL</primary><secondary>in NSE</secondary></indexterm>
+        <title>OpenSSL NSE bindings</title>
+
+        <para>
+     The <literal>openssl</literal> module provides functions for 
+     dealing with multiprecision integers. The functions reside inside the 
+     <literal>openssl</literal> namespace.
+       </para>
+
+     <variablelist>
+
+         <varlistentry>
+           <term><option>openssl.bignum_num_bits( bignum )</option></term>
+           <listitem>
+             <para>Returns the size of <literal>bignum</literal> in bits.</para>
+           </listitem>
+         </varlistentry>
+
+         <varlistentry>
+           <term><option>openssl.bignum_num_bytes( bignum )</option></term>
+           <listitem>
+             <para>Returns the size of <literal>bignum</literal> in bytes.</para>
+           </listitem>
+         </varlistentry>
+
+         <varlistentry>
+           <term><option>openssl.bignum_set_bit( bignum, position )</option></term>
+           <listitem>
+             <para>Sets bit at <literal>position</literal> in <literal>bignum</literal>.</para>
+           </listitem>
+         </varlistentry>
+
+         <varlistentry>
+           <term><option>openssl.bignum_clear_bit( bignum, position )</option></term>
+           <listitem>
+             <para>Clears bit at <literal>position</literal> in <literal>bignum</literal>.</para>
+           </listitem>
+         </varlistentry>
+
+         <varlistentry>
+           <term><option>openssl.bignum_is_bit_set( bignum, position )</option></term>
+           <listitem>
+             <para>Get bit at <literal>position</literal> in <literal>bignum</literal>.</para>
+           </listitem>
+         </varlistentry>
+
+         <varlistentry>
+           <term><option>openssl.bignum_set_negative( bignum, negative )</option></term>
+           <listitem>
+             <para>Set sign of <literal>bignum</literal>. If <literal>negative</literal> is <literal>false</literal> 
the sign becomes positive otherwise it becomes negative.</para>
+           </listitem>
+         </varlistentry>
+
+         <varlistentry>
+           <term><option>openssl.bignum_is_negative( bignum )</option></term>
+           <listitem>
+             <para>Check sign of <literal>bignum</literal>.</para>
+           </listitem>
+         </varlistentry>
+
+         <varlistentry>
+           <term><option>openssl.bignum_bin2bn( string )</option></term>
+           <listitem>
+             <para>Converts binary encoded <literal>string</literal> into a <literal>bignum</literal>.</para>
+           </listitem>
+         </varlistentry>
+
+         <varlistentry>
+           <term><option>openssl.bignum_dec2bn( string )</option></term>
+           <listitem>
+             <para>Converts decimal encoded <literal>string</literal> into a <literal>bignum</literal>.</para>
+           </listitem>
+         </varlistentry>
+
+         <varlistentry>
+           <term><option>openssl.bignum_hex2bn( string )</option></term>
+           <listitem>
+             <para>Converts hex-encoded <literal>string</literal> into a <literal>bignum</literal>.</para>
+           </listitem>
+         </varlistentry>
+
+         <varlistentry>
+           <term><option>openssl.bignum_bn2bin( bignum )</option></term>
+           <listitem>
+             <para>Converts <literal>bignum</literal> into a binary encoded string.</para>
+           </listitem>
+         </varlistentry>
+
+         <varlistentry>
+           <term><option>openssl.bignum_bn2dec( bignum )</option></term>
+           <listitem>
+             <para>Converts <literal>bignum</literal> into a decimal encoded string.</para>
+           </listitem>
+         </varlistentry>
+
+         <varlistentry>
+           <term><option>openssl.bignum_bn2hex( bignum )</option></term>
+           <listitem>
+             <para>Converts <literal>bignum</literal> into a hex-encoded string.</para>
+           </listitem>
+         </varlistentry>
+
+         <varlistentry>
+           <term><option>openssl.bignum_rand( bits )</option></term>
+           <listitem>
+             <para>Returns random <literal>bignum</literal> with <literal>bits</literal> bit size.</para>
+           </listitem>
+         </varlistentry>
+
+         <varlistentry>
+           <term><option>openssl.bignum_pseudo_rand( bits )</option></term>
+           <listitem>
+             <para>Returns pseudo random <literal>bignum</literal> with <literal>bits</literal> bit size.</para>
+           </listitem>
+         </varlistentry>
+
+         <varlistentry>
+           <term><option>openssl.bignum_mod_exp( a, p, m )</option></term>
+           <listitem>
+             <para>Returns bignum which is the result of <literal>a</literal>^<literal>p</literal> mod 
<literal>m</literal>.</para>
+           </listitem>
+         </varlistentry>
+
+         <varlistentry>
+           <term><option>openssl.rand_bytes( bytes )</option></term>
+           <listitem>
+             <para>Returns a string of <literal>bytes</literal> length with random data.</para>
+           </listitem>
+         </varlistentry>
+
+         <varlistentry>
+           <term><option>openssl.rand_pseudo_bytes( bytes )</option></term>
+           <listitem>
+             <para>Returns a string of <literal>bytes</literal> length with pseudo random data.</para>
+           </listitem>
+         </varlistentry>
+
+     </variablelist>
+        <indexterm class="endofrange" startref="nse-openssl-indexterm"/>
+    </sect2>
+
      <sect2 id="nse-lib-ipOps">
      <title>IP Operations</title>
         <indexterm><primary><varname>ipOps</varname> NSE module</primary></indexterm>
Index: nse_openssl.h
===================================================================
--- nse_openssl.h     (.../nmap)      (revision 0)
+++ nse_openssl.h     (.../nmap-exp/sven/nse_openssl) (revision 9880)
@@ -0,0 +1,19 @@
+#include "../nmap_config.h"
+
+#if HAVE_OPENSSL
+
+#ifndef OPENSSLLIB
+#define OPENSSLLIB
+
+#define OPENSSLLIBNAME "openssl"
+
+extern "C" {
+#include "lua.h"
+#include "lauxlib.h"
+}
+
+LUALIB_API int luaopen_openssl(lua_State *L);
+
+#endif
+
+#endif
Index: nse_openssl.cc
===================================================================
--- nse_openssl.cc    (.../nmap)      (revision 0)
+++ nse_openssl.cc    (.../nmap-exp/sven/nse_openssl) (revision 9880)
@@ -0,0 +1,258 @@
+#include "nmap_config.h"
+
+/* OpenSSL library for lua
+ * adapted from lmd5 library (http://www.tecgraf.puc-rio.br/~lhf/ftp/lua/)
+ * Original code written by Luiz Henrique de Figueiredo <lhf () tecgraf puc-rio br>
+ * Adapted for NMap by Thomas Buchanan <tbuchanan () thecompassgrp net>
+ * bignum and rand_bytes functions added by Sven Klemm <sven () c3d2 de>
+ */
+
+#include <openssl/crypto.h>
+#include <openssl/bn.h>
+#include <openssl/rand.h>
+
+#include "nse_openssl.h"
+
+typedef struct bignum_data {
+  BIGNUM * bn;
+} bignum_data_t;
+
+static int l_bignum_bin2bn( lua_State *L ) /** bignum_bin2bn( string s ) */
+{
+  size_t len;
+  const unsigned char * s = (unsigned char *) luaL_checklstring( L, 1, &len );
+  BIGNUM * num = BN_new();
+  BN_bin2bn( s, len, num );
+  bignum_data_t * data = (bignum_data_t *) lua_newuserdata( L, sizeof(bignum_data_t));
+  luaL_getmetatable( L, "BIGNUM" );
+  lua_setmetatable( L, -2 );
+  data->bn = num;
+  return 1;
+}
+
+static int l_bignum_dec2bn( lua_State *L ) /** bignum_dec2bn( string s ) */
+{
+  const char * s = luaL_checkstring( L, 1 );
+  BIGNUM * num = BN_new();
+  BN_dec2bn( &num, s );
+  bignum_data_t * data = (bignum_data_t *) lua_newuserdata( L, sizeof(bignum_data_t));
+  luaL_getmetatable( L, "BIGNUM" );
+  lua_setmetatable( L, -2 );
+  data->bn = num;
+  return 1;
+}
+
+static int l_bignum_hex2bn( lua_State *L ) /** bignum_hex2bn( string s ) */
+{
+  const char * s = luaL_checkstring( L, 1 );
+  BIGNUM * num = BN_new();
+  BN_hex2bn( &num, s );
+  bignum_data_t * data = (bignum_data_t *) lua_newuserdata( L, sizeof(bignum_data_t));
+  luaL_getmetatable( L, "BIGNUM" );
+  lua_setmetatable( L, -2 );
+  data->bn = num;
+  return 1;
+}
+
+static int l_bignum_rand( lua_State *L ) /** bignum_rand( number bits ) */
+{
+  size_t bits = luaL_checkint( L, 1 );
+  BIGNUM * num = BN_new();
+  BN_rand( num, bits, -1, 0 );
+  bignum_data_t * data = (bignum_data_t *) lua_newuserdata( L, sizeof(bignum_data_t));
+  luaL_getmetatable( L, "BIGNUM" );
+  lua_setmetatable( L, -2 );
+  data->bn = num;
+  return 1;
+}
+
+static int l_bignum_pseudo_rand( lua_State *L ) /** bignum_pseudo_rand( number bits ) */
+{
+  size_t bits = luaL_checkint( L, 1 );
+  BIGNUM * num = BN_new();
+  BN_pseudo_rand( num, bits, -1, 0 );
+  bignum_data_t * data = (bignum_data_t *) lua_newuserdata( L, sizeof(bignum_data_t));
+  luaL_getmetatable( L, "BIGNUM" );
+  lua_setmetatable( L, -2 );
+  data->bn = num;
+  return 1;
+}
+
+static int l_bignum_mod_exp( lua_State *L ) /** bignum_mod_exp( BIGNUM a, BIGNUM p, BIGNUM m ) */
+{
+  bignum_data_t * a = (bignum_data_t *) luaL_checkudata(L, 1, "BIGNUM");
+  bignum_data_t * p = (bignum_data_t *) luaL_checkudata(L, 2, "BIGNUM");
+  bignum_data_t * m = (bignum_data_t *) luaL_checkudata(L, 3, "BIGNUM");
+  BIGNUM * result = BN_new();
+  BN_CTX * ctx = BN_CTX_new();
+  BN_CTX_init( ctx );
+  BN_mod_exp( result, a->bn, p->bn, m->bn, ctx );
+  BN_CTX_free( ctx );
+  bignum_data_t * data = (bignum_data_t *) lua_newuserdata( L, sizeof(bignum_data_t));
+  luaL_getmetatable( L, "BIGNUM" );
+  lua_setmetatable( L, -2 );
+  data->bn = result;
+  return 1;
+}
+
+static int l_bignum_num_bits( lua_State *L ) /** bignum_num_bits( BIGNUM bn ) */
+{
+  bignum_data_t * userdata = (bignum_data_t *) luaL_checkudata(L, 1, "BIGNUM");
+  lua_pushnumber( L, BN_num_bits( userdata->bn) );
+  return 1;
+}
+
+static int l_bignum_num_bytes( lua_State *L ) /** bignum_num_bytes( BIGNUM bn ) */
+{
+  bignum_data_t * userdata = (bignum_data_t *) luaL_checkudata(L, 1, "BIGNUM");
+  lua_pushnumber( L, BN_num_bytes( userdata->bn) );
+  return 1;
+}
+
+static int l_bignum_set_bit( lua_State *L ) /** bignum_set_bit( BIGNUM bn, number position ) */
+{
+  bignum_data_t * userdata = (bignum_data_t *) luaL_checkudata(L, 1, "BIGNUM");
+  int position = luaL_checkint( L, 2 );
+  BN_set_bit( userdata->bn, position );
+  return 0;
+}
+
+static int l_bignum_clear_bit( lua_State *L ) /** bignum_clear_bit( BIGNUM bn, number position ) */
+{
+  bignum_data_t * userdata = (bignum_data_t *) luaL_checkudata(L, 1, "BIGNUM");
+  int position = luaL_checkint( L, 2 );
+  BN_clear_bit( userdata->bn, position );
+  return 0;
+}
+
+static int l_bignum_is_bit_set( lua_State *L ) /** bignum_set_bit( BIGNUM bn, number position ) */
+{
+  bignum_data_t * userdata = (bignum_data_t *) luaL_checkudata(L, 1, "BIGNUM");
+  int position = luaL_checkint( L, 2 );
+  lua_pushboolean( L, BN_is_bit_set( userdata->bn, position ) );
+  return 1;
+}
+
+static int l_bignum_set_negative( lua_State *L ) /** bignum_set_negative( BIGNUM bn ) */
+{
+  bignum_data_t * userdata = (bignum_data_t *) luaL_checkudata(L, 1, "BIGNUM");
+  int value = lua_toboolean(L, 2);
+  BN_set_negative( userdata->bn, value );
+  return 0;
+}
+
+static int l_bignum_is_negative( lua_State *L ) /** bignum_is_negative( BIGNUM bn ) */
+{
+  bignum_data_t * userdata = (bignum_data_t *) luaL_checkudata(L, 1, "BIGNUM");
+  lua_pushboolean( L, BN_is_negative( userdata->bn) );
+  return 1;
+}
+
+static int l_bignum_bn2bin( lua_State *L ) /** bignum_bn2bin( BIGNUM bn ) */
+{
+  bignum_data_t * userdata = (bignum_data_t *) luaL_checkudata(L, 1, "BIGNUM");
+  unsigned char * result = (unsigned char *) malloc( BN_num_bytes( userdata->bn ) );
+  int len = BN_bn2bin( userdata->bn, result );
+  lua_pushlstring( L, (char *) result, len );
+  free( result );
+  return 1;
+}
+
+static int l_bignum_bn2dec( lua_State *L ) /** bignum_bn2dec( BIGNUM bn ) */
+{
+  bignum_data_t * userdata = (bignum_data_t *) luaL_checkudata(L, 1, "BIGNUM");
+  char * result = BN_bn2dec( userdata->bn );
+  lua_pushstring( L, result );
+  OPENSSL_free( result );
+  return 1;
+}
+
+static int l_bignum_bn2hex( lua_State *L ) /** bignum_bn2hex( BIGNUM bn ) */
+{
+  bignum_data_t * userdata = (bignum_data_t *) luaL_checkudata(L, 1, "BIGNUM");
+  char * result = BN_bn2hex( userdata->bn );
+  lua_pushstring( L, result );
+  OPENSSL_free( result );
+  return 1;
+}
+
+static int l_bignum_free( lua_State *L ) /** bignum_free( bignum ) */
+{
+  bignum_data_t * userdata = (bignum_data_t *) luaL_checkudata(L, 1, "BIGNUM");
+  BN_clear_free( userdata->bn );
+  return 0;
+}
+
+static int l_rand_bytes( lua_State *L ) /** rand_bytes( number bytes ) */
+{
+  size_t len = luaL_checkint( L, 1 );
+  unsigned char * result = (unsigned char *) malloc( len );
+  RAND_bytes( result, len );
+  lua_pushlstring( L, (char *) result, len );
+  free( result );
+  return 1;
+}
+
+static int l_rand_pseudo_bytes( lua_State *L ) /** rand_pseudo_bytes( number bytes ) */
+{
+  size_t len = luaL_checkint( L, 1 );
+  unsigned char * result = (unsigned char *) malloc( len );
+  RAND_pseudo_bytes( result, len );
+  lua_pushlstring( L, (char *) result, len );
+  free( result );
+  return 1;
+}
+
+static const struct luaL_reg bignum_methods[] = {
+  { "num_bits", l_bignum_num_bits },
+  { "num_bytes", l_bignum_num_bytes },
+  { "to_bin", l_bignum_bn2bin },
+  { "to_dec", l_bignum_bn2dec },
+  { "to_hex", l_bignum_bn2hex },
+  { "is_bit_set", l_bignum_is_bit_set },
+  { "set_bit", l_bignum_set_bit },
+  { "clear_bit", l_bignum_clear_bit },
+  { "is_bit_set", l_bignum_is_bit_set },
+  { "set_negative", l_bignum_set_negative },
+  { "is_negative", l_bignum_is_negative },
+  { "__gc", l_bignum_free },
+  { NULL, NULL }
+};
+
+static const struct luaL_reg openssllib[] = {
+  { "bignum_num_bits", l_bignum_num_bits },
+  { "bignum_num_bytes", l_bignum_num_bytes },
+  { "bignum_set_bit", l_bignum_set_bit },
+  { "bignum_clear_bit", l_bignum_clear_bit },
+  { "bignum_is_bit_set", l_bignum_is_bit_set },
+  { "bignum_set_negative", l_bignum_set_negative },
+  { "bignum_is_negative", l_bignum_is_negative },
+  { "bignum_bin2bn", l_bignum_bin2bn },
+  { "bignum_dec2bn", l_bignum_dec2bn },
+  { "bignum_hex2bn", l_bignum_hex2bn },
+  { "bignum_rand", l_bignum_rand },
+  { "bignum_pseudo_rand", l_bignum_pseudo_rand },
+  { "bignum_bn2bin", l_bignum_bn2bin },
+  { "bignum_bn2dec", l_bignum_bn2dec },
+  { "bignum_bn2hex", l_bignum_bn2hex },
+  { "bignum_mod_exp", l_bignum_mod_exp },
+  { "rand_bytes", l_rand_bytes},
+  { "rand_pseudo_bytes", l_rand_pseudo_bytes},
+  { NULL, NULL }
+};
+
+LUALIB_API int luaopen_openssl(lua_State *L) {
+
+  luaL_openlib(L, OPENSSLLIBNAME, openssllib, 0);
+
+  // create metatable for bignum
+  luaL_newmetatable( L, "BIGNUM" );
+  // metatable.__index = metatable
+  lua_pushvalue( L, -1 );
+  lua_setfield( L, -2, "__index" );
+  // register methods
+  luaL_register( L, NULL, bignum_methods );
+
+  return 1;
+}
+


_______________________________________________
Sent through the nmap-dev mailing list
http://cgi.insecure.org/mailman/listinfo/nmap-dev
Archived at http://SecLists.Org

_______________________________________________
Sent through the nmap-dev mailing list
http://cgi.insecure.org/mailman/listinfo/nmap-dev
Archived at http://SecLists.Org


Current thread: