whois/whois.py
changeset 32 5f851e9c196a
parent 12 c57439b500cb
child 34 f9da616f15cf
equal deleted inserted replaced
31:92176112c2d6 32:5f851e9c196a
    31           Author:  Chris Wolf
    31           Author:  Chris Wolf
    32 """
    32 """
    33 import sys
    33 import sys
    34 import socket
    34 import socket
    35 import optparse
    35 import optparse
    36 #import pdb
    36 # import pdb
       
    37 
    37 
    38 
    38 def enforce_ascii(a):
    39 def enforce_ascii(a):
    39     if isinstance(a, str) or isinstance(a, unicode):
    40     if isinstance(a, str) or isinstance(a, unicode):
    40         # return a.encode('ascii', 'replace')
    41         # return a.encode('ascii', 'replace')
    41         r = ""
    42         r = ""
    46                 r += i
    47                 r += i
    47         return r
    48         return r
    48     else:
    49     else:
    49         return a
    50         return a
    50 
    51 
    51 class NICClient(object) :
    52 
    52 
    53 class NICClient(object):
    53     ABUSEHOST           = "whois.abuse.net"
    54 
    54     NICHOST             = "whois.crsnic.net"
    55     ABUSEHOST = "whois.abuse.net"
    55     INICHOST            = "whois.networksolutions.com"
    56     NICHOST = "whois.crsnic.net"
    56     DNICHOST            = "whois.nic.mil"
    57     INICHOST = "whois.networksolutions.com"
    57     GNICHOST            = "whois.nic.gov"
    58     DNICHOST = "whois.nic.mil"
    58     ANICHOST            = "whois.arin.net"
    59     GNICHOST = "whois.nic.gov"
    59     LNICHOST            = "whois.lacnic.net"
    60     ANICHOST = "whois.arin.net"
    60     RNICHOST            = "whois.ripe.net"
    61     LNICHOST = "whois.lacnic.net"
    61     PNICHOST            = "whois.apnic.net"
    62     RNICHOST = "whois.ripe.net"
    62     MNICHOST            = "whois.ra.net"
    63     PNICHOST = "whois.apnic.net"
    63     QNICHOST_TAIL       = ".whois-servers.net"
    64     MNICHOST = "whois.ra.net"
    64     SNICHOST            = "whois.6bone.net"
    65     QNICHOST_TAIL = ".whois-servers.net"
    65     BNICHOST            = "whois.registro.br"
    66     SNICHOST = "whois.6bone.net"
    66     NORIDHOST           = "whois.norid.no"
    67     BNICHOST = "whois.registro.br"
    67     IANAHOST            = "whois.iana.org"
    68     NORIDHOST = "whois.norid.no"
    68     DENICHOST           = "de.whois-servers.net"
    69     IANAHOST = "whois.iana.org"
    69     DEFAULT_PORT        = "nicname"
    70     DENICHOST = "de.whois-servers.net"
    70     WHOIS_SERVER_ID     = "Whois Server:"
    71     DEFAULT_PORT = "nicname"
       
    72     WHOIS_SERVER_ID = "Whois Server:"
    71     WHOIS_ORG_SERVER_ID = "Registrant Street1:Whois Server:"
    73     WHOIS_ORG_SERVER_ID = "Registrant Street1:Whois Server:"
    72 
    74 
    73 
    75     WHOIS_RECURSE = 0x01
    74     WHOIS_RECURSE       = 0x01
    76     WHOIS_QUICK = 0x02
    75     WHOIS_QUICK         = 0x02
    77 
    76 
    78     ip_whois = [LNICHOST, RNICHOST, PNICHOST, BNICHOST]
    77     ip_whois = [ LNICHOST, RNICHOST, PNICHOST, BNICHOST ]
    79 
    78 
    80     def __init__(self):
    79     def __init__(self) :
       
    80         self.use_qnichost = False
    81         self.use_qnichost = False
    81        
    82 
    82     def findwhois_server(self, buf, hostname):
    83     def findwhois_server(self, buf, hostname):
    83         """Search the initial TLD lookup results for the regional-specifc
    84         """Search the initial TLD lookup results for the regional-specifc
    84         whois server for getting contact details.
    85         whois server for getting contact details.
    85         """
    86         """
    86         #print 'finding whois server'
    87         # print 'finding whois server'
    87         #print 'parameters:', buf, 'hostname', hostname
    88         # print 'parameters:', buf, 'hostname', hostname
    88         nhost = None
    89         nhost = None
    89         parts_index = 1
    90         parts_index = 1
    90         start = buf.find(NICClient.WHOIS_SERVER_ID)
    91         start = buf.find(NICClient.WHOIS_SERVER_ID)
    91         #print 'start', start
    92         # print 'start', start
    92         if (start == -1):
    93         if (start == -1):
    93             start = buf.find(NICClient.WHOIS_ORG_SERVER_ID)
    94             start = buf.find(NICClient.WHOIS_ORG_SERVER_ID)
    94             parts_index = 2
    95             parts_index = 2
    95        
    96 
    96         if (start > -1):  
    97         if (start > -1):
    97             end = buf[start:].find('\n')
    98             end = buf[start:].find('\n')
    98             #print 'end:', end
    99             # print 'end:', end
    99             whois_line = buf[start:end+start]
   100             whois_line = buf[start:end+start]
   100             #print 'whois_line', whois_line
   101             # print 'whois_line', whois_line
   101             nhost = whois_line.split(NICClient.WHOIS_SERVER_ID+' ').pop()
   102             nhost = whois_line.split(NICClient.WHOIS_SERVER_ID+' ').pop()
   102             nhost = nhost.split('http://').pop()
   103             nhost = nhost.split('http://').pop()
   103             #if the whois address is domain.tld/something then
   104             # if the whois address is domain.tld/something then
   104             #s.connect((hostname, 43)) does not work
   105             # s.connect((hostname, 43)) does not work
   105             if nhost.count('/') > 0:
   106             if nhost.count('/') > 0:
   106                 nhost = None
   107                 nhost = None
   107             #print 'nhost:',nhost
   108             # print 'nhost:',nhost
   108         elif (hostname == NICClient.ANICHOST):
   109         elif (hostname == NICClient.ANICHOST):
   109             for nichost in NICClient.ip_whois:
   110             for nichost in NICClient.ip_whois:
   110                 if (buf.find(nichost) != -1):
   111                 if (buf.find(nichost) != -1):
   111                     nhost = nichost
   112                     nhost = nichost
   112                     break
   113                     break
   113         return nhost
   114         return nhost
   114        
   115 
   115     def whois(self, query, hostname, flags):
   116     def whois(self, query, hostname, flags):
   116         """Perform initial lookup with TLD whois server
   117         """Perform initial lookup with TLD whois server
   117         then, if the quick flag is false, search that result
   118         then, if the quick flag is false, search that result
   118         for the region-specifc whois server and do a lookup
   119         for the region-specifc whois server and do a lookup
   119         there for contact details
   120         there for contact details
   120         """
   121         """
   121         #print 'Performing the whois'
   122         # print 'Performing the whois'
   122         #print 'parameters given:', query, hostname, flags
   123         # print 'parameters given:', query, hostname, flags
   123         #pdb.set_trace()
   124         # pdb.set_trace()
   124         s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   125         s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   125         s.connect((hostname, 43))
   126         s.connect((hostname, 43))
   126         """send takes bytes as an input
   127         """send takes bytes as an input
   127         """
   128         """
   128         queryBytes = None
   129         queryBytes = None
   129         if (hostname == NICClient.DENICHOST):
   130         if (hostname == NICClient.DENICHOST):
   130             #print 'the domain is in NIC DENIC'
   131             # print 'the domain is in NIC DENIC'
   131             queryBytes = ("-T dn,ace -C UTF-8 " + query + "\r\n").encode()
   132             queryBytes = ("-T dn,ace -C UTF-8 " + query + "\r\n").encode()
   132             #print 'queryBytes:', queryBytes
   133             # print 'queryBytes:', queryBytes
   133         else:
   134         else:
   134             queryBytes = (query  + "\r\n").encode()        
   135             queryBytes = (query + "\r\n").encode()
   135         s.send(queryBytes)
   136         s.send(queryBytes)
   136         """recv returns bytes
   137         """recv returns bytes
   137         """
   138         """
   138         #print s
   139         # print s
   139         response = b''
   140         response = b''
   140         while True:
   141         while True:
   141             d = s.recv(4096)
   142             d = s.recv(4096)
   142             response += d
   143             response += d
   143             if not d:
   144             if not d:
   144                 break
   145                 break
   145         s.close()
   146         s.close()
   146         #pdb.set_trace()
   147         # pdb.set_trace()
   147         nhost = None
   148         nhost = None
   148         #print 'response', response
   149         # print 'response', response
   149         response = enforce_ascii(response)
   150         response = enforce_ascii(response)
   150         if (flags & NICClient.WHOIS_RECURSE and nhost == None):
   151         if (flags & NICClient.WHOIS_RECURSE and nhost is None):
   151             #print 'Inside first if'
   152             # print 'Inside first if'
   152             nhost = self.findwhois_server(response.decode(), hostname)
   153             nhost = self.findwhois_server(response.decode(), hostname)
   153             #print 'nhost is:', nhost
   154             # print 'nhost is:', nhost
   154         if (nhost != None):
   155         if (nhost is not None):
   155             #print 'inside second if'
   156             # print 'inside second if'
   156             response += self.whois(query, nhost, 0)
   157             response += self.whois(query, nhost, 0)
   157             #print 'response', response
   158             # print 'response', response
   158         #print 'returning whois response'
   159         # print 'returning whois response'
   159         return response.decode()
   160         return response.decode()
   160    
   161 
   161     def choose_server(self, domain):
   162     def choose_server(self, domain):
   162         """Choose initial lookup NIC host"""
   163         """Choose initial lookup NIC host"""
   163         if (domain.endswith("-NORID")):
   164         if (domain.endswith("-NORID")):
   164             return NICClient.NORIDHOST
   165             return NICClient.NORIDHOST
   165         pos = domain.rfind('.')
   166         pos = domain.rfind('.')
   166         if (pos == -1):
   167         if (pos == -1):
   167             return None
   168             return None
   168         tld = domain[pos+1:]
   169         tld = domain[pos+1:]
   169         if (tld[0].isdigit()):
   170         if (tld[0].isdigit()):
   170             return NICClient.ANICHOST
   171             return NICClient.ANICHOST
   171    
   172 
   172         return tld + NICClient.QNICHOST_TAIL
   173         return tld + NICClient.QNICHOST_TAIL
   173    
   174 
   174     def whois_lookup(self, options, query_arg, flags):
   175     def whois_lookup(self, options, query_arg, flags):
   175         """Main entry point: Perform initial lookup on TLD whois server,
   176         """Main entry point: Perform initial lookup on TLD whois server,
   176         or other server to get region-specific whois server, then if quick
   177         or other server to get region-specific whois server, then if quick
   177         flag is false, perform a second lookup on the region-specific
   178         flag is false, perform a second lookup on the region-specific
   178         server for contact records"""
   179         server for contact records"""
   179         #print 'whois_lookup'
   180         # print 'whois_lookup'
   180         nichost = None
   181         nichost = None
   181         #pdb.set_trace()
   182         # pdb.set_trace()
   182         # this would be the case when this function is called by other than main
   183         # whoud happen when this function is called by other than main
   183         if (options == None):                    
   184         if (options is None):
   184             options = {}
   185             options = {}
   185      
   186 
   186         if ( (not 'whoishost' in options or options['whoishost'] == None)
   187         if (('whoishost' not in options or options['whoishost'] is None)
   187             and (not 'country' in options or options['country'] == None)):
   188                 and ('country' not in options or options['country'] is None)):
   188             self.use_qnichost = True
   189             self.use_qnichost = True
   189             options['whoishost'] = NICClient.NICHOST
   190             options['whoishost'] = NICClient.NICHOST
   190             if ( not (flags & NICClient.WHOIS_QUICK)):
   191             if (not (flags & NICClient.WHOIS_QUICK)):
   191                 flags |= NICClient.WHOIS_RECURSE
   192                 flags |= NICClient.WHOIS_RECURSE
   192            
   193 
   193         if ('country' in options and options['country'] != None):
   194         if ('country' in options and options['country'] is not None):
   194             result = self.whois(query_arg, options['country'] + NICClient.QNICHOST_TAIL, flags)
   195             result = self.whois(
       
   196                 query_arg,
       
   197                 options['country'] + NICClient.QNICHOST_TAIL,
       
   198                 flags
       
   199             )
   195         elif (self.use_qnichost):
   200         elif (self.use_qnichost):
   196             nichost = self.choose_server(query_arg)
   201             nichost = self.choose_server(query_arg)
   197             if (nichost != None):
   202             if (nichost is not None):
   198                 result = self.whois(query_arg, nichost, flags)
   203                 result = self.whois(query_arg, nichost, flags)
   199         else:
   204         else:
   200             result = self.whois(query_arg, options['whoishost'], flags)
   205             result = self.whois(query_arg, options['whoishost'], flags)
   201         #print 'whois_lookup finished'
   206         # print 'whois_lookup finished'
   202         return result
   207         return result
   203 #---- END OF NICClient class def ---------------------
   208 
   204    
   209 
   205 def parse_command_line(argv):
   210 def parse_command_line(argv):
   206     """Options handling mostly follows the UNIX whois(1) man page, except
   211     """Options handling mostly follows the UNIX whois(1) man page, except
   207     long-form options can also be used.
   212     long-form options can also be used.
   208     """
   213     """
   209     flags = 0
   214     flags = 0
   210    
   215 
   211     usage = "usage: %prog [options] name"
   216     usage = "usage: %prog [options] name"
   212            
   217 
   213     parser = optparse.OptionParser(add_help_option=False, usage=usage)
   218     parser = optparse.OptionParser(add_help_option=False, usage=usage)
   214     parser.add_option("-a", "--arin", action="store_const",
   219     parser.add_option("-a", "--arin", action="store_const",
   215                       const=NICClient.ANICHOST, dest="whoishost",
   220                       const=NICClient.ANICHOST, dest="whoishost",
   216                       help="Lookup using host " + NICClient.ANICHOST)
   221                       help="Lookup using host " + NICClient.ANICHOST)
   217     parser.add_option("-A", "--apnic", action="store_const",
   222     parser.add_option("-A", "--apnic", action="store_const",
   229     parser.add_option("-g", "--gov", action="store_const",
   234     parser.add_option("-g", "--gov", action="store_const",
   230                       const=NICClient.GNICHOST, dest="whoishost",
   235                       const=NICClient.GNICHOST, dest="whoishost",
   231                       help="Lookup using host " + NICClient.GNICHOST)
   236                       help="Lookup using host " + NICClient.GNICHOST)
   232     parser.add_option("-h", "--host", action="store",
   237     parser.add_option("-h", "--host", action="store",
   233                       type="string", dest="whoishost",
   238                       type="string", dest="whoishost",
   234                        help="Lookup using specified whois host")
   239                       help="Lookup using specified whois host")
   235     parser.add_option("-i", "--nws", action="store_const",
   240     parser.add_option("-i", "--nws", action="store_const",
   236                       const=NICClient.INICHOST, dest="whoishost",
   241                       const=NICClient.INICHOST, dest="whoishost",
   237                       help="Lookup using host " + NICClient.INICHOST)
   242                       help="Lookup using host " + NICClient.INICHOST)
   238     parser.add_option("-I", "--iana", action="store_const",
   243     parser.add_option("-I", "--iana", action="store_const",
   239                       const=NICClient.IANAHOST, dest="whoishost",
   244                       const=NICClient.IANAHOST, dest="whoishost",
   246                       help="Lookup using host " + NICClient.MNICHOST)
   251                       help="Lookup using host " + NICClient.MNICHOST)
   247     parser.add_option("-p", "--port", action="store",
   252     parser.add_option("-p", "--port", action="store",
   248                       type="int", dest="port",
   253                       type="int", dest="port",
   249                       help="Lookup using specified tcp port")
   254                       help="Lookup using specified tcp port")
   250     parser.add_option("-Q", "--quick", action="store_true",
   255     parser.add_option("-Q", "--quick", action="store_true",
   251                      dest="b_quicklookup",
   256                       dest="b_quicklookup",
   252                      help="Perform quick lookup")
   257                       help="Perform quick lookup")
   253     parser.add_option("-r", "--ripe", action="store_const",
   258     parser.add_option("-r", "--ripe", action="store_const",
   254                       const=NICClient.RNICHOST, dest="whoishost",
   259                       const=NICClient.RNICHOST, dest="whoishost",
   255                       help="Lookup using host " + NICClient.RNICHOST)
   260                       help="Lookup using host " + NICClient.RNICHOST)
   256     parser.add_option("-R", "--ru", action="store_const",
   261     parser.add_option("-R", "--ru", action="store_const",
   257                       const="ru", dest="country",
   262                       const="ru", dest="country",
   259     parser.add_option("-6", "--6bone", action="store_const",
   264     parser.add_option("-6", "--6bone", action="store_const",
   260                       const=NICClient.SNICHOST, dest="whoishost",
   265                       const=NICClient.SNICHOST, dest="whoishost",
   261                       help="Lookup using host " + NICClient.SNICHOST)
   266                       help="Lookup using host " + NICClient.SNICHOST)
   262     parser.add_option("-?", "--help", action="help")
   267     parser.add_option("-?", "--help", action="help")
   263 
   268 
   264        
       
   265     return parser.parse_args(argv)
   269     return parser.parse_args(argv)
   266    
   270 
   267 if __name__ == "__main__":
   271 if __name__ == "__main__":
   268     flags = 0
   272     flags = 0
   269     nic_client = NICClient()
   273     nic_client = NICClient()
   270     (options, args) = parse_command_line(sys.argv)
   274     (options, args) = parse_command_line(sys.argv)
   271     if (options.b_quicklookup is True):
   275     if (options.b_quicklookup is True):
   272         flags = flags|NICClient.WHOIS_QUICK
   276         flags = flags | NICClient.WHOIS_QUICK
   273     print(nic_client.whois_lookup(options.__dict__, args[1], flags))
   277     print(nic_client.whois_lookup(options.__dict__, args[1], flags))