change cli to use (type, hrn) instead of record in remove calls
[sfa.git] / cmdline / clientstub.py
1 #!/usr/bin/python
2
3 import os, sys
4 from M2Crypto import SSL
5 from sec import *
6 from cliexcep import *
7 import report
8
9 # XXX SMBAKER: changed MAX_RESULT from 3000B to 32KB
10 MAX_RESULT = 32768
11
12 def verify_callback(preverify_ok, ctx):
13     return 1
14
15 class GENIClient():
16     def __init__(self, hrn, type, id_file, id_key_file, acc_file, cred_file):
17         self.hrn = hrn
18         self.type = type
19
20         #check if the certificate and the private key exists, terminate if not
21         if not os.path.exists(id_file):
22             report.error("Certificate file " + id_file + " does not exist")
23             raise NonexistingFile(id_file)
24
25         if not os.path.exists(id_key_file):
26             report.error("Key file: " + id_key_file + " does not exist")
27             raise NonexistingFile(key_file)
28
29         report.trace("cert: " + id_file + ", key_file: " + id_key_file)
30
31         #check the acc and cred files
32         if not os.path.exists(acc_file) or not is_valid_chain(acc_file):
33             report.trace("replacing acc_file: " + acc_file + " with anonymous acc")
34             open(acc_file, 'w').write('ANONYM')
35
36         if not os.path.exists(cred_file) or not is_valid_chain(cred_file):
37             report.trace("replacing cred_file: " + cred_file + " with no_cred")
38             open(cred_file, 'w').write('NO_CRED')
39
40         #initialize the security system
41         self.sec = Sec('client',  id_file, id_key_file, acc_file, cred_file)
42         #ssl parameters
43         self.ctx = SSL.Context()
44         self.ctx.load_cert(self.sec.id_file, self.sec.id_key_file)
45         self.ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, depth=9, callback=verify_callback)
46
47     def connect(self, host, port):
48         #if the acc and cred needs renewal then do call to authority
49         if self.type == 'user' or self.type == 'slice' or self.type == 'SA':
50             reg_type = 'slice'
51         else:
52             reg_type ='component'
53
54         auth_host = host
55         auth_port = port
56
57         report.trace("renewing accounting")
58         renew_res1 = renew_cert('accounting', '.', reg_type, self.hrn, None, None, (auth_host, auth_port), self.sec)
59         if renew_res1 == None:
60             report.error("There is no certificate in the directory .")
61             raise NoCertInDirectory(".")
62
63         report.trace("renewing credential")
64         renew_res2 = renew_cert('credential', '.', reg_type, self.hrn, None, None, (auth_host, auth_port), self.sec)
65         # XXX check result of renew_res2 ?
66
67         #connect to server
68         server = SSL.Connection(self.ctx)
69
70         report.trace("connecting")
71         server.connect((host,port))
72
73         report.trace("authenticating")
74         peer = self.sec.auth_protocol(server)
75         if peer:
76             report.trace("Authentication successful")
77             return server
78         else:
79             report.error("Authentication failed")
80             raise AuthenticationFailed()
81
82 def toFileFormat(res_str):
83     out_str = ""
84     try:
85         res_dict = eval(res_str)
86         if res_dict['geni'].has_key('pubkey'): # in public key, replace '\n' with ' '
87             pubkey = res_dict['geni']['pubkey']
88             pubkey = pubkey.split('-----BEGIN RSA PRIVATE KEY-----')[1].split('-----END RSA PRIVATE KEY-----')[0].replace('\n',' ')
89             pubkey = '-----BEGIN RSA PRIVATE KEY-----'+pubkey+'-----END RSA PRIVATE KEY-----'
90             res_dict['geni']['pubkey'] = pubkey
91
92         if res_dict.has_key('message'):
93             out_str = res_dict['message']+'\n'
94         else:
95             out_str = "{'geni':{\n"
96             for key in res_dict['geni']:
97                 val = ''
98                 if res_dict['geni'][key] == None:
99                     val = ''
100                 elif isinstance(res_dict['geni'][key], str):
101                     val = res_dict['geni'][key]
102                 else:
103                     val = str(res_dict['geni'][key])
104                 out_str = out_str+"'"+key+"':"+val+"\n"
105             out_str = out_str + "}\n"
106             out_str = out_str + "'pl':{\n"
107             for key in res_dict['pl']:
108                 val = ''
109                 if res_dict['pl'][key] == None:
110                     val = ''
111                 if isinstance(res_dict['pl'][key], str):
112                     val = res_dict['pl'][key]
113                 else:
114                     val = str(res_dict['pl'][key])
115                 out_str = out_str+"'"+key+"':"+val+"\n"
116             out_str = out_str + "}}"
117     except:
118         out_str = res_str
119     return out_str
120
121 def evaluate(call_data):
122     call_data = eval(call_data)
123     #adjust the key format to obey server's storage format
124     if call_data['g_params'].has_key('pubkey'): #replace the ' ' with '\n'
125         pubkey = call_data['g_params']['pubkey']
126         pubkey = pubkey.split('-----BEGIN RSA PRIVATE KEY-----')[1].split('-----END RSA PRIVATE KEY-----')[0].replace(' ','\n')
127         pubkey = '-----BEGIN RSA PRIVATE KEY-----'+pubkey+'-----END RSA PRIVATE KEY-----'
128         call_data['g_params']['pubkey'] = pubkey
129     return call_data
130
131 def oldmain():
132     try:
133         #read the input file
134         fp = open('tmp_input.txt', 'r')
135         user_data = fp.readline()
136         call_data = fp.read()
137         print 'Read file.\n'
138
139         #client related info
140         HRN = user_data.split(' ')[0]
141         TYPE = user_data.split(' ')[1].split('\n')[0]
142         name = get_leaf(HRN)
143         ID_FILE = name+'.cert'
144         ID_KEY_FILE = name+'.pkey'
145         ACC_FILE = 'acc_file'
146         CRED_FILE = 'cred_file'
147         my_client = GENIClient(HRN, TYPE, ID_FILE, ID_KEY_FILE, ACC_FILE, CRED_FILE)
148         print 'Constructed client.\n'
149
150         #operation call
151         message = evaluate(call_data)
152         server = my_client.connect(SERVER_HOST, SERVER_PORT)
153         if server:
154             server.write(str(message))
155             result = toFileFormat(server.read(MAX_RESULT))
156             server.close()
157             print 'Performed the call.\n'
158         else:
159             result = "Error in client data structures.\n"
160
161         #write result to output file
162         open('tmp_output.txt','w').write(result)
163         print 'Written to file.\n'
164     except "XXX": # XXX smbaker
165         #write result to output file
166         open('tmp_output.txt','w').write("An error occurred in client stub.\n")
167         print 'Exception occurred.\n'
168
169 #if __name__=="__main__":
170 #    print 'Client started.\n'
171 #    os.system("echo foo > foo.txt")
172 #    os.system("mv tmp_input.3 tmp_input.4")
173 #    os.system("mv tmp_input.2 tmp_input.3")
174 #    os.system("mv tmp_input.1 tmp_input.2")
175 #    os.system("cp tmp_input.txt tmp_input.1")
176 #    main()