first draft for the myplc-docs package (cross-module change)
[myplc.git] / check-ssl-peering.py
1 #!/usr/bin/env plcsh
2 # checking ssl connection
3 # mimicks what PyCurl does
4
5 import sys
6 import pycurl
7
8 class check_ssl:
9
10     def getpeername_post_request (self,local_peername) :
11         methodname="GetPeerName"
12         from PLC.GPG import gpg_sign
13         signature = gpg_sign((),
14                              self.options.PLC_ROOT_GPG_KEY,
15                              self.options.PLC_ROOT_GPG_KEY_PUB,
16                          methodname)
17         post="""<?xml version='1.0'?>
18 <methodCall>
19 <methodName>GetPeerName</methodName>
20 <params>
21 <param>
22 <value><struct>
23 <member>
24 <name>AuthMethod</name>
25 <value><string>gpg</string></value>
26 </member>
27 <member>
28 <name>name</name>
29 <value><string>%s</string></value>
30 </member>
31 <member>
32 <name>signature</name>
33 <value><string>%s
34 </string></value>
35 </member>
36 </struct></value>
37 </param>
38 </params>
39 </methodCall>"""%(local_peername,signature)
40         return post
41
42     def check_url (self,url,local_peername,remote_peername,cert,timeout=10,verbose=1):
43         curl=pycurl.Curl()
44         curl.setopt(pycurl.NOSIGNAL, 1)
45         
46         # Follow redirections
47         curl.setopt(pycurl.FOLLOWLOCATION, 1)
48         curl.setopt(pycurl.URL, str(url))
49         cert_path = str(cert)
50         curl.setopt(pycurl.CAINFO, cert_path)
51         curl.setopt(pycurl.SSL_VERIFYPEER, 2)
52
53    # Set connection timeout
54         if timeout:
55             curl.setopt(pycurl.CONNECTTIMEOUT, timeout)
56             curl.setopt(pycurl.TIMEOUT, timeout)
57
58         curl.setopt(pycurl.VERBOSE, verbose)
59
60     # Post request
61         curl.setopt(pycurl.POST, 1)
62         curl.setopt(pycurl.POSTFIELDS, self.getpeername_post_request(local_peername))
63
64         import StringIO
65         b = StringIO.StringIO()
66         curl.setopt(pycurl.WRITEFUNCTION, b.write)
67
68         try:
69             curl.perform()
70             errcode = curl.getinfo(pycurl.HTTP_CODE)
71             response = b.getvalue()
72             print 'xmlrpc answer',response
73             if response.find('Failed') >= 0:
74                 print 'FAILURE : failed to authenticate ?'
75                 return False
76             elif response.find(remote_peername) <0:
77                 print 'FAILURE : xmlrpc round trip OK but peername does not match'
78                 return False
79             else:
80                 print 'SUCCESS'
81                 return True
82
83         except pycurl.error, err:
84             (errcode, errmsg) = err
85             if errcode == 60:
86                 print 'FAILURE', "SSL certificate validation failed, %r"%(errmsg)
87             elif errcode != 200:
88                 print 'FAILURE', "HTTP error %d, errmsg %r" % (errcode,errmsg)
89             return False
90
91     def main (self):
92         from optparse import OptionParser
93         usage="%prog [options] local-peername remote-peername cacert hostname [ .. hostname ]"
94         parser=OptionParser(usage=usage)
95         parser.add_option('-s','--secret',default='/etc/planetlab/secring.gpg',
96                           dest='PLC_ROOT_GPG_KEY',
97                           help='local GPG secret ring')
98         parser.add_option('-p','--public',default='/etc/planetlab/pubring.gpg',
99                           dest='PLC_ROOT_GPG_KEY_PUB',
100                           help='local GPG public ring')
101         (self.options, args) = parser.parse_args()
102
103         if len(args) < 4:
104             parser.print_help()
105             sys.exit(2)
106         arg=0
107         local_peername=args[arg] ; arg+=1
108         remote_peername=args[arg] ; arg+=1
109         cacert=args[arg]; arg+=1
110         ok=False
111         for hostname in args[arg:]:
112 # this does not seem to make any difference
113 #            for url_format in [ 'https://%s:443/PLCAPI/' , 'https://%s/PLCAPI/' ]:
114             for url_format in [ 'https://%s/PLCAPI/' ]:
115                 url=url_format%hostname
116                 print '============================== Checking url=',url
117                 if self.check_url(url,local_peername,remote_peername,cacert):
118                     ok=True
119         if ok:
120             return 0
121         else:
122             return 1
123             
124 if __name__ == '__main__':
125     sys.exit(check_ssl().main())