Nmap Development mailing list archives

Re: [NSE][PATCH] only show script errors in verbose mode


From: "Patrick Donnelly" <batrick.donnelly () gmail com>
Date: Fri, 26 Sep 2008 13:06:30 -0600

On Fri, Sep 26, 2008 at 12:26 PM, David Fifield <david () bamsoftware com> wrote:
On Thu, Sep 25, 2008 at 11:19:26PM -0600, Patrick Donnelly wrote:
On Thu, Sep 25, 2008 at 10:52 PM, David Fifield <david () bamsoftware com> wrote:
Yes, now we're getting somewhere. Maybe we shouldn't use newproxy if
it's not documented, but the technique of using a userdata to represent
a unique type sounds perfect. I can't see the rest of the
implementation, so maybe you can provide a sketch of it.

Basically, I would see us having a register_error function somewhere
that would associate a string error identifier with the unique
userdata object. The package.errors table would have the string
associated with the userdata and vice versa, literally:

package.errors.MISSING_SYSTEM_DEPENDENCY = newproxy()
package.errors[package.errors.MISSING_SYSTEM_DEPENDENCY] =
"MISSING_SYSTEM_DEPENDENCY"

So, when we catch an error in C via pcall we can quickly identify the
type of error. Internally we may have a "degree of severity" (or
perhaps simply verbosity) which we use to notify the user.

This is the right idea, but again, I think it's a bad idea to use
newproxy if it's undocumented and unsupported. Plus if we can't set a
metatable on the result of newproxy it limits our flexibility.

newproxy(true) gives the resultant userdata a metatable (that you can
then modify from Lua). You can also use debug.setmetatable for the
same purpose.

We can make our own version of newproxy very easily in order to have a
more time-persistent function in case newproxy is removed.

How about just creating a new C type, say nmap.error, each instance of
which would be associated with a certain metatable (so we could do
luaL_checkudata on it), and which would allow a custom string for each
instance. I was reading http://www.lua.org/pil/28.2.html and it appears
to be just what we need.

Well yes, we want a class of errors. As I showed earlier, we have each
userdata used as a unique key in the errors table. If, when we index a
userdata thrown by an error, we get nil, then it is _not_ one of our
module errors (it is just a different kind of error).

Also, luaL_checkudata is designed for argument checking. Using this
function on what was thrown by an error would result in another error
(for anything but the userdata). You see this function properly used
in places like nsock when we check for a socket userdata. For example,
try doing this in a test script:

assert(nmap.new_socket()).connect(newproxy(), "127.0.0.1", 80)

This will throw an error in connect because an invalid userdata was
given (by luaL_checkudata).

Where does the error get raised and how?

The error would be raised by the C module (possibly by a script or Lua
module, doesn't matter too much). The module could quickly check if a
dependency is missing (e.g. OpenSSL) and raise the error.

That would be great. So the C module would just check HAVE_OPENSSL at
compile time and either define all the functions or include code to
raise an error. Tell me how you get an error from a C module at
"require" time. Aren't all the C modules loaded all at once in init_lua?
How does a C module know when it has been required?

A C module has the "main" function luaopen_libraryname. We can have
the module throw the error there. There are actually problems with
this that I just recalled. Whenever require catches an error thrown by
loading a module, it flags that module name in package.loaded with a
userdata, so in later calls to require it will immediately error again
(with a different error message). For example:

package.preload.hi = function() error"WUT" end
require"hi"
stdin:1: WUT
stack traceback:
        [C]: in function 'error'
        stdin:1: in function <stdin:1>
        [C]: in function 'require'
        stdin:1: in main chunk
        [C]: ?
require"hi"
stdin:1: loop or previous error loading module 'hi'
stack traceback:
        [C]: in function 'require'
        stdin:1: in main chunk
        [C]: ?

So the first call properly returns the error but subsequent calls do
not. This won't work for us. I'm still giving this some thought.

Is there a way to associate a different string with each instance of an error?

Yes, as shown above.

No, I mean there should be a way to associate a different string with
each MISSING_SYSTEM_DEPENDENCY instance, for example. Like the error
message should have "openssl" in it if it was raised by the openssl
module.

I see. Yes it would be possible, just awkward. What may end up being
better is simply using tables instead of userdata and having a field
that describes the actual dependency.

Cheers,

-- 
-Patrick Donnelly

"One of the lessons of history is that nothing is often a good thing
to do and always a clever thing to say."

-Will Durant

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


Current thread: