I'm totally new to Python (as of half an hour ago) and trying to write a simple script to enumerate users on an SMTP server.
The users file is a simple list (one per line) of usernames.
The script runs fine but with each iteration of the loop it slows until, around loop 14, it seems to hang completely. No error - I have to ^c.
Can anyone shed some light on the problem please?
TIA, Tom
#!/usr/bin/python
import socket
import sys
if len(sys.argv) != 2:
print "Usage: vrfy.py <username file>"
sys.exit(0)
#open user file
file=open(sys.argv[1], 'r')
users=[x.strip() for x in file.readlines()]
file.close
#Just for debugging
print users
# Create a Socket
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Connect to the Server
connect=s.connect(('192.168.13.222',25))
for x in users:
# VRFY a user
s.send('VRFY ' + x + '\r\n')
result=s.recv(1024)
print result
# Close the socket
s.close()
Memory - if you're storing all of the generated values somewhere, the loop might be slowing down because the of all the memory being used. Python has it's own memory manager, so using up lots of memory could eventually make the program slower.
Infinite While Loop in PythonInfinite while loop refers to a while loop where the while condition never becomes false. When a condition never becomes false, the program enters the loop and keeps repeating that same block of code over and over again, and the loop never ends.
Map() Function in Python The map() function is a replacement to a for a loop. It applies a function for each element of an iterable.
Growing variables in a loop takes very long. Each time you increase the length of the variable, a million times here, you force MATLAB to first create a variable with the initial length+1, then copy the contents, then delete the old variable. That's probably what is taking your code so long.
Most likely your SMTP server is tarpitting your client connection. This is a defense against runaway clients, or clients which submit large volumes of "junk" commands. From the manpage for Postfix smtpd:
smtpd_junk_command_limit (normal: 100, stress: 1)
The number of junk commands (NOOP, VRFY, ETRN or RSET) that a
remote SMTP client can send before the Postfix SMTP server
starts to increment the error counter with each junk command.
The smtpd daemon will insert a 1-second delay before replying after a certain amount of junk is seen. If you have root access to the smtp server in question, try an strace to see if nanosleep syscalls are being issued by the server.
Here is a trace from running your script against my local server. After 100 VRFY commands it starts sleeping between commands. Your server may have a lower limit of ~15 junk commands:
nanosleep({1, 0}, 0x7fffda9a67a0) = 0
poll([{fd=9, events=POLLOUT}], 1, 300000) = 1 ([{fd=9, revents=POLLOUT}])
write(9, "252 2.0.0 pat\r\n", 15) = 15
poll([{fd=9, events=POLLIN}], 1, 300000) = 1 ([{fd=9, revents=POLLIN}])
read(9, "VRFY pat\r\n", 4096) = 10
s.recv
blocks so if you have no more data on the socket then it will block forever.
You have to keep track of how much data you are receiving. You need to know this ahead of time so the client and the server can agree on the size.
Solving the exact same problem I also ran into the issue. I'm almost sure @samplebias is right. I found I could work around the "tarpitting" by abusing the poor system even more, tearing down and rebuilding every connection:
#[ ...Snip... ]
import smtplib
#[ ...Snip... ]
for USER in open(opts.USERS,'r'):
smtpserver = smtplib.SMTP(HOST,PORT)
smtpserver.ehlo()
verifyuser = smtpserver.verify(USER)
print("%s %s: %s") % (HOST.rstrip(), USER.rstrip(), verifyuser)
smtpserver.quit()
I'm curious whether this particular type of hammering would work in a live environment, but too certain it would make some people very unhappy.
PS, python: batteries included.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With