b91834df27cb5ecfc62f4023364870f7f3f90b65
[sfa.git] / server / server.py
1 #wrapper for the registry
2
3 # Socket address
4 LISTEN_HOST = '127.0.0.1' 
5 LISTEN_PORT = 8002
6 SR_FILE = 'interface_tree_sr'
7 CR_FILE = 'interface_tree_cr'
8
9 AUTH_HOST = '127.0.0.1' 
10 AUTH_PORT = 8002
11
12 import SocketServer
13
14 import socket, os, sys
15 from M2Crypto import SSL
16 from M2Crypto.SSL import SSLError
17 from M2Crypto import X509
18 from pg import DB
19 sys.path.append('../')
20 sys.path.append('../util')
21 sys.path.append('../util/sec')
22 sys.path.append("../PLCAPI/trunk")
23 from util import *
24 from tree import *
25 from excep import *
26 from sec import *
27 from db import *
28 from pl_to_geni import *
29 import time, datetime, calendar
30
31 # Import the API Shell
32 from PLC.Shell import Shell
33 shell = Shell(globals = globals())             # Add all the API methods to the global namespace
34 ##                 ,config = options.config,     # Configuartion file (Optional. Defaluts to /etc/planetlab/plc_config)
35 ##                 url = options.url,           # XML-RPC server uirl (Optional)
36 ##                 xmlrpc = options.xmlrpc,     # Use XML-RPC ? (Optional)
37 ##                 cacert = options.cacert,     # Certificate to use (Optional)
38 ##                 method = options.method,     # API authentication method (Optional)
39 ##                 role = options.role,         # Role to assume (Optional)
40 ##                 user = options.user,         # (Optional)
41 ##                 password = options.password, # (Required if user is specified)
42 ##                 session = options.session)   # Session authentication 
43
44 class GENIServer(SSL.SSLServer):
45
46     #record is the record to be registered
47     #dbinfo is the information showing the relevant tables to act (db and table name), in the subtree this interface manages
48     def register(self, record, dbinfo):
49         cnx = dbinfo[0]
50         table = dbinfo[1] 
51         type = record['g_params']["type"]
52         
53         try:
54             #check if record already exists
55             existing_res = check_exists_geni(record, dbinfo)
56             if existing_res:
57                     raise ExistingRecord("Record "+record['g_params']['hrn']+" already exists.\n" )
58             if type == "SA" or type == 'MA':
59                 #geni parameters
60                 record['g_params']["wrapperurl"] = 'local'
61                 reg_type = ''
62                 if type == "SA":
63                     reg_type = 'slc'
64                 else:
65                     reg_type = 'comp'
66                 rights = '(2-0)(4-0)(6-0)(7-0)(8-0)(9-0)(0-1)(1-1)(2-1)(3-1)(4-1)(5-1)(6-1)(7-1)(8-1)(9-1)'
67                 rights = rights + '#0:reg:'+reg_type+":"+obtain_authority(record['g_params']["hrn"])+'#1:reg:'+reg_type+":"+record['g_params']["hrn"]
68                 record['g_params']['rights'] = rights
69                 long_hrn = record['g_params']["hrn"]
70                 hrn_suffix = get_leaf(record['g_params']["hrn"])
71                 pointer = -1
72                 login_base = ''
73                 #PL specific parameters
74                 site_fields = record['p_params']
75                 
76                 #check if the authority's site exists already
77                 other_tree = None
78                 if reg_type == 'slc':
79                     other_tree = self.cr_tree
80                 else:
81                     other_tree = self.sr_tree
82                 info = other_tree.tree_lookup(long_hrn)
83                 if info:
84                     login_base = info.login_base
85                     pointer = cnx.query("SELECT site_id FROM sites WHERE login_base = '"+login_base+"';").dictresult()[0]['site_id']
86                 else:
87                     #check if login_base is specified
88                     if site_fields.has_key('login_base'):
89                         login_base = site_fields['login_base']
90                         querystr = "SELECT * FROM sites WHERE login_base = '"+login_base+"'"
91                         res = cnx.query(querystr).dictresult()
92                         if res:
93                             return "Site login_base '"+login_base+", already exists in the system. Try another name.\n"
94                     else:
95                         #determine new login_base
96                         login_base = hrn_to_loginbase(long_hrn)
97                         for i in range(1,10):
98                             querystr = "SELECT * FROM sites WHERE login_base = '"+login_base+"'"
99                             res = cnx.query(querystr).dictresult()
100                             if not res:
101                                 break
102                             else:
103                                 login_base = hrn_to_loginbase(long_hrn, i)
104                         site_fields['login_base'] = login_base                        
105                     #add into PL table
106                     pointer = shell.AddSite(pl_auth, site_fields)
107                     
108                 #create the folder for the site and keys
109                 curdir = os.getcwd()
110                 if reg_type == 'slc':
111                     dir_type = 'slice'
112                 else:
113                     dir_type = 'component'
114                 dirname = dir_type+'/'+(long_hrn).replace('.','/')
115                 if os.path.exists(dirname):
116                     os.system('rm -rf '+dirname)
117                 os.makedirs(dirname)
118                 os.chdir(dirname)
119                 create_self_cert(hrn_suffix)
120                 os.chdir(curdir)
121                 
122                 #insert into GENI parent table  
123                 record['g_params']["hrn"] = get_leaf(record['g_params']["hrn"])
124                 record['g_params']['pubkey'] = X509.load_cert(dirname+'/'+hrn_suffix+'.cert').get_pubkey().as_pem(cipher=None)
125                 record['g_params']['pointer'] = pointer
126                 querystr = generate_querystr('INSERT', table, record['g_params'])
127                 cnx.query(querystr)
128                 
129                 #create the new table for the site
130                 new_table_name = hrn_to_tablename(long_hrn, reg_type)
131                 cnx.query('DROP TABLE IF EXISTS '+new_table_name) #drop the table if it exists
132                 querystr = "CREATE TABLE "+new_table_name+" ( \
133                 hrn text, \
134                 type text, \
135                 uuid text, \
136                 userlist text, \
137                 rights text, \
138                 description text, \
139                 pubkey text, \
140                 wrapperURL text, \
141                 disabled text, \
142                 pointer integer);"
143                 cnx.query(querystr)
144                 
145                 #update the interface tree
146                 tree = None
147                 if type == 'SA':
148                     tree = self.sr_tree
149                 else:
150                     tree = self.cr_tree
151                 parent_data = tree.tree_lookup(obtain_authority(long_hrn)).node_data
152                 parent_db_info = parent_data['db_info']
153                 parent_key_info = parent_data['key_info']
154                 info = TreeNodeInfo()
155                 info.name = long_hrn
156                 info.login_base = login_base
157                 db_info = DbInfo()
158                 key_info = KeyInfo()
159                 info.node_data = {'db_info':db_info, 'key_info':key_info}
160                 
161                 db_info.table_name = new_table_name
162                 db_info.db_name = parent_db_info.db_name
163                 db_info.address = parent_db_info.address
164                 db_info.port = parent_db_info.port
165                 db_info.user = parent_db_info.user
166                 db_info.password = parent_db_info.password
167                 
168                 key_info.acc_file = ''
169                 key_info.cred_file = ''
170                 key_info.folder = parent_key_info.folder+'/'+hrn_suffix
171                 key_info.id_file = hrn_suffix+'.cert'
172                 key_info.id_key_file = hrn_suffix+'.pkey'
173
174                 tree.tree_add(info)
175                 if type == 'SA':
176                     self.save_state('sr')
177                 else:
178                     self.save_state('cr')
179                 return type+' '+long_hrn + ' is successfully added.\n'
180             
181             elif type == "slice":
182                 login_base = get_leaf(obtain_authority(record['g_params']["hrn"]))
183                 #geni parameters
184                 #hrn is inside dictionary, passed by the client
185                 long_hrn = record['g_params']["hrn"]
186                 hrn_suffix = get_leaf(record['g_params']["hrn"])
187                 #PL specific parameters
188                 slice_fields = record['p_params']
189                 slice_fields['name'] = login_base + "_" + hrn_suffix
190                 
191                 #insert the PL tables first
192                 pointer = shell.AddSlice(pl_auth, slice_fields)
193                 #insert into the GENI tables
194                 record['g_params']["pointer"] = pointer
195                 querystr = "UPDATE "+table+" SET hrn = '"+hrn_suffix+"'"
196                 if record['g_params'].has_key('userlist'):
197                     querystr = querystr+" userlist = '"+record['g_params']['userlist']+"'"
198                 if record['g_params'].has_key('rights'):
199                     querystr = querystr+" rights = '"+record['g_params']['rights']+"'"
200                 querystr = querystr+" WHERE pointer = "+str(record['g_params']["pointer"])
201                 cnx.query(querystr)
202                 return "Slice "+long_hrn+" is successfully added.\n"
203             elif type == "user":        
204                 #geni parameters
205                 #hrn and pubkey are inside dictinary, passed by the client
206                 long_hrn = record['g_params']["hrn"]
207                 record['g_params']["hrn"] = get_leaf(record['g_params']["hrn"])
208                 rights = '(2-0)(4-0)(6-0)(7-0)(8-0)(9-0)'
209                 rights = rights + '#0:reg:slc:'+obtain_authority(record['g_params']["hrn"])
210                 record['g_params']["rights"] = rights
211                 #PL specific parameters
212                 user_fields = record['p_params']
213                 
214                 #insert the PL tables first
215                 pointer = shell.AddPerson(pl_auth, user_fields)
216                 #insert into the GENI tables
217                 record['g_params']["pointer"] = pointer
218                 querystr = generate_querystr('INSERT', table, record['g_params'])
219                 cnx.query(querystr)
220                 return "User "+long_hrn+" is successfully added.\n"
221                 
222             elif type == "node":        
223                 #geni parameters
224                 #hrn and pubkey are inside dictinary, passed by the client
225                 long_hrn = record['g_params']["hrn"]
226                 login_base = self.cr_tree.tree_lookup(obtain_authority(long_hrn)).login_base
227                 record['g_params']["hrn"] = get_leaf(record['g_params']["hrn"])
228                 rights = ''
229                 record['g_params']["rights"] = rights
230                 #PL specific parameters
231                 node_fields = record['p_params']
232                 
233                 #insert the PL tables first
234                 pointer = shell.AddNode(pl_auth, login_base, node_fields)
235         
236                 #insert into the GENI tables
237                 record['g_params']["pointer"] = pointer
238                 querystr = "UPDATE "+table+" SET hrn = '"+record['g_params']["hrn"]+"'"
239                 if record['g_params'].has_key('rights') and record['g_params']['rights'] != '':
240                     querystr = querystr+" rights = '"+record['g_params']['rights']+"'"
241                 querystr = querystr+" WHERE pointer = "+str(record['g_params']["pointer"])
242                 cnx.query(querystr)
243                 return "Node "+long_hrn+" is successfully added.\n"
244                 
245         except Exception, e:
246             print "Error in 'register():"+str(e)
247             return "Error in register:."+str(e)
248             
249     #record is the record to be updated
250     #record contains the new values of the fields to be changed in a dictionary. 
251     #precondition: the authorization mechanism should already checked the fields intended to be updated
252     #dbinfo is the information showing the relevant tables to act (db and table name), in the subtree this interface manages
253     def update(self, record, dbinfo):
254         cnx = dbinfo[0]
255         table = dbinfo[1] 
256         try:
257             #determine the type and PL pointer of the record
258             existing_res = check_exists_geni(record, dbinfo)
259             if not existing_res:
260                 raise NonexistingRecord("Record "+record['g_params']["hrn"]+" does not exist.\n" )
261             type = existing_res['type']
262             pointer = existing_res['pointer']
263             long_hrn = record['g_params']["hrn"]
264             
265             #PL update
266             if type == "SA" and pointer != -1:
267                 #check if record exists in PL
268                 pl_res = shell.GetSites(pl_auth, [pointer])
269                 if not pl_res:
270                     self.remove(record,dbinfo)
271                     raise NonexistingRecord("Record "+record['g_params']["hrn"]+" does not exist.\n" )
272                 #PL specific parameters
273                 site_fields = record['p_params']
274                 #update the PL tables
275                 shell.UpdateSite(pl_auth, pointer, site_fields)
276             elif type == "MA" and pointer != -1:
277                 #check if record exists in PL
278                 pl_res = shell.GetSites(pl_auth, [pointer])
279                 if not pl_res:
280                     self.remove(record,dbinfo)
281                     raise NonexistingRecord("Record "+record['g_params']["hrn"]+" does not exist.\n" )
282                 #PL specific parameters
283                 site_fields = record['p_params']
284                 #update the PL tables
285                 shell.UpdateSite(pl_auth, pointer, site_fields)
286             elif type == "slice":
287                 #check if record exists in PL
288                 pl_res = shell.GetSlices(pl_auth, [pointer])
289                 if not pl_res:
290                     self.remove(record,dbinfo)
291                     raise NonexistingRecord("Record "+record['g_params']["hrn"]+" does not exist.\n" )
292                 #PL specific parameters
293                 slice_fields = record['p_params']
294                 #update the PL tables
295                 shell.UpdateSlice(pl_auth, pointer, slice_fields)
296                 #process the new users added to the slice
297                 for user in record['g_params']['userlist']:
298                     usr_dbinfo = determine_dbinfo(get_authority(user), self.tree)
299                     if usr_dbinfo:
300                         rec = {'g_params':{'hrn':user}, 'p_params':{}}
301                         user_pointer = self.lookup(rec, usr_dbinfo)['geni']['pointer']
302                         querystr = "INSERT INTO slice_person VALUES("+pointer+", "+user_pointer+");"
303                         cnx.query(querystr)
304             elif type == "user":
305                 #check if record exists in PL
306                 pl_res = shell.GetPersons(pl_auth, [pointer])
307                 if not pl_res:
308                     self.remove(record,dbinfo)
309                     raise NonexistingRecord("Record "+record['g_params']["hrn"]+" does not exist.\n" )
310                 #PL specific parameters
311                 user_fields = record['p_params']
312                 #update the PL tables
313                 shell.UpdatePerson(pl_auth, pointer, user_fields)
314             elif type == "node":
315                 #check if record exists in PL
316                 pl_res = shell.GetNodes(pl_auth, [pointer])
317                 if not pl_res:
318                     self.remove(record,dbinfo)
319                     raise NonexistingRecord("Record "+record['g_params']["hrn"]+" does not exist.\n" )
320                 #PL specific parameters
321                 node_fields = record['p_params']
322                 #update the PL tables
323                 shell.UpdateNode(pl_auth, pointer, node_fields)
324                 
325             #geni update
326             #all fields to be updated resides in the dictionary passed by the client, we just change the hrn field
327             record['g_params']["hrn"] = get_leaf(record['g_params']["hrn"])
328             #update the GENI table
329             querystr = generate_querystr('UPDATE', table, record['g_params'])
330             cnx.query(querystr)
331             return "The record '"+long_hrn+"' is successfully updated.\n"
332         except Exception, e:
333             print "Error in 'update():'"+str(e)
334             return "Error in update:"+str(e)
335
336     #record shows the hrn to be deleted
337     #dbinfo is the information showing the relevant tables to act (db and table name), in the subtree this interface manages
338     #we enforce that the deletions of SA/MA are only at leaf
339     def remove(self, record, dbinfo):
340         cnx = dbinfo[0]
341         table = dbinfo[1] 
342         try:
343             #determine the type and PL pointer of the record
344             long_hrn = record['g_params']["hrn"]
345             hrn_suffix = get_leaf(record['g_params']["hrn"])
346             existing_res = check_exists_geni(record, dbinfo)
347             if not existing_res:
348                 raise NonexistingRecord("Record "+record['g_params']["hrn"]+" does not exist.\n" )
349             type = existing_res['type']
350             pointer = existing_res['pointer']
351             
352             #delete from the PL tables
353             if type == "SA" or type == "MA":
354                 #do not allow removal if site is not leaf
355                 tree = None
356                 if type == 'SA':
357                     tree = self.sr_tree
358                 else:
359                     tree = self.cr_tree
360                 leaf = tree.is_leaf(long_hrn)
361                 if leaf == None:
362                     return "Error in remove.\n"
363                 elif leaf == False:
364                     return "Site removal should be at the leaves.\n"
365             
366                 #update the interface tree
367                 tree.tree_remove(long_hrn)
368                 
369                 if type == 'SA':
370                     self.save_state('sr')
371                 else:
372                     self.save_state('cr')
373                 
374                 #if the site still exists in the tree, do not remove from pl, else remove
375                 if not site_to_auth(pointer):
376                     try:
377                         shell.DeleteSite(pl_auth, pointer)
378                     except:
379                         1==1  #the site may not be deleted because ttl of it expired, so should continue
380             elif type == 'user':
381                 shell.DeletePerson(pl_auth, pointer)
382             elif type == "slice":
383                 shell.DeleteSlice(pl_auth, pointer)
384             elif type == "node":
385                 shell.DeleteNode(pl_auth, pointer)
386                 
387             #delete from the GENI table
388             querystr = generate_querystr('DELETE', table, record['g_params'])
389             cnx.query(querystr)
390             return "The record '"+long_hrn+"' is successfully removed.\n"
391         except Exception, e:
392             print "Error in 'delete()'"+str(e)
393             return "Error in delete:"+str(e)
394             
395     #record shows the hrn to be searched
396     #dbinfo is the information showing the relevant tables to act (db and table name), in the subtree this interface manages
397     def lookup(self, record, dbinfo):
398         cnx = dbinfo[0]
399         table = dbinfo[1] 
400         try:
401             #lookup in GENI tables
402             existing_res = check_exists_geni(record, dbinfo)
403             if not existing_res:
404                 raise NonexistingRecord("Record "+record['g_params']["hrn"]+" does not exist.\n" )
405             type = existing_res['type']
406             pointer = existing_res['pointer']
407             #lookup in the PL tables
408             pl_res = None
409             if type == "SA" and pointer != -1:
410                 pl_res = shell.GetSites(pl_auth, [pointer])
411                 if not pl_res:
412                     self.remove(record,dbinfo)
413                     raise NonexistingRecord("Record "+record['g_params']["hrn"]+" does not exist.\n" )
414                 pl_res = pl_res[0]
415             elif type == "MA" and pointer != -1:
416                 pl_res = shell.GetSites(pl_auth, [pointer])
417                 if not pl_res:
418                     self.remove(record,dbinfo)
419                     raise NonexistingRecord("Record "+record['g_params']["hrn"]+" does not exist.\n" )
420                 pl_res = pl_res[0]
421             elif type == "slice":
422                 pl_res = shell.GetSlices(pl_auth, [pointer])
423                 if not pl_res:
424                     self.remove(record,dbinfo)
425                     raise NonexistingRecord("Record "+record['g_params']["hrn"]+" does not exist.\n" )
426                 pl_res = pl_res[0]
427             elif type == "user":
428                 pl_res = shell.GetPersons(pl_auth, [pointer])
429                 if not pl_res:
430                     self.remove(record,dbinfo)
431                     raise NonexistingRecord("Record "+record['g_params']["hrn"]+" does not exist.\n" )
432                 pl_res = pl_res[0]
433             elif type == "node":
434                 pl_res = shell.GetNodes(pl_auth, [pointer])
435                 if not pl_res:
436                     self.remove(record,dbinfo)
437                     raise NonexistingRecord("Record "+record['g_params']["hrn"]+" does not exist.\n" )
438                 pl_res = pl_res[0]
439             return str({'pl':pl_res, 'geni':existing_res})
440         except:
441             return None
442             
443
444     def list(self, record, dbinfo):
445         x=1
446         
447     #grants the credentials existing in database to the caller
448     #peer parameter shows the caller information
449     #record keeps the parameter: credential name
450     #dbinfo is the information showing the relevant tables to act (db and table name), in the subtree this interface manages
451     #keyinfo is the id, id_key, and accounting data for the authority
452     #peerinfo is [peer_hrn, peer_certficate]
453     def getCredential(self, record, dbinfo, keyinfo, peerinfo):
454         cnx = dbinfo[0]
455         table = dbinfo[1] 
456         try:
457             cred_pem = None
458             if record['g_params']['cred_name'].split(':')[0] == 'registry':
459                 #lookup in GENI tables
460                 geni_res = cnx.query("SELECT * FROM "+table+" WHERE hrn = '"+get_leaf(peerinfo[0])+"' ").dictresult()
461                 if geni_res:
462                     geni_res = geni_res[0]
463                 else:
464                     raise NonexistingRecord("Record "+peerinfo[0]+" does not exist.\n" )
465                 type = geni_res['type']
466                 pointer = geni_res['pointer']
467                 rights = geni_res['rights']
468                 #lookup in the PL tables
469                 pl_res = None
470                 if type == "SA" and pointer != -1:
471                     pl_res = shell.GetSites(pl_auth, [pointer])
472                     if not pl_res:
473                         self.remove(record,dbinfo)
474                         raise NonexistingRecord("Record "+peerinfo[0]+" does not exist.\n" )
475                 elif type == "MA" and pointer != -1:
476                     pl_res = shell.GetSites(pl_auth, [pointer])
477                     if not pl_res:
478                         self.remove(record,dbinfo)
479                         raise NonexistingRecord("Record "+peerinfo[0]+" does not exist.\n" )
480                 elif type == "user":
481                     pl_res = shell.GetPersons(pl_auth, [pointer])
482                     if not pl_res:
483                         self.remove(record,dbinfo)
484                         raise NonexistingRecord("Record "+peerinfo[0]+" does not exist.\n" )
485                     pl_res = shell.GetPersons(pl_auth, [pointer])[0]
486                     if rights == '' or rights == None:
487                         if 'admin' in pl_res['roles']:
488                             rights = '(0-0)(1-0)(2-0)(3-0)(4-0)(5-0)(6-0)(7-0)(8-0)(9-0)'+ \
489                                         '(0-1)(1-1)(2-1)(3-1)(4-1)(5-1)(6-1)(7-1)(8-1)(9-1)'
490                             rights = rights + '#0:reg:slc:'+ROOT_AUTH + '#1:reg:comp:'+ROOT_AUTH
491                         elif 'pi' in pl_res['roles']:
492                             rights = '(0-0)(1-0)(2-0)(3-0)(4-0)(5-0)(6-0)(7-0)(8-0)(9-0)'+\
493                                         '(0-1)(1-1)(2-1)(3-1)(4-1)(5-1)(6-1)(7-1)(8-1)(9-1)'
494                             rights = rights + '#0:reg:slc:'+obtain_authority(peerinfo[0]) + '#1:reg:comp:'+obtain_authority(peerinfo[0])
495                         elif 'user' in pl_res['roles']:
496                             rights = '(2-0)(4-0)(6-0)(7-0)(8-0)(9-0)'
497                             rights = rights + '#0:reg:slc:'+obtain_authority(peerinfo[0])
498                 elif type == "node":
499                     pl_res = shell.GetNodes(pl_auth, [pointer])
500                     if not pl_res:
501                         self.remove(record,dbinfo)
502                         raise NonexistingRecord("Record "+peerinfo[0]+" does not exist.\n" )
503                 #authcert, authkey, pubkey, cname, rights, time
504                 cname = 'Registry credentials'
505                 openssl_cert = peerinfo[1]
506                 cred_pem = create_cred(keyinfo[0], keyinfo[1], openssl_cert.get_pubkey(), cname, rights)
507             else:
508                 cred_name = record['g_params']['cred_name'].split(':')
509                 if cred_name[0] == 'slice':
510                     slc_rec = {'g_params':{'hrn':cred_name[1]}, 'p_params':{}}
511                     slc_result = self.lookup(slc_rec, dbinfo)
512                     has_slc = False
513                     deleted = slc_result['p_params']['is_deleted']
514                     expires= time.strptime(slc_result['p_params']['expires'], PL_DATETIME_FORMAT)
515                     expires = datetime.timedelta(seconds=calendar.timegm(expires))
516                     if slc_result and  deleted == 'f':
517 ##                        if peerinfo[0] in slc_result['geni']['userlist']:
518 ##                            has_slc = True
519 ##                        else:
520                         usr_dbinfo = determine_dbinfo(get_authority(peerinfo[0]), self.tree)
521                         if usr_dbinfo:
522                             rec = {'g_params':{'hrn':peerinfo[0]}, 'p_params':{}}
523                             user_pointer = self.lookup(rec, usr_dbinfo)['geni']['pointer']
524                             querystr = "SELECT * FROM person_slice WHERE person_id = "+user_pointer+" AND slice_id = "+slc_result['geni']['pointer']
525                             usr_slc_res = cnx.query(querystr).dictresult()
526                             if usr_slc_res:
527                                 has_slc = True
528                         if has_slc:
529                             rights = ''
530                             if slc_result['geni']['rights'] != '' or slc_result['geni']['rights'] != None:
531                                 rights = slc_result['geni']['rights']
532                             else:
533                                 rights = '(10-0)(11-0)(12-0)(13-0)(14-0)(15-0)(16-0)(17-0)(18-0)(20-0)(21-0)(22-0)(23-0)'
534                                 rights = rights + '#0:comp:planetlab.*'
535                             #authcert, authkey, pubkey, cname, rights, time
536                             cname = slc_result['geni']['hrn']
537                             timenow = datetime.timedelta(seconds=time.time())
538                             if expires - timenow > CRED_GRANT_TIME:
539                                 openssl_cert = crypto.load_certificate(crypto.FILETYPE_PEM, peerinfo[1])
540                                 cred_pem = create_cred(keyinfo[0], keyinfo[1], openssl_cert.get_pubkey(), cname, rights)
541                 else:
542                     raise NonexistingCredType("Credential "+cred_name[0]+" does not exist.\n" )
543             if cred_pem == None:
544                 return cred_pem
545             else:
546                 return crypto.dump_certificate(crypto.FILETYPE_PEM, cred_pem)+keyinfo[3]
547         except: 
548             return None     
549
550
551     #returns the existing acconting information in database to the caller
552     #peer parameter shows the caller certificate, containing the public key
553     #record keeps the parameter: account_name to ask for
554     #dbinfo is the information showing the relevant tables to act (db and table name), in the subtree this interface manages
555     #keyinfo is the id, id_key, and accounting data for the authority
556     #peer_cert is the ssl certificate of the peer
557     def getAccounting(self, record, dbinfo, keyinfo, peer_cert):
558         cnx = dbinfo[0]
559         table = dbinfo[1] 
560         try:
561             acc = None
562             #check if the record exists
563             rec = {'g_params':{'hrn':record['g_params']['account_name']}, 'p_params':{}}
564             res = eval(self.lookup(rec, dbinfo))
565             if not res:
566                 raise NonexistingRecord("Record "+record['g_params']["account_name"]+" does not exist.\n" )
567             if res['geni']['pubkey'] == peer_cert.get_pubkey().as_pem(cipher=None):
568                 openssl_cert = crypto.load_certificate(crypto.FILETYPE_PEM, peer_cert.as_pem())
569                 uuid = 0
570                 if not res['pl']:
571                     uuid = res['geni']['uuid']
572                 else:
573                     uuid = res['pl']['uuid']
574                 acc = create_acc(keyinfo[0], keyinfo[1], openssl_cert.get_pubkey(), record['g_params']['account_name'], uuid)
575             if acc == None:
576                 return acc
577             else:
578                 return crypto.dump_certificate(crypto.FILETYPE_PEM, acc)+keyinfo[2]
579         except:
580             return None
581         
582     def __init__(self, socket, handler):
583         #initialize trees
584         self.sr_tree_file = SR_FILE
585         self.cr_tree_file = CR_FILE
586         self.sr_tree = None
587         self.cr_tree = None
588         self.construct_hierarchy()
589         set_tree_globals(self.sr_tree, self.cr_tree)
590         #initialize security module
591         self.sec = None
592         self.sec_init()
593         #set function list
594         self.functionList = {"register":self.register, "remove":self.remove, "update":self.update, "lookup":self.lookup, "list":self.list, "getCredential":self.getCredential, "getAccounting":self.getAccounting}
595         SSL.SSLServer.__init__(self, socket, handler, self.sec.ctx)
596     
597     def construct_hierarchy(self):
598         self.sr_tree = InterfaceTree('slice', self.sr_tree_file, (AUTH_HOST, AUTH_PORT)) #slice registry interface tree
599         self.cr_tree = InterfaceTree('component', self.cr_tree_file, (AUTH_HOST, AUTH_PORT)) #component registry interface tree
600     
601     def sec_init(self):
602         key_info = self.sr_tree.my_tree.info.node_data['key_info']
603         id_file = key_info.folder+'/'+key_info.id_file
604         id_key_file = key_info.folder+'/'+key_info.id_key_file
605         acc_file = key_info.folder+'/'+key_info.acc_file
606         cred_file = key_info.folder+'/'+key_info.cred_file
607             
608         self.sec = Sec('server', id_file, id_key_file, acc_file, cred_file) 
609         renew_cert('accounting', key_info.folder, 'slice', self.sr_tree.my_tree.info.name, None, None, (AUTH_HOST, AUTH_PORT), self.sec)
610         renew_cert('credential', key_info.folder, 'slice', self.sr_tree.my_tree.info.name, None, None, (AUTH_HOST, AUTH_PORT), self.sec)
611         
612     #save the state of the interface trees
613     def save_state(self, type='both'):
614         if type == 'sr' or type == 'both' :
615             self.sr_tree.save_tree()
616         if type == 'cr' or type == 'both' :
617             self.cr_tree.save_tree()
618
619 class handle_connection(SocketServer.BaseRequestHandler):
620     def handle(self):
621 ##        pid = os.fork()
622 ##        if pid:
623 ##            # parent process closes connnection and returns
624 ##            self.request.socket.close()
625 ##            return
626 ##        else:
627         try:
628             peer = server.sec.auth_protocol(self.request)
629             if not peer:
630                 return
631             
632             operation_request = msg_to_params(self.request.read())
633             #determine the database information associated with the hrn of the call
634             hrn_of_call = operation_request["g_params"]["hrn"]
635             opname = operation_request["opname"]
636             target_hrn = ''
637             if opname == "register" or opname == "remove" or opname == "update" or opname == "lookup":
638                 target_hrn = obtain_authority(hrn_of_call)
639             elif opname == 'list' or opname == 'getCredential' or opname == 'getAccounting':
640                 target_hrn = hrn_of_call 
641             reg_type = ''
642             if opname == "register" or opname == "remove" or opname == "update" or opname == "lookup" or opname == 'list':
643                 type = operation_request["g_params"]["type"]
644                 if type == 'slice' or type == 'user' or type == 'SA':
645                     reg_type = 'slice'
646                 else:
647                     reg_type = 'component'
648             elif opname == 'getCredential':
649                 if operation_request["g_params"]["cred_name"].split(':')[1] == 'slc':
650                     reg_type = 'slice'
651                 else:
652                     reg_type = 'component'
653             elif opname == 'getAccounting':
654                 reg_type = operation_request["g_params"]["registry"]
655             tree = None
656             if reg_type == 'slice':
657                 tree = server.sr_tree
658             else:
659                 tree = server.cr_tree    
660             dbinfo = determine_dbinfo(target_hrn, tree)
661             keyinfo = None
662             if opname == 'getAccounting':
663                 keyinfo = tree.determine_keyinfo(target_hrn, server, 'accounting')
664             elif opname == 'getCredential':
665                 keyinfo = tree.determine_keyinfo(target_hrn, server, 'credential')
666             if (dbinfo == None):
667                 self.request.write("WRONG INTERFACE")
668                 return
669             # check to see if a matching function has been registered
670             if not server.functionList.has_key(operation_request['opname']): 
671                 self.request.write("NO FUNC")
672                 return
673             #check the authorization of the peer
674             if not server.sec.check_authorization(peer.acc, peer.cred, operation_request):
675                 self.request.write("AUTHORIZATION FAIL")
676                 return
677         
678             #perform the function call
679             op = server.functionList[operation_request["opname"]]
680             params = {'g_params':operation_request["g_params"], 'p_params':operation_request["p_params"]} 
681             result = None
682             if op == server.getAccounting:
683                 result = op(params,dbinfo, keyinfo, peer.cert)
684             elif op == server.getCredential:
685                 peerinfo = [peer.acc.get_hrn(), crypto.load_certificate(crypto.FILETYPE_PEM, peer.cert.as_pem())]
686                 result = op(params,dbinfo, keyinfo, peerinfo)
687             elif op == server.register or op == server.update or op == server.remove:
688                 result = str({'message':op(params,dbinfo)})
689             else:
690                 result = op(params,dbinfo)
691                 if not result: 
692                     self.request.write(str({'message':'Requested record does not exist.\n'}))
693             self.request.write(result)
694             return
695         except Exception, e:
696             print "There is an error handling the request. "+str(e)
697             return
698
699 #child process never executes this function, because it exits in "handle_connection".
700 ##    def finish(self):
701 ##        server.save_state()
702     
703 server = GENIServer((LISTEN_HOST, LISTEN_PORT), handle_connection)
704 def main():
705     server.save_state()
706     server.serve_forever()   
707
708
709 if __name__=="__main__":
710     main()
711