Python Training: DynDNS auto-login

It’s been a while, I know. For one reason or another I haven’t been getting round to updating the blog lately. Worst thing is I do have a bunch of stuff to post, so I hope to keep it coming in the near future. Anyway, I’ve been trying to polish my python skills a little bit, because I have to admit, it has to be one of the sweetest scripting languages out there: tons of support, and libraries, really doesn’t have a steep learning curve at all, object oriented (if you wish)…. there’s really nothing much I can say in the negative aspect.

For this second lil’ script I figured we could do something helpful once again. Many of you might host a little web server at home, or like ssh access to your machine, but keep forgetting you static ip, or even worst, get a dynamic ip from you ISP. I use DynDNS to help me get around these small IP troubles. And as helpful as it is, it also comes with one fairly annoying string attached, when you get yourself the free account, you need to login once a month to avoid your name address from expiring. I just want a name for my IP, and I tend to keep forgetting to do these things. So every month or so, two if I was lucky, I’d find my name address gone. Python script to the rescue. You can add this script to your crontab, and it will login automatically for you with the username and password provided to the script. Not rocket science, but definitely helpful.

The most relevant stuff here is the use of urllib and urllib2, which allow us to encode parameters for an HTTP POST request, and perform the actual page requests. The whole login process also uses a cookie, which made us have to use the cookielib to set up a cookiejar. Before you login, you are given a cookie, which you need to store for the process to succeed. Once you have that sorted, you can submit that form together with the right parameters (including a hidden one you need to parse from the HTML output). I figured out my explanation isn’t too clarifying, so without further ado, here’s the script:

#!/usr/bin/python

import urllib
import urllib2
import cookielib
import getopt
import sys

def getRandHTMLResponse(response):
	target = "<form id='login"
	targetresponse = "<div id='loginbox'"
	
	response = response[response.find(targetresponse):len(response)]
	return response[response.find(target)+len(target):response.find(target)+len(target):response.find(target)+len(target)+4]

def getHiddenRandHTMLResponse(response):
	target = "<input type='hidden' name='multiform' value='"
	targetresponse = "<div id='loginbox'"
	parsedres = response[response.find(targetresponse):len(response)]
	return parsedres[parsedres.find(target)+len(target):parsedres.find(target)+len(target)+34]


def checkLogin(response):
	target = "<title>DynDNS.com - My Account</title>"
	if response.find(target) == -1:
		return False
	return True


class HTMLSession:
	cj = None
	opener = None
	txHeaders = None

	def __init__(self, txHeaders):
		#The CookieJar will hold any cookies necessary throughout the login process.
		self.cj = cookielib.MozillaCookieJar()
		self.txHeaders = txHeaders
		self.opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cj))
        	urllib2.install_opener(self.opener)

	def setHeaders(self, txheaders):
		self.txHeaders = txHeaders
	
	def getHeaders(self):
		return self.txHeaders
	
	def openURI(self, uri, txdata):
		try:
			req = urllib2.Request(uri, txdata, self.txHeaders)
			# create a request object
	
			handle = urllib2.urlopen(req)
			# and open it to return a handle on the url

		except IOError as e:
			print 'we failed to open "%s".' % uri

			if hasattr(e, 'code'):
				print 'We failed with error code - %s.' % e.code
			elif hasattr(e, 'reason'):
				print "The error object has the following 'reason' attribute :"
				print e.reason
				print "This usually means the server doesn't exist,'"
				print "is down, or we don't have an internet connection."
				return None
		else:
			return handle.read()


def main(argv):
	username = ""
	password = ""
	hiddenval = ""
	theurl = "https://www.dyndns.com/account/entrance/"
	thelogouturl = "https://www.dyndns.com/account/entrance/?__logout=1"
	txdata = None
	txheaders =  {'User-agent' : 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'}
	# fake a user agent, some websites (like google) don't like automated exploration


	try:

		opts, args = getopt.getopt(argv, "hu:p:", ["help", "username=","password="])
	except getopt.GetoptError:
		usage()
		exit(2)
	for opt, arg in opts:
		if opt in ("-h", "--help"):
			usage()
			exit(2)
		elif opt in ("-u", "--username"):
			username = arg
		elif opt in ("-p", "--password"):
			password = arg

	myhtmlsession = HTMLSession(txheaders)
	response = myhtmlsession.openURI(theurl, None)
	
	if response == None:
		sys.exit(0)
	
	hiddenval = getHiddenRandHTMLResponse(response)
	txdata = urllib.urlencode({'username':username, 'password':password, 'multiform':hiddenval, 'submit': "Log in"})
	
	response = myhtmlsession.openURI(theurl, txdata)
	if response == None:
		sys.exit(0)

	#we should sleep here for about 10 seconds.
	if checkLogin(response):
		print('We have succesfully logged into DynDNS.')

	response = myhtmlsession.openURI(thelogouturl, None)
	if response == None:
		sys.exit(0)


if __name__ == "__main__":
	main(sys.argv[1:])

One thought on “Python Training: DynDNS auto-login

  1. Was going to script something myself similar but figured there’d be someone who may have already done something like this. Good stuff, except you don’t have the routine usage() defined.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>