mirror of
https://github.com/nmap/nmap.git
synced 2025-12-06 04:31:29 +00:00
merging nse_openssl branch
This commit is contained in:
11
Makefile.in
11
Makefile.in
@@ -62,9 +62,14 @@ INSTALLNDIFF=@INSTALLNDIFF@
|
|||||||
UNINSTALLZENMAP=@UNINSTALLZENMAP@
|
UNINSTALLZENMAP=@UNINSTALLZENMAP@
|
||||||
|
|
||||||
ifneq (@LIBLUA_LIBS@,)
|
ifneq (@LIBLUA_LIBS@,)
|
||||||
NSE_SRC=nse_main.cc nse_nsock.cc nse_init.cc nse_fs.cc nse_nmaplib.cc nse_debug.cc nse_pcrelib.cc nse_binlib.cc nse_hash.cc nse_bit.cc
|
NSE_SRC=nse_main.cc nse_nsock.cc nse_init.cc nse_fs.cc nse_nmaplib.cc nse_debug.cc nse_pcrelib.cc nse_binlib.cc nse_bit.cc
|
||||||
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_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_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
|
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_bit.o
|
||||||
|
ifneq (@OPENSSL_LIBS@,)
|
||||||
|
NSE_SRC+=nse_openssl.cc
|
||||||
|
NSE_HDRS+=nse_openssl.h
|
||||||
|
NSE_OBJS+=nse_openssl.o
|
||||||
|
endif
|
||||||
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@
|
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@
|
||||||
|
|||||||
@@ -1164,6 +1164,233 @@ if(s) code_to_be_done_on_match end
|
|||||||
<indexterm class="endofrange" startref="nse-pcre-indexterm"/>
|
<indexterm class="endofrange" startref="nse-pcre-indexterm"/>
|
||||||
</sect2>
|
</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>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>openssl.md2( message )</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>Returns the MD2 digest of <literal>message</literal>.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>openssl.md4( message )</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>Returns the MD4 digest of <literal>message</literal>.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>openssl.md5( message )</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>Returns the MD5 digest of <literal>message</literal>.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>openssl.sha1( message )</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>Returns the SHA1 digest of <literal>message</literal>.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>openssl.ripemd160( message )</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>Returns the RIPEMD160 digest of <literal>message</literal>.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>openssl.digest( algorithm, message )</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>Returns the digest specified by <literal>algorithm</literal> of <literal>message</literal>.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>openssl.hmac( algorithm, key, message )</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para></para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>openssl.encrypt( algorithm, key, iv, data, padding = false )</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>Encrypt <literal>data</literal> with the encryption algorithm <literal>algorithm</literal>, <literal>key</literal> and the initialization vector <literal>iv</literal>.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>openssl.decrypt( algorithm, key, iv, data, padding = false )</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>Decrypt <literal>data</literal> with the encryption algorithm <literal>algorithm</literal>, <literal>key</literal> and the initialization vector <literal>iv</literal>.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>openssl.supported_ciphers()</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>Returns a table with the names of the supported cipher algorithms.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>openssl.supported_digests()</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>Returns a table with the names of the supported digest algorithms.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>openssl.DES_string_to_key( string data )</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>Converts <literal>data</literal> which must be a 7-byte string into a 8-byte DES key and sets the parity.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
<indexterm class="endofrange" startref="nse-openssl-indexterm"/>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
<sect2 id="nse-lib-ipOps">
|
<sect2 id="nse-lib-ipOps">
|
||||||
<title>IP Operations</title>
|
<title>IP Operations</title>
|
||||||
<indexterm><primary><varname>ipOps</varname> NSE module</primary></indexterm>
|
<indexterm><primary><varname>ipOps</varname> NSE module</primary></indexterm>
|
||||||
|
|||||||
@@ -291,7 +291,7 @@
|
|||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\nse_hash.cc"
|
RelativePath="..\nse_openssl.cc"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
@@ -488,7 +488,7 @@
|
|||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\nse_hash.h"
|
RelativePath="..\nse_openssl.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
|
|||||||
131
nse_hash.cc
131
nse_hash.cc
@@ -1,131 +0,0 @@
|
|||||||
#include <ctype.h>
|
|
||||||
#include <string.h>
|
|
||||||
extern "C" {
|
|
||||||
#include "lua.h"
|
|
||||||
#include "lualib.h"
|
|
||||||
#include "lauxlib.h"
|
|
||||||
}
|
|
||||||
#include "nse_hash.h"
|
|
||||||
|
|
||||||
#include "nbase/nbase_md5.h"
|
|
||||||
#include "nbase/nbase_sha1.h"
|
|
||||||
|
|
||||||
|
|
||||||
static int l_md5(lua_State *L)
|
|
||||||
{
|
|
||||||
size_t len;
|
|
||||||
const char *str = luaL_checklstring(L, 1, &len);
|
|
||||||
|
|
||||||
MD5_CTX c;
|
|
||||||
unsigned char digest[MD5_DIGEST_LENGTH];
|
|
||||||
luaL_Buffer buf;
|
|
||||||
char hdigit[3];
|
|
||||||
|
|
||||||
luaL_buffinit(L,&buf);
|
|
||||||
|
|
||||||
if (!nb_MD5_Init(&c)) {
|
|
||||||
/* ERROR */
|
|
||||||
luaL_error(L, "MD5 init error");
|
|
||||||
}
|
|
||||||
|
|
||||||
nb_MD5_Update(&c, str, len);
|
|
||||||
nb_MD5_Final(digest, &c);
|
|
||||||
|
|
||||||
for (int ii = 0; ii < MD5_DIGEST_LENGTH; ii++) {
|
|
||||||
sprintf(hdigit, "%02x", digest[ii]);
|
|
||||||
luaL_addlstring(&buf, hdigit, 2);
|
|
||||||
}
|
|
||||||
luaL_pushresult(&buf);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int l_md5bin(lua_State *L)
|
|
||||||
{
|
|
||||||
size_t len;
|
|
||||||
const char *str = luaL_checklstring(L, 1, &len);
|
|
||||||
|
|
||||||
MD5_CTX c;
|
|
||||||
unsigned char digest[MD5_DIGEST_LENGTH];
|
|
||||||
luaL_Buffer buf;
|
|
||||||
|
|
||||||
luaL_buffinit(L,&buf);
|
|
||||||
|
|
||||||
if (!nb_MD5_Init(&c)) {
|
|
||||||
/* ERROR */
|
|
||||||
luaL_error(L, "MD5 init error");
|
|
||||||
}
|
|
||||||
|
|
||||||
nb_MD5_Update(&c, str, len);
|
|
||||||
nb_MD5_Final(digest, &c);
|
|
||||||
|
|
||||||
lua_pushlstring(L, (char *)digest, MD5_DIGEST_LENGTH);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int l_sha1(lua_State *L)
|
|
||||||
{
|
|
||||||
size_t len;
|
|
||||||
const char *str = luaL_checklstring(L, 1, &len);
|
|
||||||
|
|
||||||
SHA_CTX c;
|
|
||||||
unsigned char digest[SHA_DIGEST_LENGTH];
|
|
||||||
luaL_Buffer buf;
|
|
||||||
char hdigit[3];
|
|
||||||
|
|
||||||
luaL_buffinit(L,&buf);
|
|
||||||
|
|
||||||
if (!nb_SHA1_Init(&c)) {
|
|
||||||
/* ERROR */
|
|
||||||
luaL_error(L, "sha1 init error");
|
|
||||||
}
|
|
||||||
|
|
||||||
nb_SHA1_Update(&c, str, len);
|
|
||||||
nb_SHA1_Final(digest, &c);
|
|
||||||
|
|
||||||
for (int ii = 0; ii < SHA_DIGEST_LENGTH; ii++) {
|
|
||||||
sprintf(hdigit, "%02x", digest[ii]);
|
|
||||||
luaL_addlstring(&buf, hdigit, 2);
|
|
||||||
}
|
|
||||||
luaL_pushresult(&buf);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int l_sha1bin(lua_State *L)
|
|
||||||
{
|
|
||||||
size_t len;
|
|
||||||
const char *str = luaL_checklstring(L, 1, &len);
|
|
||||||
|
|
||||||
SHA_CTX c;
|
|
||||||
unsigned char digest[SHA_DIGEST_LENGTH];
|
|
||||||
luaL_Buffer buf;
|
|
||||||
|
|
||||||
|
|
||||||
luaL_buffinit(L,&buf);
|
|
||||||
|
|
||||||
if (!nb_SHA1_Init(&c)) {
|
|
||||||
/* ERROR */
|
|
||||||
luaL_error(L, "sha1 init error");
|
|
||||||
}
|
|
||||||
|
|
||||||
nb_SHA1_Update(&c, str, len);
|
|
||||||
nb_SHA1_Final(digest, &c);
|
|
||||||
|
|
||||||
lua_pushlstring(L, (char *) digest, SHA_DIGEST_LENGTH);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static const luaL_reg hashlib[] =
|
|
||||||
{
|
|
||||||
{"md5", l_md5},
|
|
||||||
{"sha1", l_sha1},
|
|
||||||
{"md5bin", l_md5bin},
|
|
||||||
{"sha1bin", l_sha1bin},
|
|
||||||
{NULL, NULL}
|
|
||||||
};
|
|
||||||
|
|
||||||
LUALIB_API int luaopen_hashlib (lua_State *L) {
|
|
||||||
luaL_register(L, NSE_HASHLIBNAME, hashlib);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
#ifndef NSE_HASHLIB
|
|
||||||
#define NSE_HASHLIB
|
|
||||||
|
|
||||||
#define NSE_HASHLIBNAME "hash"
|
|
||||||
|
|
||||||
LUALIB_API int luaopen_hashlib (lua_State *L);
|
|
||||||
|
|
||||||
#endif /* NSE_HASHLIB */
|
|
||||||
@@ -8,8 +8,11 @@
|
|||||||
#include "nse_pcrelib.h"
|
#include "nse_pcrelib.h"
|
||||||
#include "nse_bit.h"
|
#include "nse_bit.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_OPENSSL
|
||||||
|
#include "nse_openssl.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "nse_binlib.h"
|
#include "nse_binlib.h"
|
||||||
#include "nse_hash.h"
|
|
||||||
|
|
||||||
#include "nbase.h"
|
#include "nbase.h"
|
||||||
|
|
||||||
@@ -245,8 +248,10 @@ int init_lua (lua_State *L)
|
|||||||
{NSE_PCRELIBNAME, luaopen_pcrelib}, // pcre library
|
{NSE_PCRELIBNAME, luaopen_pcrelib}, // pcre library
|
||||||
{"nmap", luaopen_nmap}, // nmap bindings
|
{"nmap", luaopen_nmap}, // nmap bindings
|
||||||
{NSE_BINLIBNAME, luaopen_binlib},
|
{NSE_BINLIBNAME, luaopen_binlib},
|
||||||
{NSE_HASHLIBNAME, luaopen_hashlib},
|
|
||||||
{BITLIBNAME, luaopen_bit}, // bit library
|
{BITLIBNAME, luaopen_bit}, // bit library
|
||||||
|
#ifdef HAVE_OPENSSL
|
||||||
|
{OPENSSLLIBNAME, luaopen_openssl}, // openssl bindings
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
luaL_openlibs(L); // opens all standard libraries
|
luaL_openlibs(L); // opens all standard libraries
|
||||||
|
|||||||
520
nse_openssl.cc
Normal file
520
nse_openssl.cc
Normal file
@@ -0,0 +1,520 @@
|
|||||||
|
#ifdef WIN32
|
||||||
|
#include "nmap_winconfig.h"
|
||||||
|
#else
|
||||||
|
#include "nmap_config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* 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 <openssl/md2.h>
|
||||||
|
#include <openssl/md4.h>
|
||||||
|
#include <openssl/md5.h>
|
||||||
|
#include <openssl/sha.h>
|
||||||
|
#include <openssl/ripemd.h>
|
||||||
|
#include <openssl/hmac.h>
|
||||||
|
#include <openssl/des.h>
|
||||||
|
#include <openssl/evp.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 ) );
|
||||||
|
if (!result) return luaL_error( L, "Couldn't allocate memory.");
|
||||||
|
|
||||||
|
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 );
|
||||||
|
if (!result) return luaL_error( L, "Couldn't allocate memory.");
|
||||||
|
|
||||||
|
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 );
|
||||||
|
if (!result) return luaL_error( L, "Couldn't allocate memory.");
|
||||||
|
|
||||||
|
RAND_pseudo_bytes( result, len );
|
||||||
|
lua_pushlstring( L, (char *) result, len );
|
||||||
|
free( result );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l_md2(lua_State *L) /** md2(string s) */
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
const unsigned char *s = (unsigned char *) luaL_checklstring( L, 1, &len );
|
||||||
|
unsigned char digest[16];
|
||||||
|
|
||||||
|
lua_pushlstring( L, (char *) MD2( s, len, digest ), 16 );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l_md4(lua_State *L) /** md4(string s) */
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
const unsigned char *s = (unsigned char *) luaL_checklstring( L, 1, &len );
|
||||||
|
unsigned char digest[16];
|
||||||
|
|
||||||
|
lua_pushlstring( L, (char *) MD4( s, len, digest ), 16 );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l_md5(lua_State *L) /** md5(string s) */
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
const unsigned char *s = (unsigned char *) luaL_checklstring( L, 1, &len );
|
||||||
|
unsigned char digest[16];
|
||||||
|
|
||||||
|
lua_pushlstring( L, (char *) MD5( s, len, digest ), 16 );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l_sha1(lua_State *L) /** sha1(string s) */
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
const unsigned char *s = (unsigned char *) luaL_checklstring( L, 1, &len );
|
||||||
|
unsigned char digest[20];
|
||||||
|
|
||||||
|
lua_pushlstring( L, (char *) SHA1( s, len, digest ), 20 );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l_ripemd160(lua_State *L) /** ripemd160(string s) */
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
const unsigned char *s = (unsigned char *) luaL_checklstring( L, 1, &len );
|
||||||
|
unsigned char digest[20];
|
||||||
|
|
||||||
|
lua_pushlstring( L, (char *) RIPEMD160( s, len, digest ), 20 );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l_digest(lua_State *L) /** digest(string algorithm, string message) */
|
||||||
|
{
|
||||||
|
size_t msg_len;
|
||||||
|
unsigned int digest_len;
|
||||||
|
const char *algorithm = luaL_checkstring( L, 1 );
|
||||||
|
const unsigned char *msg = (unsigned char *) luaL_checklstring( L, 2, &msg_len );
|
||||||
|
unsigned char digest[EVP_MAX_MD_SIZE];
|
||||||
|
const EVP_MD * evp_md;
|
||||||
|
EVP_MD_CTX mdctx;
|
||||||
|
|
||||||
|
evp_md = EVP_get_digestbyname( algorithm );
|
||||||
|
|
||||||
|
if (!evp_md) return luaL_error( L, "Unknown digest algorithm: %s", algorithm );
|
||||||
|
|
||||||
|
EVP_MD_CTX_init(&mdctx);
|
||||||
|
if (!(
|
||||||
|
EVP_DigestInit_ex( &mdctx, evp_md, NULL ) &&
|
||||||
|
EVP_DigestUpdate( &mdctx, msg, msg_len ) &&
|
||||||
|
EVP_DigestFinal_ex( &mdctx, digest, &digest_len ))) {
|
||||||
|
EVP_MD_CTX_cleanup( &mdctx );
|
||||||
|
return luaL_error( L, "OpenSSL error" );
|
||||||
|
}
|
||||||
|
EVP_MD_CTX_cleanup( &mdctx );
|
||||||
|
|
||||||
|
lua_pushlstring( L, (char *) digest, digest_len );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l_hmac(lua_State *L) /** hmac(string algorithm, string key, string message) */
|
||||||
|
{
|
||||||
|
size_t key_len, msg_len;
|
||||||
|
unsigned int digest_len;
|
||||||
|
const char *algorithm = luaL_checkstring( L, 1 );
|
||||||
|
const unsigned char *key = (unsigned char *) luaL_checklstring( L, 2, &key_len );
|
||||||
|
const unsigned char *msg = (unsigned char *) luaL_checklstring( L, 3, &msg_len );
|
||||||
|
unsigned char digest[EVP_MAX_MD_SIZE];
|
||||||
|
const EVP_MD * evp_md;
|
||||||
|
evp_md = EVP_get_digestbyname( algorithm );
|
||||||
|
|
||||||
|
if (!evp_md) return luaL_error( L, "Unknown digest algorithm: %s", algorithm );
|
||||||
|
|
||||||
|
HMAC( evp_md, key, key_len, msg, msg_len, digest, &digest_len );
|
||||||
|
|
||||||
|
lua_pushlstring( L, (char *) digest, digest_len );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct enumerator_data {
|
||||||
|
lua_State * L;
|
||||||
|
int index;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void enumerate_algorithms( const OBJ_NAME * name, void * arg )
|
||||||
|
{
|
||||||
|
struct enumerator_data* data = (struct enumerator_data *) arg;
|
||||||
|
lua_pushstring( data->L, name->name );
|
||||||
|
lua_rawseti( data->L, -2, data->index );
|
||||||
|
data->index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l_supported_digests(lua_State *L) /** supported_digests() */
|
||||||
|
{
|
||||||
|
enumerator_data data;
|
||||||
|
data.L = L;
|
||||||
|
data.index = 1;
|
||||||
|
|
||||||
|
lua_newtable( L );
|
||||||
|
OBJ_NAME_do_all_sorted( OBJ_NAME_TYPE_MD_METH,enumerate_algorithms, &data );
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l_supported_ciphers(lua_State *L) /** supported_ciphers() */
|
||||||
|
{
|
||||||
|
enumerator_data data;
|
||||||
|
data.L = L;
|
||||||
|
data.index = 1;
|
||||||
|
|
||||||
|
lua_newtable( L );
|
||||||
|
OBJ_NAME_do_all_sorted( OBJ_NAME_TYPE_CIPHER_METH,enumerate_algorithms, &data );
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l_encrypt(lua_State *L) /** encrypt( string algorithm, string key, string iv, string data, bool padding = false ) */
|
||||||
|
{
|
||||||
|
const char *algorithm = luaL_checkstring( L, 1 );
|
||||||
|
const EVP_CIPHER * evp_cipher = EVP_get_cipherbyname( algorithm );
|
||||||
|
if (!evp_cipher) return luaL_error( L, "Unknown cipher algorithm: %s", algorithm );
|
||||||
|
|
||||||
|
size_t data_len;
|
||||||
|
const unsigned char *key = (unsigned char *) luaL_checkstring( L, 2 );
|
||||||
|
const unsigned char *iv = (unsigned char *) luaL_optstring( L, 3, "" );
|
||||||
|
const unsigned char *data = (unsigned char *) luaL_checklstring( L, 4, &data_len );
|
||||||
|
int padding = lua_toboolean( L, 5 );
|
||||||
|
|
||||||
|
EVP_CIPHER_CTX cipher_ctx;
|
||||||
|
EVP_CIPHER_CTX_init( &cipher_ctx );
|
||||||
|
|
||||||
|
int out_len, final_len;
|
||||||
|
unsigned char * out = (unsigned char *) malloc( data_len + EVP_MAX_BLOCK_LENGTH );
|
||||||
|
if (!out) return luaL_error( L, "Couldn't allocate memory.");
|
||||||
|
|
||||||
|
if (!(
|
||||||
|
EVP_EncryptInit_ex( &cipher_ctx, evp_cipher, NULL, key, *iv ? iv : NULL ) &&
|
||||||
|
EVP_CIPHER_CTX_set_padding( &cipher_ctx, padding ) &&
|
||||||
|
EVP_EncryptUpdate( &cipher_ctx, out, &out_len, data, data_len ) &&
|
||||||
|
EVP_EncryptFinal_ex( &cipher_ctx, out + out_len, &final_len ) )) {
|
||||||
|
EVP_CIPHER_CTX_cleanup( &cipher_ctx );
|
||||||
|
free( out );
|
||||||
|
return luaL_error( L, "OpenSSL error" );
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_pushlstring( L, (char *) out, out_len + final_len );
|
||||||
|
|
||||||
|
EVP_CIPHER_CTX_cleanup( &cipher_ctx );
|
||||||
|
free( out );
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l_decrypt(lua_State *L) /** decrypt( string algorithm, string key, string iv, string data, bool padding = false ) */
|
||||||
|
{
|
||||||
|
const char *algorithm = luaL_checkstring( L, 1 );
|
||||||
|
const EVP_CIPHER * evp_cipher = EVP_get_cipherbyname( algorithm );
|
||||||
|
if (!evp_cipher) return luaL_error( L, "Unknown cipher algorithm: %s", algorithm );
|
||||||
|
|
||||||
|
size_t data_len;
|
||||||
|
const unsigned char *key = (unsigned char *) luaL_checkstring( L, 2 );
|
||||||
|
const unsigned char *iv = (unsigned char *) luaL_optstring( L, 3, "" );
|
||||||
|
const unsigned char *data = (unsigned char *) luaL_checklstring( L, 4, &data_len );
|
||||||
|
int padding = lua_toboolean( L, 5 );
|
||||||
|
|
||||||
|
EVP_CIPHER_CTX cipher_ctx;
|
||||||
|
EVP_CIPHER_CTX_init( &cipher_ctx );
|
||||||
|
|
||||||
|
int out_len, final_len;
|
||||||
|
unsigned char * out = (unsigned char *) malloc( data_len );
|
||||||
|
if (!out) return luaL_error( L, "Couldn't allocate memory.");
|
||||||
|
|
||||||
|
if (!(
|
||||||
|
EVP_DecryptInit_ex( &cipher_ctx, evp_cipher, NULL, key, *iv ? iv : NULL ) &&
|
||||||
|
EVP_CIPHER_CTX_set_padding( &cipher_ctx, padding ) &&
|
||||||
|
EVP_DecryptUpdate( &cipher_ctx, out, &out_len, data, data_len ) &&
|
||||||
|
EVP_DecryptFinal_ex( &cipher_ctx, out + out_len, &final_len ) )) {
|
||||||
|
EVP_CIPHER_CTX_cleanup( &cipher_ctx );
|
||||||
|
free( out );
|
||||||
|
return luaL_error( L, "OpenSSL error" );
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_pushlstring( L, (char *) out, out_len + final_len );
|
||||||
|
|
||||||
|
EVP_CIPHER_CTX_cleanup( &cipher_ctx );
|
||||||
|
free( out );
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l_DES_string_to_key(lua_State *L) /** DES_string_to_key( string data ) */
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
const unsigned char *data = (unsigned char *) luaL_checklstring( L, 1, &len );
|
||||||
|
if ( len != 7 )
|
||||||
|
return luaL_error( L, "String must have length of 7 bytes." );
|
||||||
|
|
||||||
|
DES_cblock key;
|
||||||
|
key[0] = data[0];
|
||||||
|
for( int i = 1; i < 8; i++ )
|
||||||
|
key[i] = data[i-1] << (8-i) | data[i] >> i;
|
||||||
|
|
||||||
|
DES_set_odd_parity( &key );
|
||||||
|
|
||||||
|
lua_pushlstring( L, (char *) key, 8 );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const struct luaL_reg bignum_methods[] = {
|
||||||
|
{ "num_bits", l_bignum_num_bits },
|
||||||
|
{ "num_bytes", l_bignum_num_bytes },
|
||||||
|
{ "tobin", l_bignum_bn2bin },
|
||||||
|
{ "todec", l_bignum_bn2dec },
|
||||||
|
{ "tohex", 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 },
|
||||||
|
{ "md2", l_md2 },
|
||||||
|
{ "md4", l_md4 },
|
||||||
|
{ "md5", l_md5 },
|
||||||
|
{ "sha1", l_sha1 },
|
||||||
|
{ "ripemd160", l_ripemd160 },
|
||||||
|
{ "digest", l_digest },
|
||||||
|
{ "hmac", l_hmac },
|
||||||
|
{ "encrypt", l_encrypt },
|
||||||
|
{ "decrypt", l_decrypt },
|
||||||
|
{ "DES_string_to_key", l_DES_string_to_key },
|
||||||
|
{ "supported_digests", l_supported_digests },
|
||||||
|
{ "supported_ciphers", l_supported_ciphers },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
LUALIB_API int luaopen_openssl(lua_State *L) {
|
||||||
|
|
||||||
|
OpenSSL_add_all_algorithms();
|
||||||
|
|
||||||
|
luaL_register(L, OPENSSLLIBNAME, openssllib);
|
||||||
|
|
||||||
|
// 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 );
|
||||||
|
|
||||||
|
lua_pop( L, 1 ); // BIGNUM
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
19
nse_openssl.h
Normal file
19
nse_openssl.h
Normal file
@@ -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
|
||||||
@@ -3,15 +3,24 @@
|
|||||||
|
|
||||||
module(... or "pop3",package.seeall)
|
module(... or "pop3",package.seeall)
|
||||||
|
|
||||||
|
local HAVE_SSL = false
|
||||||
|
|
||||||
require 'base64'
|
require 'base64'
|
||||||
require 'bit'
|
require 'bit'
|
||||||
|
require 'stdnse'
|
||||||
|
|
||||||
|
if pcall(require,'openssl') then
|
||||||
|
HAVE_SSL = true
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err = {
|
err = {
|
||||||
none = 0,
|
none = 0,
|
||||||
userError = 1,
|
userError = 1,
|
||||||
pwError = 2,
|
pwError = 2,
|
||||||
informationMissing = 3
|
informationMissing = 3,
|
||||||
|
OpenSSLMissing = 4,
|
||||||
}
|
}
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -112,8 +121,8 @@ end
|
|||||||
function login_apop(socket, user, pw, challenge)
|
function login_apop(socket, user, pw, challenge)
|
||||||
if type(challenge) ~= "string" then return false, err.informationMissing end
|
if type(challenge) ~= "string" then return false, err.informationMissing end
|
||||||
|
|
||||||
local apStr = hash.md5(challenge .. pw)
|
local apStr = stdnse.tohex(openssl.md5(challenge .. pw))
|
||||||
socket:send("APOP " .. user .. " " .. apStr .. "\r\n")
|
socket:send(("APOP %s %s\r\n"):format(user, apStr))
|
||||||
|
|
||||||
status, line = socket:receive_lines(1)
|
status, line = socket:receive_lines(1)
|
||||||
|
|
||||||
@@ -168,33 +177,6 @@ function capabilities(host, port)
|
|||||||
return capas
|
return capas
|
||||||
end
|
end
|
||||||
|
|
||||||
---
|
|
||||||
-- Calculate HMAC-MD5 hash
|
|
||||||
--@param key Key for hash calculation
|
|
||||||
--@param msg Message to be hashed
|
|
||||||
--@return HMAC-MD5 of given message
|
|
||||||
function hmacMD5(key, msg)
|
|
||||||
local ipad = {}
|
|
||||||
local opad = {}
|
|
||||||
|
|
||||||
if (string.len(key) > 64) then
|
|
||||||
key = hash.md5binary(key)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- create both pads, XORing with key
|
|
||||||
for i = 1, string.len(key) do
|
|
||||||
ipad[i] = string.char(bit.bxor(0x36, string.byte(string.sub(key, i))))
|
|
||||||
opad[i] = string.char(bit.bxor(0x5c, string.byte(string.sub(key, i))))
|
|
||||||
end
|
|
||||||
for i = #ipad + 1, 64 do
|
|
||||||
ipad[i] = string.char(0x36)
|
|
||||||
opad[i] = string.char(0x5c)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- calc HMAC-md5
|
|
||||||
return hash.md5(table.concat(opad) .. hash.md5bin(table.concat(ipad) .. msg))
|
|
||||||
end
|
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Try to login using AUTH command using SASL/CRAM-MD5 method
|
-- Try to login using AUTH command using SASL/CRAM-MD5 method
|
||||||
--@param socket Socket connected to POP3 server
|
--@param socket Socket connected to POP3 server
|
||||||
@@ -209,7 +191,7 @@ function login_sasl_crammd5(socket, user, pw)
|
|||||||
|
|
||||||
local challenge = base64.dec(string.sub(line, 3))
|
local challenge = base64.dec(string.sub(line, 3))
|
||||||
|
|
||||||
local digest = hmacMD5(pw, challenge)
|
local digest = stdnse.tohex(openssl.hmac('md5', pw, challenge))
|
||||||
local authStr = base64.enc(user .. " " .. digest)
|
local authStr = base64.enc(user .. " " .. digest)
|
||||||
socket:send(authStr .. "\r\n")
|
socket:send(authStr .. "\r\n")
|
||||||
|
|
||||||
@@ -221,3 +203,15 @@ function login_sasl_crammd5(socket, user, pw)
|
|||||||
return false, err.pwError
|
return false, err.pwError
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- overwrite functions requiring OpenSSL if we got no OpenSSL
|
||||||
|
if not HAVE_SSL then
|
||||||
|
|
||||||
|
local no_ssl = function()
|
||||||
|
return false, err.OpenSSLMissing
|
||||||
|
end
|
||||||
|
|
||||||
|
login_apop = no_ssl
|
||||||
|
login_sasl_crammd5 = no_ssl
|
||||||
|
end
|
||||||
|
|
||||||
|
|||||||
152
nselib/ssh1.lua
Normal file
152
nselib/ssh1.lua
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
|
||||||
|
-- @author = Sven Klemm <sven@c3d2.de>
|
||||||
|
-- @copyright See nmaps COPYING for licence
|
||||||
|
|
||||||
|
module(... or "ssh1",package.seeall)
|
||||||
|
|
||||||
|
local bin = require "bin"
|
||||||
|
local bit = require "bit"
|
||||||
|
local math = require "math"
|
||||||
|
local stdnse = require "stdnse"
|
||||||
|
local openssl = require "openssl"
|
||||||
|
|
||||||
|
--- fetch SSH1 host key
|
||||||
|
--@param host nmap host table
|
||||||
|
--@param port nmap port table
|
||||||
|
fetch_host_key = function(host, port)
|
||||||
|
local socket = nmap.new_socket()
|
||||||
|
local catch = function() socket:close() end
|
||||||
|
local try = nmap.new_try(catch)
|
||||||
|
|
||||||
|
try(socket:connect(host.ip, port.number))
|
||||||
|
-- fetch banner
|
||||||
|
try(socket:receive_lines(1))
|
||||||
|
-- send our banner
|
||||||
|
try(socket:send("SSH-1.5-Nmap-SSH1-Hostkey\r\n"))
|
||||||
|
|
||||||
|
local data, packet_length, padding, offset
|
||||||
|
data = try(socket:receive())
|
||||||
|
socket:close()
|
||||||
|
offset, packet_length = bin.unpack( ">i", data )
|
||||||
|
padding = 8 - packet_length % 8
|
||||||
|
offset = offset + padding
|
||||||
|
|
||||||
|
if padding + packet_length + 4 == data:len() then
|
||||||
|
-- seems to be a proper SSH1 packet
|
||||||
|
local msg_code,host_key_bits,exp,mod,length,fp_input
|
||||||
|
offset, msg_code = bin.unpack( ">c", data, offset )
|
||||||
|
if msg_code == 2 then -- 2 => SSH_SMSG_PUBLIC_KEY
|
||||||
|
-- ignore cookie and server key bits
|
||||||
|
offset, _, _ = bin.unpack( ">A8i", data, offset )
|
||||||
|
-- skip server key exponent and modulus
|
||||||
|
offset, length = bin.unpack( ">S", data, offset )
|
||||||
|
offset = offset + math.ceil( length / 8 )
|
||||||
|
offset, length = bin.unpack( ">S", data, offset )
|
||||||
|
offset = offset + math.ceil( length / 8 )
|
||||||
|
|
||||||
|
offset, host_key_bits = bin.unpack( ">i", data, offset )
|
||||||
|
offset, length = bin.unpack( ">S", data, offset )
|
||||||
|
offset, exp = bin.unpack( ">A" .. math.ceil( length / 8 ), data, offset )
|
||||||
|
exp = openssl.bignum_bin2bn( exp )
|
||||||
|
offset, length = bin.unpack( ">S", data, offset )
|
||||||
|
offset, mod = bin.unpack( ">A" .. math.ceil( length / 8 ), data, offset )
|
||||||
|
mod = openssl.bignum_bin2bn( mod )
|
||||||
|
|
||||||
|
fp_input = mod:tobin()..exp:tobin()
|
||||||
|
|
||||||
|
return {exp=exp,mod=mod,bits=host_key_bits,key_type='rsa1',fp_input=fp_input,
|
||||||
|
full_key=exp:todec()..' '..mod:todec(),algorithm="RSA1",
|
||||||
|
fingerprint=openssl.md5(fp_input)}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- format key as hexadecimal fingerprint
|
||||||
|
fingerprint_hex = function( fingerprint, algorithm, bits )
|
||||||
|
fingerprint = stdnse.tohex(fingerprint,{separator=":",group=2})
|
||||||
|
return ("%d %s (%s)"):format( bits, fingerprint, algorithm )
|
||||||
|
end
|
||||||
|
|
||||||
|
--- format key as bubblebabble fingerprint
|
||||||
|
fingerprint_bubblebabble = function( fingerprint, algorithm, bits )
|
||||||
|
local vowels = {'a','e','i','o','u','y'}
|
||||||
|
local consonants = {'b','c','d','f','g','h','k','l','m','n','p','r','s','t','v','z','x'}
|
||||||
|
local s = "x"
|
||||||
|
local seed = 1
|
||||||
|
|
||||||
|
for i=1,#fingerprint+2,2 do
|
||||||
|
local in1,in2,idx1,idx2,idx3,idx4,idx5
|
||||||
|
if i < #fingerprint or #fingerprint / 2 % 2 ~= 0 then
|
||||||
|
in1 = fingerprint:byte(i)
|
||||||
|
idx1 = (bit.band(bit.rshift(in1,6),3) + seed) % 6 + 1
|
||||||
|
idx2 = bit.band(bit.rshift(in1,2),15) + 1
|
||||||
|
idx3 = (bit.band(in1,3) + math.floor(seed/6)) % 6 + 1
|
||||||
|
s = s .. vowels[idx1] .. consonants[idx2] .. vowels[idx3]
|
||||||
|
if i < #fingerprint then
|
||||||
|
in2 = fingerprint:byte(i+1)
|
||||||
|
idx4 = bit.band(bit.rshift(in2,4),15) + 1
|
||||||
|
idx5 = bit.band(in2,15) + 1
|
||||||
|
s = s .. consonants[idx4] .. '-' .. consonants[idx5]
|
||||||
|
seed = (seed * 5 + in1 * 7 + in2) % 36
|
||||||
|
end
|
||||||
|
else
|
||||||
|
idx1 = seed % 6 + 1
|
||||||
|
idx2 = 16 + 1
|
||||||
|
idx3 = math.floor(seed/6) + 1
|
||||||
|
s = s .. vowels[idx1] .. consonants[idx2] .. vowels[idx3]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
s = s .. 'x'
|
||||||
|
return ("%d %s (%s)"):format( bits, s, algorithm )
|
||||||
|
end
|
||||||
|
|
||||||
|
--- format key as visual fingerprint
|
||||||
|
-- ported from http://www.openbsd.org/cgi-bin/cvsweb/~checkout~/src/usr.bin/ssh/key.c
|
||||||
|
fingerprint_visual = function( fingerprint, algorithm, bits )
|
||||||
|
local i,j,field,characters,input,fieldsize_x,fieldsize_y,s
|
||||||
|
fieldsize_x, fieldsize_y = 17, 9
|
||||||
|
characters = {' ','.','o','+','=','*','B','O','X','@','%','&','#','/','^','S','E'}
|
||||||
|
|
||||||
|
-- initialize drawing area
|
||||||
|
field = {}
|
||||||
|
for i=1,fieldsize_x do
|
||||||
|
field[i]={}
|
||||||
|
for j=1,fieldsize_y do field[i][j]=1 end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- we start in the center and mark it
|
||||||
|
x, y = math.ceil(fieldsize_x/2), math.ceil(fieldsize_y/2)
|
||||||
|
field[x][y] = #characters - 1;
|
||||||
|
|
||||||
|
-- iterate over fingerprint
|
||||||
|
for i=1,#fingerprint do
|
||||||
|
input = fingerprint:byte(i)
|
||||||
|
-- each byte conveys four 2-bit move commands
|
||||||
|
for j=1,4 do
|
||||||
|
if bit.band( input, 1) == 1 then x = x + 1 else x = x - 1 end
|
||||||
|
if bit.band( input, 2) == 2 then y = y + 1 else y = y - 1 end
|
||||||
|
|
||||||
|
x = math.max(x,1); x = math.min(x,fieldsize_x)
|
||||||
|
y = math.max(y,1); y = math.min(y,fieldsize_y)
|
||||||
|
|
||||||
|
if field[x][y] < #characters - 2 then
|
||||||
|
field[x][y] = field[x][y] + 1
|
||||||
|
end
|
||||||
|
input = bit.rshift( input, 2 )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- mark end point
|
||||||
|
field[x][y] = #characters;
|
||||||
|
|
||||||
|
-- build output
|
||||||
|
s = ('\n+--[%4s %4d]----+\n'):format( algorithm, bits )
|
||||||
|
for i=1,fieldsize_y do
|
||||||
|
s = s .. '|'
|
||||||
|
for j=1,fieldsize_x do s = s .. characters[ field[j][i] ] end
|
||||||
|
s = s .. '|\n'
|
||||||
|
end
|
||||||
|
s = s .. '+-----------------+\n'
|
||||||
|
return s
|
||||||
|
end
|
||||||
|
|
||||||
187
nselib/ssh2.lua
Normal file
187
nselib/ssh2.lua
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
|
||||||
|
-- @author = Sven Klemm <sven@c3d2.de>
|
||||||
|
-- @copyright See nmaps COPYING for licence
|
||||||
|
|
||||||
|
module(... or "ssh2",package.seeall)
|
||||||
|
|
||||||
|
require "bin"
|
||||||
|
require "base64"
|
||||||
|
require "openssl"
|
||||||
|
require "stdnse"
|
||||||
|
|
||||||
|
-- table holding transport layer functions
|
||||||
|
transport = {}
|
||||||
|
|
||||||
|
-- table of SSH2 constants
|
||||||
|
local SSH2
|
||||||
|
|
||||||
|
--- pack multiprecision integer for sending
|
||||||
|
--@param bn openssl bignum
|
||||||
|
--@return packed multiprecision integer
|
||||||
|
transport.pack_mpint = function( bn )
|
||||||
|
local bytes, packed
|
||||||
|
bytes = bn:num_bytes()
|
||||||
|
packed = bn:tobin()
|
||||||
|
if bytes % 8 == 0 then
|
||||||
|
bytes = bytes + 1
|
||||||
|
packed = string.char(0) .. packed
|
||||||
|
end
|
||||||
|
return bin.pack( ">IA", bytes, packed )
|
||||||
|
end
|
||||||
|
|
||||||
|
--- build a ssh2 packet
|
||||||
|
--@param payload payload of the packet
|
||||||
|
--@return packet to send on the wire
|
||||||
|
transport.build = function( payload )
|
||||||
|
local packet_length, padding_length
|
||||||
|
padding_length = 8 - ( (payload:len() + 1 + 4 ) % 8 )
|
||||||
|
packet_length = payload:len() + padding_length + 1
|
||||||
|
return bin.pack( ">IcAA", packet_length, padding_length, payload, openssl.rand_pseudo_bytes( padding_length ) )
|
||||||
|
end
|
||||||
|
|
||||||
|
--- extract the payload from a received SSH2 packet
|
||||||
|
--@param received SSH2 packet
|
||||||
|
--@return payload of the SSH2 packet
|
||||||
|
transport.payload = function( packet )
|
||||||
|
local packet_length, padding_length, payload_length, payload, offset
|
||||||
|
offset, packet_length, padding_length = bin.unpack( ">Ic", packet )
|
||||||
|
payload_length = packet_length - padding_length - 1
|
||||||
|
offset, payload = bin.unpack( ">A" .. payload_length, packet, offset )
|
||||||
|
return payload
|
||||||
|
end
|
||||||
|
|
||||||
|
--- build kexdh_init packet
|
||||||
|
transport.kexdh_init = function( e )
|
||||||
|
return bin.pack( ">cA", SSH2.SSH_MSG_KEXDH_INIT, transport.pack_mpint( e ) )
|
||||||
|
end
|
||||||
|
|
||||||
|
--- build kex_init packet
|
||||||
|
transport.kex_init = function( cookie, options )
|
||||||
|
options = options or {}
|
||||||
|
kex_algorithms = "diffie-hellman-group1-sha1"
|
||||||
|
host_key_algorithms = options['host_key_algorithms'] or "ssh-dss,ssh-rsa"
|
||||||
|
encryption_algorithms = "aes128-cbc,3des-cbc,blowfish-cbc,aes192-cbc,aes256-cbc,aes128-ctr,aes192-ctr,aes256-ctr"
|
||||||
|
mac_algorithms = "hmac-md5,hmac-sha1,hmac-ripemd160"
|
||||||
|
compression_algorithms = "none"
|
||||||
|
languages = ""
|
||||||
|
|
||||||
|
local payload = bin.pack( ">cAaa", SSH2.SSH_MSG_KEXINIT, cookie, kex_algorithms, host_key_algorithms )
|
||||||
|
payload = payload .. bin.pack( ">aa", encryption_algorithms, encryption_algorithms )
|
||||||
|
payload = payload .. bin.pack( ">aa", mac_algorithms, mac_algorithms )
|
||||||
|
payload = payload .. bin.pack( ">aa", compression_algorithms, compression_algorithms )
|
||||||
|
payload = payload .. bin.pack( ">aa", languages, languages )
|
||||||
|
payload = payload .. bin.pack( ">cI", 0, 0 )
|
||||||
|
|
||||||
|
return payload
|
||||||
|
end
|
||||||
|
|
||||||
|
--- parse kexinit package
|
||||||
|
-- returns an empty table in case of an error
|
||||||
|
transport.parse_kex_init = function( payload )
|
||||||
|
local _, offset, msg_code, parsed, fields, fieldname
|
||||||
|
parsed = {}
|
||||||
|
|
||||||
|
-- check for proper msg code
|
||||||
|
offset, msg_code = bin.unpack( ">c", payload )
|
||||||
|
if msg_code ~= SSH2.SSH_MSG_KEXINIT then return {} end
|
||||||
|
|
||||||
|
offset, parsed.cookie = bin.unpack( ">A16", payload, offset )
|
||||||
|
|
||||||
|
fields = {'kex_algorithms','server_host_key_algorithms',
|
||||||
|
'encryption_algorithms_client_to_server','encryption_algorithms_server_to_client',
|
||||||
|
'mac_algorithms_client_to_server','mac_algorithms_server_to_client',
|
||||||
|
'compression_algorithms_client_to_server','compression_algorithms_server_to_client',
|
||||||
|
'languages_client_to_server','languages_server_to_client'}
|
||||||
|
for _, fieldname in pairs( fields ) do
|
||||||
|
offset, parsed[fieldname] = bin.unpack( ">a", payload, offset )
|
||||||
|
end
|
||||||
|
|
||||||
|
return parsed
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- fetch SSH2 host key
|
||||||
|
--@param host nmap host table
|
||||||
|
--@param port nmap port table
|
||||||
|
--@param key_type key type to fetch
|
||||||
|
--@return table containing the key and fingerprint
|
||||||
|
fetch_host_key = function( host, port, key_type )
|
||||||
|
local socket = nmap.new_socket()
|
||||||
|
local catch = function() socket:close() end
|
||||||
|
local try = nmap.new_try(catch)
|
||||||
|
-- oakley group 2 prime taken from rfc 2409
|
||||||
|
local prime = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF"
|
||||||
|
|
||||||
|
try(socket:connect(host.ip, port.number))
|
||||||
|
-- fetch banner
|
||||||
|
try(socket:receive_lines(1))
|
||||||
|
-- send our banner
|
||||||
|
try(socket:send("SSH-2.0-Nmap-SSH2-Hostkey\r\n"))
|
||||||
|
|
||||||
|
local cookie = openssl.rand_bytes( 16 )
|
||||||
|
local packet = transport.build( transport.kex_init( cookie, {host_key_algorithms=key_type} ) )
|
||||||
|
try(socket:send( packet ))
|
||||||
|
|
||||||
|
local kex_init = try(socket:receive_bytes(1))
|
||||||
|
kex_init = transport.parse_kex_init( transport.payload( kex_init ) )
|
||||||
|
|
||||||
|
if not tostring(kex_init.server_host_key_algorithms):find( key_type, 1, true ) then
|
||||||
|
-- server does not support host key type
|
||||||
|
stdnse.print_debug( 2, "Hostkey type '%s' not supported by server.", key_type )
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local e, g, x, p
|
||||||
|
-- e = g^x mod p
|
||||||
|
g = openssl.bignum_dec2bn( "2" )
|
||||||
|
p = openssl.bignum_hex2bn( prime )
|
||||||
|
x = openssl.bignum_pseudo_rand( 1024 )
|
||||||
|
e = openssl.bignum_mod_exp( g, x, p )
|
||||||
|
|
||||||
|
packet = transport.build( transport.kexdh_init( e ) )
|
||||||
|
try(socket:send( packet ))
|
||||||
|
|
||||||
|
kexdh_reply = try(socket:receive_bytes(1))
|
||||||
|
kexdh_reply = transport.payload( kexdh_reply )
|
||||||
|
-- check for proper msg code
|
||||||
|
if kexdh_reply:byte(1) ~= SSH2.SSH_MSG_KEXDH_REPLY then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local _,public_host_key,bits,algorithm
|
||||||
|
_, _, public_host_key = bin.unpack( ">ca", kexdh_reply )
|
||||||
|
|
||||||
|
if key_type == 'ssh-dss' then
|
||||||
|
algorithm = "DSA"
|
||||||
|
local p
|
||||||
|
_, _, p = bin.unpack( ">aa", public_host_key )
|
||||||
|
bits = openssl.bignum_bin2bn( p ):num_bits()
|
||||||
|
elseif key_type == 'ssh-rsa' then
|
||||||
|
algorithm = "RSA"
|
||||||
|
local n
|
||||||
|
_, _, _, n = bin.unpack( ">aaa", public_host_key )
|
||||||
|
bits = openssl.bignum_bin2bn( n ):num_bits()
|
||||||
|
else
|
||||||
|
stdnse.print_debug( "Unsupported key type: %s", key_type )
|
||||||
|
end
|
||||||
|
|
||||||
|
return { key=public_host_key, key_type=key_type, fp_input=public_host_key, bits=bits,
|
||||||
|
full_key=('%s %s'):format(key_type,base64.enc(public_host_key)),
|
||||||
|
algorithm=algorithm, fingerprint=openssl.md5(public_host_key) }
|
||||||
|
end
|
||||||
|
|
||||||
|
-- constants
|
||||||
|
|
||||||
|
SSH2 = {
|
||||||
|
SSH_MSG_DISCONNECT = 1,
|
||||||
|
SSH_MSG_IGNORE = 2,
|
||||||
|
SSH_MSG_UNIMPLEMENTED = 3,
|
||||||
|
SSH_MSG_DEBUG = 4,
|
||||||
|
SSH_MSG_SERVICE_REQUEST = 5,
|
||||||
|
SSH_MSG_SERVICE_ACCEPT = 6,
|
||||||
|
SSH_MSG_KEXINIT = 20,
|
||||||
|
SSH_MSG_NEWKEYS = 21,
|
||||||
|
SSH_MSG_KEXDH_INIT = 30,
|
||||||
|
SSH_MSG_KEXDH_REPLY = 31,
|
||||||
|
}
|
||||||
|
|
||||||
103
scripts/SSH-hostkey.nse
Normal file
103
scripts/SSH-hostkey.nse
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
--- Shows SSH Hostkeys
|
||||||
|
--
|
||||||
|
-- Shows fingerprint or fingerprint and key depending on verbosity level.
|
||||||
|
-- Puts the found hostkeys in nmap.registry for other scripts to use them.
|
||||||
|
-- You can control the output with the ssh_hostkey script argument. Possible
|
||||||
|
-- values are bubble,visual,full and all.
|
||||||
|
--
|
||||||
|
--@usage
|
||||||
|
-- nmap host --script SSH-hostkey --script-args ssh_hostkey=full
|
||||||
|
-- nmap host --script SSH-hostkey --script-args ssh_hostkey=all
|
||||||
|
-- nmap host --script SSH-hostkey --script-args ssh_hostkey='visual bubble'
|
||||||
|
--
|
||||||
|
--@output
|
||||||
|
-- 22/tcp open ssh
|
||||||
|
-- | SSH Hostkey: 2048 f0:58:ce:f4:aa:a4:59:1c:8e:dd:4d:07:44:c8:25:11 (RSA)
|
||||||
|
-- 22/tcp open ssh
|
||||||
|
-- | SSH Hostkey: 2048 f0:58:ce:f4:aa:a4:59:1c:8e:dd:4d:07:44:c8:25:11 (RSA)
|
||||||
|
-- | +--[ RSA 2048]----+
|
||||||
|
-- | | .E*+ |
|
||||||
|
-- | | oo |
|
||||||
|
-- | | . o . |
|
||||||
|
-- | | O . . |
|
||||||
|
-- | | o S o . |
|
||||||
|
-- | | = o + . |
|
||||||
|
-- | | . * o . |
|
||||||
|
-- | | = . |
|
||||||
|
-- | | o . |
|
||||||
|
-- |_ +-----------------+
|
||||||
|
-- 22/tcp open ssh
|
||||||
|
-- | SSH Hostkey: 2048 xuvah-degyp-nabus-zegah-hebur-nopig-bubig-difeg-hisym-rumef-cuxex (RSA)
|
||||||
|
-- |_ ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAwVuv2gcr0maaKQ69VVIEv2ob4OxnuI64fkeOnCXD1lUx5tTA+vefXUWEMxgMuA7iX4irJHy2zer0NQ3Z3yJvr5scPgTYIaEOp5Uo/eGFG9Agpk5wE8CoF0e47iCAPHqzlmP2V7aNURLMODb3jVZuI07A2ZRrMGrD8d888E2ORVORv1rYeTYCqcMMoVFmX9l3gWEdk4yx3w5sD8v501Iuyd1v19mPfyhrI5E1E1nl/Xjp5N0/xP2GUBrdkDMxKaxqTPMie/f0dXBUPQQN697a5q+5lBRPhKYOtn6yQKCd9s1Q22nxn72Jmi1RzbMyYJ52FosDT755Qmb46GLrDMaZMQ==
|
||||||
|
|
||||||
|
id = "SSH Hostkey"
|
||||||
|
author = "Sven Klemm <sven@c3d2.de>"
|
||||||
|
description = "Show SSH Hostkeys"
|
||||||
|
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
|
||||||
|
categories = {"safe","default","intrusive"}
|
||||||
|
|
||||||
|
require("shortport")
|
||||||
|
require("stdnse")
|
||||||
|
|
||||||
|
-- openssl is required for this script
|
||||||
|
if pcall(require,"openssl") then
|
||||||
|
require("ssh1")
|
||||||
|
require("ssh2")
|
||||||
|
else
|
||||||
|
action = function()
|
||||||
|
stdnse.print_debug( 3, "Skipping %s script because OpenSSL is missing.", id )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
portrule = shortport.port_or_service(22, "ssh")
|
||||||
|
|
||||||
|
|
||||||
|
--- put hostkey in the nmap registry for usage by other scripts
|
||||||
|
--@param host nmap host table
|
||||||
|
--@param key host key table
|
||||||
|
local add_key_to_registry = function( host, key )
|
||||||
|
nmap.registry[id] = nmap.registry[id] or {}
|
||||||
|
nmap.registry[id][host.ip] = nmap.registry[id][host.ip] or {}
|
||||||
|
table.insert( nmap.registry[id][host.ip], key )
|
||||||
|
end
|
||||||
|
|
||||||
|
action = action or function(host, port)
|
||||||
|
local output = {}
|
||||||
|
local keys = {}
|
||||||
|
local _,key
|
||||||
|
local format = nmap.registry.args.ssh_hostkey or "hex"
|
||||||
|
local all_formats = format:find( 'all', 1, true )
|
||||||
|
|
||||||
|
key = ssh1.fetch_host_key( host, port )
|
||||||
|
if key then table.insert( keys, key ) end
|
||||||
|
|
||||||
|
key = ssh2.fetch_host_key( host, port, "ssh-dss" )
|
||||||
|
if key then table.insert( keys, key ) end
|
||||||
|
|
||||||
|
key = ssh2.fetch_host_key( host, port, "ssh-rsa" )
|
||||||
|
if key then table.insert( keys, key ) end
|
||||||
|
|
||||||
|
for _, key in ipairs( keys ) do
|
||||||
|
add_key_to_registry( host, key )
|
||||||
|
if format:find( 'hex', 1, true ) or all_formats then
|
||||||
|
table.insert( output, ssh1.fingerprint_hex( key.fingerprint, key.algorithm, key.bits ) )
|
||||||
|
end
|
||||||
|
if format:find( 'bubble', 1, true ) or all_formats then
|
||||||
|
table.insert( output, ssh1.fingerprint_bubblebabble( openssl.sha1(key.fp_input), key.algorithm, key.bits ) )
|
||||||
|
end
|
||||||
|
if format:find( 'visual', 1, true ) or all_formats then
|
||||||
|
-- insert empty line so table is not destroyed if this is the first
|
||||||
|
-- line of output
|
||||||
|
if #output == 0 then table.insert( output, " " ) end
|
||||||
|
table.insert( output, ssh1.fingerprint_visual( key.fingerprint, key.algorithm, key.bits ) )
|
||||||
|
end
|
||||||
|
if nmap.verbosity() > 1 or format:find( 'full', 1, true ) or all_formats then
|
||||||
|
table.insert( output, key.full_key )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if #output > 0 then
|
||||||
|
return table.concat( output, '\n' )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
Reference in New Issue
Block a user