


CLOSE_WAIT check
------------------

Ncrack will now check if the connection has been closed by the peer before
trying out a new authentication attempt within that connection. It does that
by issuing a read call (through nsock) with a tiny timeout. If nsock returns
NSE_STATUS_TIMEOUT instead of an NSE_STATUS_EOF, then our connection hasn't been
closed yet by the peer. Of course we check that by using an additional boolean
variable so as to differentiate between normal timeouts and this particular
one. There is not really any other *portable* way to check if our connection
is in CLOSE_WAIT state (e.g Linux netstat just parses /proc and *BSD use
fcntl et al)



NextPair Problem
------------------

Problem: each service that needs to be cracked holds a pointer to the loaded
username list and password list (they are vector objects). Each time a new
connection is made or a new authentication attempt is going to be tried in the
current connection then we need to call NextPair() which gives us the next login
username and password pair. The normal way to do that would be to just move the
password list iterator each time, and the username list iterator once the
password list iterator has finished one full iteration. However, by using this
crude approach arises the following problem: 

-- What happens when a connection is prematurely closed by the peer for one
reason or another (before the current login pair is actually tested)? --

It is obvious that the iterator approach would never really try out that pair,
because it would just forget about the unfinished authentication attempt and
move on giving the next (always unique) pair.

Solution: (still needs to be more tested for some end-cases)

Each time a connection is prematurely closed by the peer, which essentially
means that our current authentication attempt was not completed, then we throw
the current pair inside the service's login-pair pool (which is a stl list). The
next time we are going to ask for a pair from NextPair(), if the pair_pool
is not empty, then it will return us one element from that, giving us the
opportunity to retry that pair once again. The element is removed from the pool
when we extract it from NextPair() and if the authentication doesn't finish this
time either, then we move it back to the list so it can be reused later once
again (and this will go on happening until the authentication finishes all steps
for that pair or any other pair in that situation).

The problem, however, is a little more complex than it first seems:

-- What happens if the username list iteration finishes while we have pending
authentication attempts taking place but the pairs for these attempts had been
extracted from the pair_pool? --

Normally, since the pair_pool has its elements removed and would be 
empty at the time the username list iteration finishes, then there is no
way to actually know if the service needs to be moved to the services_finished
list (which should be moved there only after *every* pair has been tested out,
including everything from the pair_pool).
To be able to account for that, we keep a separate mirror_pair_pool which holds
copies of the current pairs being tested out from the main pair_pool. Each time
a pair has been tested out fully, then we can remove that element from the
mirror_pair_pool (remember that the element from the pair_pool had already been
removed at the time it was returned from NextPair()). If it fails being tested,
then we move back that pair to the pair_pool list only (we already have a copy
at the mirror_pair_pool). 
Note down, that all this happens to take care of a highly improbable case, but
which however just *might* happen one day. Also, note that every list involved
in the solution is usually really small so any iterations are not
resource-consuming.

