def load_from_pyopenssl_x509(self, x509):
self.cert = x509
- ##
- # Return another instance of the same class.
- # XXX: probably will be deleted, can use cls() function instead
-
- def create_similar(self):
- return Certificate()
-
##
# Load the certificate from a string
# if there are more certs, then create a parent and let the parent load
# itself from the remainder of the string
if len(parts) > 1:
- self.parent = self.create_similar()
+ self.parent = self.__class__()
self.parent.load_from_string(parts[1])
##
return self.parent
##
- # Verify a chain of certificates.
+ # Verification examines a chain of certificates to ensure that each parent
+ # signs the child, and that some certificate in the chain is signed by a
+ # trusted certificate.
#
# Verification is a basic recursion: <pre>
# if this_certificate was signed by trusted_certs:\r
-# config.py
+##
+# Geniwrapper Configuration Info
#
-# geniwrapper configuration info
+# This module holds configuration parameters for geniwrapper. There are two
+# main pieces of information that are used: the database connection and
+# the PLCAPI connection
+##
+
+##
+# Geniwrapper uses a MYSQL database to store records. This database may be
+# co-located with the PLC database, or it may be a separate database. The
+# following parameters define the connection to the database.
#
-# this module holds configuration parameters for geniwrapper. The wrapper
-# needs an account to connect to PLC with and a database to store geni
-# tables
+# Note that Geniwrapper does not access any of the PLC databases directly via
+# a mysql connection; All PLC databases are accessed via PLCAPI.
def get_default_dbinfo():
dbinfo={}
return dbinfo
+##
+# Geniwrapper uses a PLCAPI connection to perform operations on the registry,
+# such as creating and deleting slices. This connection requires an account
+# on the PLC server with full administrator access.
+#
+# The Url parameter controls whether the connection uses PLCAPI directly (i.e.
+# Geniwrapper is located on the same machine as PLC), or uses a XMLRPC connection
+# to the PLC machine. If you wish to use the API directly, then remove the Url
+# field from the dictionary.
+
+def get_pl_auth():
+ pl_auth = {'Username': 'root@198.0.0.132',
+ 'AuthMethod': 'password',\r
+ 'AuthString': 'root',\r
+ "Url": "https://localhost:443/PLCAPI/"\r
+ }\r
+ return pl_auth
##
-#
# Implements Geni Credentials
#
# Credentials are layered on top of certificates, and are essentially a
# certificate that stores a tuple of parameters.
+##
from cert import *
from rights import *
# addition to the checks for ordinary certificates, verification also
# ensures that the delegate bit was set by each parent in the chain. If
# a delegate bit was not set, then an exception is thrown.
+ #
+ # Each credential must be a subset of the rights of the parent.
def verify_chain(self, trusted_certs = None):
# do the normal certificate verification stuff
+++ /dev/null
-import os
-from pg import DB
-from excep import *
-from tree import *
-from util import *
-
-#planetlab authentication structure
-pl_auth = {'Username': 'ssevinc@princeton.edu', # User account
-'AuthMethod': 'password', # Type of auth this is. Can be password, session ...
-'AuthString': 'Ss3928Ee' # the password for this account
-}
-
-def get_plDB_conn():
- dbname = 'plDB'
- address = 'localhost'
- port = 5433
- user = 'postgres'
- password = '111'
- cnx = DB(dbname, address, port=port, user=user, passwd=password)
- return cnx
-
-#copy the pl db info to requester
-def get_plDB_info(dst):
- dst.db_name = 'plDB'
- dst.address = 'localhost'
- dst.port = 5433
- dst.user = 'postgres'
- dst.password = '111'
-
-
-#determines the database info of a given hrn
-#if the hrn does not exist in the tree hierarchy None is returned
-def determine_dbinfo(hrn, tree):
- info = tree.tree_lookup(hrn)
- if info == None:
- return None
- else:
- db_info = info.node_data['db_info']
- cnx = DB(db_info.db_name, db_info.address, port = db_info.port, user = db_info.user, passwd = db_info.password)
- tablename = db_info.table_name
- return [cnx, tablename]
-
-#convert the parameter list to query string suitable for supplying to database queries
-#input: query type, table name and field-value pairs
-def generate_querystr(type, table, dict):
- querystr = ""
- if type == 'INSERT':
- keys = dict.keys()
- str1 = keys[0]
- for i in range(1, len(keys)):
- str1 = str1 + ','+ keys[i]
- str2 = ""
- for i in range(len(keys)-1):
- if isinstance(dict[keys[i]],str):
- str2 = str2 + "'" + dict[keys[i]] + "', "
- else:
- str2 = str2 + str(dict[keys[i]]) + ", "
- if isinstance(dict[keys[len(keys)-1]],str):
- str2 = str2 + "'" + dict[keys[len(keys)-1]] + "'"
- else:
- str2 = str2 + str(dict[keys[len(keys)-1]])
- querystr = "INSERT INTO "+table+ "(" + str1 + ") VALUES(" + str2 + ")"
- elif type == 'UPDATE':
- str1 = ""
- keys = dict.keys()
- for i in range(len(keys)-1):
- if keys[i] != 'hrn':
- if isinstance(dict[keys[i]],str):
- str1 = str1 + keys[i] + " = '" + dict[keys[i]] + "', "
- else:
- str1 = str1 + keys[i] + " = " + dict[keys[i]] + ", "
- if keys[len(keys)-1] != 'hrn':
- if isinstance(dict[keys[len(keys)-1]],str):
- str1 = str1 + keys[len(keys)-1] + " = '" + dict[keys[len(keys)-1]] + "'"
- else:
- str1 = str1 + keys[len(keys)-1] + " = '" + dict[keys[len(keys)-1]]
- querystr = "UPDATE "+table+ " SET " + str1 + " WHERE hrn = '"+get_leaf(dict["hrn"])+"'"
- elif type == 'DELETE':
- querystr = "DELETE FROM "+table+" WHERE hrn = '"+get_leaf(dict["hrn"])+"'"
- return querystr
-
-# geniclient.py
-#
-# geni client
-#
-# implements the client-side of the GENI API.
+##
+# This module implements the client-side of the Geni API. Stubs are provided
+# that convert the supplied parameters to the necessary format and send them
+# via XMLRPC to a Geni Server.
#
# TODO: Investigate ways to combine this with existing PLC API?
+##
import xmlrpclib
from record import *
from geniticket import *
+##
# ServerException, ExceptionUnmarshaller
#
# Used to convert server exception strings back to an exception.
except xmlrpclib.Fault, e:\r
raise ServerException(e.faultString)
+##
# GeniTransport
#
# A transport for XMLRPC that works on top of HTTPS
else:\r
return httplib.HTTPS(host, None, key_file=self.key_file, cert_file=self.cert_file) #**(x509 or {}))\r
\r
- def getparser(self): \r
- unmarshaller = ExceptionUnmarshaller() \r
- parser = xmlrpclib.ExpatParser(unmarshaller) \r
+ def getparser(self):\r
+ unmarshaller = ExceptionUnmarshaller()\r
+ parser = xmlrpclib.ExpatParser(unmarshaller)\r
return parser, unmarshaller\r
\r
-# GeniClient:\r
+##\r
+# The GeniClient class provides stubs for executing Geni operations. A given\r
+# client object connects to one server. To connect to multiple servers, create\r
+# multiple GeniClient objects.\r
#\r
-# Class for performing GeniClient operations.\r
+# The Geni protocol uses an HTTPS connection, and the client's side of the\r
+# connection uses his private key. Generally, this private key must match the\r
+# public key that is containing in the GID that the client is providing for\r
+# those functions that take a GID.\r
\r
class GeniClient():
- # url = url of server
- # key_file = private key file of client
- # cert_file = x.509 cert of client
+ ##
+ # Create a new GeniClient object.
+ #
+ # @param url is the url of the server
+ # @param key_file = private key file of client
+ # @param cert_file = x.509 cert containing the client's public key. This
+ # could be a GID certificate, or any x.509 cert.
+
def __init__(self, url, key_file, cert_file):
self.url = url
self.key_file = key_file
# Registry Interface
# -------------------------------------------------------------------------
+ ##
+ # Create a new GID. For MAs and SAs that are physically located on the
+ # registry, this allows a owner/operator/PI to create a new GID and have it
+ # signed by his respective authority.
+ #
+ # @param cred credential of caller
+ # @param name hrn for new GID
+ # @param uuid unique identifier for new GID
+ # @param pkey_string public-key string (TODO: why is this a string and not a keypair object?)
+ #
+ # @return a GID object
+
def create_gid(self, cred, name, uuid, pkey_string):
gid_str = self.server.create_gid(cred.save_to_string(save_parents=True), name, uuid, pkey_string)
return GID(string=gid_str)
+ ##
+ # Retrieve the GID for an object. This function looks up a record in the
+ # registry and returns the GID of the record if it exists.
+ # TODO: Is this function needed? It's a shortcut for Resolve()
+ #
+ # @param name hrn to look up
+ #
+ # @return a GID object
+
def get_gid(self, name):
gid_str_list = self.server.get_gid(name)
gid_list = []
gid_list.append(GID(string=str))
return gid_list
- # get_self_credential
+ ##
+ # Get_self_credential a degenerate version of get_credential used by a
+ # client to get his initial credential when he doesn't have one. This is
+ # the same as get_credential(..., cred=None,...).
#
- # a degenerate version of get_credential used by a client to get his
- # initial credential when he doesn't have one. The same as calling
- # get_credential(..., cred=None,...)
+ # The registry ensures that the client is the principal that is named by
+ # (type, name) by comparing the public key in the record's GID to the
+ # private key used to encrypt the client-side of the HTTPS connection. Thus
+ # it is impossible for one principal to retrieve another principal's
+ # credential without having the appropriate private key.
+ #
+ # @param type type of object (user | slice | sa | ma | node
+ # @param name human readable name of object
+ #
+ # @return a credential object
def get_self_credential(self, type, name):
cred_str = self.server.get_self_credential(type, name)
return Credential(string = cred_str)
+ ##
+ # Retrieve a credential for an object.
+ #
+ # If cred==None, then the behavior reverts to get_self_credential()
+ #
+ # @param cred credential object specifying rights of the caller
+ # @param type type of object (user | slice | sa | ma | node)
+ # @param name human readable name of object
+ #
+ # @return a credental object
+
def get_credential(self, cred, type, name):
if cred == None:
return self.get_self_credential(type, name)
cred_str = self.server.get_credential(cred.save_to_string(save_parents=True), type, name)
return Credential(string = cred_str)
+ ##
+ # List the records in an authority. The objectGID in the supplied credential
+ # should name the authority that will be listed.
+ #
+ # @param cred credential object specifying rights of the caller
+ #
+ # @return list of record objects
+
def list(self, cred):
result_dict_list = self.server.list(cred.save_to_string(save_parents=True))
result_rec_list = []
result_rec_list.append(GeniRecord(dict=dict))
return result_rec_list
+ ##
+ # Register an object with the registry. In addition to being stored in the
+ # Geni database, the appropriate records will also be created in the
+ # PLC databases.
+ #
+ # The geni_info and/or pl_info fields must in the record must be filled
+ # out correctly depending on the type of record that is being registered.
+ #
+ # TODO: The geni_info member of the record should be parsed and the pl_info
+ # adjusted as necessary (add/remove users from a slice, etc)
+ #
+ # @param cred credential object specifying rights of the caller
+ # @return record to register
+ #
+ # @return GID object for the newly-registered record
+
def register(self, cred, record):
gid_str = self.server.register(cred.save_to_string(save_parents=True), record.as_dict())
return GID(string = gid_str)
+ ##
+ # Remove an object from the registry. If the object represents a PLC object,
+ # then the PLC records will also be removed.
+ #
+ # @param cred credential object specifying rights of the caller
+ # @param record record to register. The only relevant
+ # fields of the record are 'name' and 'type', which are used to lookup
+ # the current copy of the record in the Geni database, to make sure
+ # that the appopriate record is removed.
+
def remove(self, cred, record):
result = self.server.remove(cred.save_to_string(save_parents=True), record.as_dict())
return result
+ ##
+ # Resolve an object in the registry. A given HRN may have multiple records
+ # associated with it, and therefore multiple records may be returned. The
+ # caller should check the type fields of the records to find the one that
+ # he is interested in.
+ #
+ # @param cred credential object specifying rights of the caller
+ # @param name human readable name of object
+
def resolve(self, cred, name):
result_dict_list = self.server.resolve(cred.save_to_string(save_parents=True), name)
result_rec_list = []
result_rec_list.append(GeniRecord(dict=dict))
return result_rec_list
+ ##
+ # Update an object in the registry. Currently, this only updates the
+ # PLC information associated with the record. The Geni fields (name, type,
+ # GID) are fixed.
+ #
+ # The record is expected to have the pl_info field filled in with the data
+ # that should be updated.
+ #
+ # TODO: The geni_info member of the record should be parsed and the pl_info
+ # adjusted as necessary (add/remove users from a slice, etc)
+ #
+ # @param cred credential object specifying rights of the caller
+ # @param record a record object to be updated
+
def update(self, cred, record):
result = self.server.update(cred.save_to_string(save_parents=True), record.as_dict())
return result
# Slice Interface
# ------------------------------------------------------------------------
+ ##
+ # Start a slice.
+ #
+ # @param cred a credential identifying the caller (callerGID) and the slice
+ # (objectGID)
+
def start_slice(self, cred):
result = self.server.start_slice(cred.save_to_string(save_parents=True))
return result
+ ##
+ # Stop a slice.
+ #
+ # @param cred a credential identifying the caller (callerGID) and the slice
+ # (objectGID)
+
def stop_slice(self, cred):
result = self.server.stop_slice(cred.save_to_string(save_parents=True))
return result
+ ##
+ # Reset a slice.
+ #
+ # @param cred a credential identifying the caller (callerGID) and the slice
+ # (objectGID)
+
def reset_slice(self, cred):
result = self.server.reset_slice(cred.save_to_string(save_parents=True))
return result
+ ##
+ # Delete a slice.
+ #
+ # @param cred a credential identifying the caller (callerGID) and the slice
+ # (objectGID)
+
def delete_slice(self, cred):
result = self.server.delete_slice(cred.save_to_string(save_parents=True))
return result
+ ##
+ # List the slices on a component.
+ #
+ # @param cred credential object that authorizes the caller
+ #
+ # @return a list of slice names
+
def list_slices(self, cred):
result = self.server.list_slices(cred.save_to_string(save_parents=True))
return result
+ ##
+ # Retrieve a ticket. This operation is currently implemented on the
+ # registry (see SFA, engineering decisions), and is not implemented on
+ # components.
+ #
+ # The ticket is filled in with information from the PLC database. This
+ # information includes resources, and attributes such as user keys and
+ # initscripts.
+ #
+ # @param cred credential object
+ # @param name name of the slice to retrieve a ticket for
+ # @param rspec resource specification dictionary
+ #
+ # @return a ticket object
+
def get_ticket(self, cred, name, rspec):
ticket_str = self.server.get_ticket(cred.save_to_string(save_parents=True), name, rspec)
ticket = Ticket(string=ticket_str)
return ticket
+ ##
+ # Redeem a ticket. This operation is currently implemented on the
+ # component.
+ #
+ # The ticket is submitted to the node manager, and the slice is instantiated
+ # or updated as appropriate.
+ #
+ # TODO: This operation should return a sliver credential and indicate
+ # whether or not the component will accept only sliver credentials, or
+ # will accept both sliver and slice credentials.
+ #
+ # @param ticket a ticket object containing the ticket
+
def redeem_ticket(self, ticket):
result = self.server.redeem_ticket(ticket.save_to_string(save_parents=True))
return result
-# geniserver.py
-#
-# geniwrapper server
-#
-# implements a general-purpose server layer for geni. This should be usable on
-# the registry, component, or other interfaces.
+##
+# This module implements a general-purpose server layer for geni.
+# The same basic server should be usable on the registry, component, or
+# other interfaces.
#
# TODO: investigate ways to combine this with existing PLC server?
+##
import SimpleXMLRPCServer
import socket, os\r
from OpenSSL import SSL\r
\r
-# verify_callback\r
-#\r
-# verification callback for pyOpenSSL. We do our own checking of keys because\r
+##\r
+# Verification callback for pyOpenSSL. We do our own checking of keys because\r
# we have our own authentication spec. Thus we disable several of the normal\r
# prohibitions that OpenSSL places on certificates\r
\r
return 0\r
\r
-# SecureXMLServer\r
-#\r
-# taken from the web (XXX find reference). Implements an HTTPS xmlrpc server\r
+##\r
+# Taken from the web (XXX find reference). Implements an HTTPS xmlrpc server\r
class SecureXMLRPCServer(BaseHTTPServer.HTTPServer,SimpleXMLRPCServer.SimpleXMLRPCDispatcher):\r
def __init__(self, server_address, HandlerClass, key_file, cert_file, logRequests=True):\r
type, value, tb = sys.exc_info()\r
raise xmlrpclib.Fault(1,''.join(traceback.format_exception(type, value, tb)))\r
\r
-# SecureXMLRpcRequestHandler\r
-#\r
+##\r
# taken from the web (XXX find reference). Implents HTTPS xmlrpc request handler\r
\r
class SecureXMLRpcRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):\r
self.wfile.flush()\r
self.connection.shutdown() # Modified here!\r
-# GeniServer
-#
-# Class for a general purpose geni server.
-#
+##
# Implements an HTTPS XML-RPC server. Generally it is expected that GENI
# functions will take a credential string, which is passed to
# decode_authentication. Decode_authentication() will verify the validity of
# GID supplied in the credential.
class GeniServer():
+
+ ##
+ # Create a new GeniServer object.
+ #
+ # @param ip the ip address to listen on
+ # @param port the port to listen on
+ # @param key_file private key filename of registry
+ # @param cert_file certificate filename containing public key (could be a GID file)
+
def __init__(self, ip, port, key_file, cert_file):
self.key = Keypair(filename = key_file)
self.cert = Certificate(filename = cert_file)
self.trusted_cert_list = None
self.register_functions()
+ ##
+ # Decode the credential string that was submitted by the caller. Several
+ # checks are performed to ensure that the credential is valid, and that the
+ # callerGID included in the credential matches the caller that is
+ # connected to the HTTPS connection.
+
def decode_authentication(self, cred_string, operation):
self.client_cred = Credential(string = cred_string)
self.client_gid = self.client_cred.get_gid_caller()
if self.object_gid:
self.object_gid.verify_chain(self.trusted_cert_list)
- # register_functions override this to add more functions
+ ##
+ # Register functions that will be served by the XMLRPC server. This
+ # function should be overrided by each descendant class.
+
def register_functions(self):
self.server.register_function(self.noop)
+ ##
+ # Sample no-op server function. The no-op function decodes the credential
+ # that was passed to it.
+
def noop(self, cred, anything):
self.decode_authentication(cred)
return anything
+ ##
+ # Execute the server, serving requests forever.
+
def run(self):
self.server.serve_forever()
-# gid.py
-#
-# implements GENI GID
+##
+# Implements GENI GID. GIDs are based on certificates, and the GID class is a
+# descendant of the certificate class.
+##
from cert import *
import uuid
import xmlrpclib
-# GID is a tuplie:
-# (uuid, hrn, public_key)
+##
+# Create a new uuid. Returns the UUID as a string.
def create_uuid():
return str(uuid.uuid4().int)
+##
+# GID is a tuplie:
+# (uuid, hrn, public_key)
+#
+# UUID is a unique identifier and is created by the python uuid module
+# (or the utility function create_uuid() in gid.py).
+#
+# HRN is a human readable name. It is a dotted form similar to a backward domain\r
+# name. For example, planetlab.us.arizona.bakers.\r
+#\r
+# PUBLIC_KEY is the public key of the principal identified by the UUID/HRN.\r
+# It is a Keypair object as defined in the cert.py module.\r
+#\r
+# It is expected that there is a one-to-one pairing between UUIDs and HRN,
+# but it is uncertain how this would be inforced or if it needs to be enforced.
+#
+# These fields are encoded using xmlrpc into the subjectAltName field of the
+# x509 certificate. Note: Call encode() once the fields have been filled in
+# to perform this encoding.
+
+
class GID(Certificate):
uuid = None
hrn = None
+ ##
+ # Create a new GID object
+ #
+ # @param create If true, create the X509 certificate
+ # @param subject If subject!=None, create the X509 cert and set the subject name
+ # @param string If string!=None, load the GID from a string
+ # @param filename If filename!=None, load the GID from a file
+
def __init__(self, create=False, subject=None, string=None, filename=None, uuid=None, hrn=None):
Certificate.__init__(self, create, subject, string, filename)
if uuid:
self.decode()
return self.hrn
+ ##
+ # Encode the GID fields and package them into the subject-alt-name field
+ # of the X509 certificate. This must be called prior to signing the
+ # certificate. It may only be called once per certificate.
+
def encode(self):
dict = {"uuid": self.uuid,
"hrn": self.hrn}
str = xmlrpclib.dumps((dict,))
self.set_data(str)
+ ##
+ # Decode the subject-alt-name field of the X509 certificate into the
+ # fields of the GID. This is automatically called by the various get_*()
+ # functions in this class.
+
def decode(self):
data = self.get_data()
if data:
self.uuid = dict.get("uuid", None)
self.hrn = dict.get("hrn", None)
- def dump(self, indent=0):
- # TODO: implement indent
+ ##
+ # Dump the credential to stdout.
+ #
+ # @param indent specifies a number of spaces to indent the output
+ # @param dump_parents If true, also dump the parents of the GID
+
+ def dump(self, indent=0, dump_parents=False):
print " "*indent, " hrn:", self.get_hrn()
print " "*indent, "uuid:", self.get_uuid()
+ if self.parent and dump_parents:
+ print " "*indent, "parent:"
+ self.parent.dump(indent+4)
+
+ ##
+ # Verify the chain of authenticity of the GID. First perform the checks
+ # of the certificate class (verifying that each parent signs the child,
+ # etc). In addition, GIDs also confirm that the parent's HRN is a prefix
+ # of the child's HRN.
+ #
+ # Verifying these prefixes prevents a rogue authority from signing a GID
+ # for a principal that is not a member of that authority. For example,
+ # planetlab.us.arizona cannot sign a GID for planetlab.us.princeton.foo.
+
+ def verify_chain(self, trusted_certs = None):
+ # do the normal certificate verification stuff
+ Certificate.verify_chain(self, trusted_certs)
+
+ if self.parent:
+ # make sure the parent's hrn is a prefix of the child's hrn
+ if not self.get_hrn().startswith(self.parent.get_hrn()):
+ raise GidParentHrn(self.parent.get_subject())
+
+ return
+
-# hierarchy.py
+##
+# This module implements a hierarchy of authorities and performs a similar
+# function as the "tree" module of the original geniwrapper prototype. An HRN
+# is assumed to be a string of authorities separated by dots. For example,
+# "planetlab.us.arizona.bakers". Each component of the HRN is a different
+# authority, with the last component being a leaf in the tree.
#
-# hierarchy of GENI authorities
-#
-# This correspond's almost identically to the functionality of Soner's
-# "tree" module. Each component of an HRN is stored in a different subdirectory.
-# Inside this subdirectory are:
+# Each authority is stored in a subdirectory on the registry. Inside this
+# subdirectory are several files:
# *.GID - GID file
# *.PKEY - private key file
# *.DBINFO - database info
+##
import os
import report
from config import *
from geniticket import *
+##
+# The AuthInfo class contains the information for an authority. This information
+# includes the GID, private key, and database connection information.
+
class AuthInfo():
hrn = None
gid_object = None
privkey_filename = None
dbinfo_filename = None
+ ##
+ # Initialize and authority object.
+ #
+ # @param hrn the human readable name of the authority
+ # @param gid_filename the filename containing the GID
+ # @param privkey_filename the filename containing the private key
+ # @param dbinfo_filename the filename containing the database info
+
def __init__(self, hrn, gid_filename, privkey_filename, dbinfo_filename):
self.hrn = hrn
self.set_gid_filename(gid_filename)
self.privkey_filename = privkey_filename
self.dbinfo_filename = dbinfo_filename
+ ##
+ # Set the filename of the GID
+ #
+ # @param fn filename of file containing GID
+
def set_gid_filename(self, fn):
self.gid_filename = fn
self.gid_object = None
+ ##
+ # Get the GID in the form of a GID object
+
def get_gid_object(self):
if not self.gid_object:
self.gid_object = GID(filename = self.gid_filename)
return self.gid_object
+ ##
+ # Get the private key in the form of a Keypair object
+
def get_pkey_object(self):
return Keypair(filename = self.privkey_filename)
+ ##
+ # Get the dbinfo in the form of a dictionary
+
def get_dbinfo(self):
f = file(self.dbinfo_filename)
dict = eval(f.read())\r
f.close()\r
return dict\r
\r
+ ##\r
+ # Replace the GID with a new one. The file specified by gid_filename is\r
+ # overwritten with the new GID object\r
+ #\r
+ # @param gid object containing new GID\r
+\r
def update_gid_object(self, gid):\r
gid.save_to_file(self.gid_filename)\r
self.gid_object = gid\r
+\r
+##\r
+# The Hierarchy class is responsible for managing the tree of authorities.\r
+# Each authority is a node in the tree and exists as an AuthInfo object.\r
+#\r
+# The tree is stored on disk in a hierarchical manner than reflects the\r
+# structure of the tree. Each authority is a subdirectory, and each subdirectory\r
+# contains the GID, pkey, and dbinfo files for that authority (as well as\r
+# subdirectories for each sub-authority)\r
class Hierarchy():
+ ##
+ # Create the hierarchy object.
+ #
+ # @param basedir the base directory to store the hierarchy in
+
def __init__(self, basedir="."):
self.basedir = os.path.join(basedir, "authorities")
+ ##
+ # Given a hrn, return the filenames of the GID, private key, and dbinfo
+ # files.
+ #
+ # @param hrn the human readable name of the authority
+
def get_auth_filenames(self, hrn):
leaf = get_leaf(hrn)
parent_hrn = get_authority(hrn)
return (directory, gid_filename, privkey_filename, dbinfo_filename)
+ ##
+ # Check to see if an authority exists. An authority exists if it's disk
+ # files exist.
+ #
+ # @param the human readable name of the authority to check
+
def auth_exists(self, hrn):
(directory, gid_filename, privkey_filename, dbinfo_filename) = \
self.get_auth_filenames(hrn)
os.path.exists(privkey_filename) and \
os.path.exists(dbinfo_filename)
+ ##
+ # Create an authority. A private key for the authority and the associated
+ # GID are created and signed by the parent authority.
+ #
+ # @param hrn the human readable name of the authority to create
+ # @param create_parents if true, also create the parents if they do not exist
+
def create_auth(self, hrn, create_parents=False):
report.trace("Hierarchy: creating authority: " + hrn)
dbinfo_file.write(str(dbinfo))\r
dbinfo_file.close()
+ ##
+ # Return the AuthInfo object for the specified authority. If the authority
+ # does not exist, then an exception is thrown. As a side effect, disk files
+ # and a subdirectory may be created to store the authority.
+ #
+ # @param hrn the human readable name of the authority to create.
+
def get_auth_info(self, hrn):
#report.trace("Hierarchy: getting authority: " + hrn)
return auth_info
+ ##
+ # Create a new GID. The GID will be signed by the authority that is it's
+ # immediate parent in the hierarchy (and recursively, the parents' GID
+ # will be signed by its parent)
+ #
+ # @param hrn the human readable name to store in the GID
+ # @param uuid the unique identifier to store in the GID
+ # @param pkey the public key to store in the GID
+
def create_gid(self, hrn, uuid, pkey):
gid = GID(subject=hrn, uuid=uuid, hrn=hrn)
return gid
+ ##
+ # Refresh a GID. The primary use of this function is to refresh the
+ # the expiration time of the GID. It may also be used to change the HRN,
+ # UUID, or Public key of the GID.
+ #
+ # @param gid the GID to refresh
+ # @param hrn if !=None, change the hrn
+ # @param uuid if !=None, change the uuid
+ # @param pubkey if !=None, change the public key
+
def refresh_gid(self, gid, hrn=None, uuid=None, pubkey=None):
# TODO: compute expiration time of GID, refresh it if necessary
gid_is_expired = False
return gid
+ ##
+ # Retrieve an authority credential for an authority. The authority
+ # credential will contain the authority privilege and will be signed by
+ # the authority's parent.
+ #
+ # @param hrn the human readable name of the authority
+
def get_auth_cred(self, hrn):
auth_info = self.get_auth_info(hrn)
gid = auth_info.get_gid_object()
cred.sign()
return cred
-
- # this looks almost the same as get_auth_cred, but works for tickets
+ ##
+ # Retrieve an authority ticket. An authority ticket is not actually a
+ # redeemable ticket, but only serves the purpose of being included as the
+ # parent of another ticket, in order to provide a chain of authentication
+ # for a ticket.
+ #
+ # This looks almost the same as get_auth_cred, but works for tickets
# XXX does similarity imply there should be more code re-use?
+ #
+ # @param hrn the human readable name of the authority
+
def get_auth_ticket(self, hrn):
auth_info = self.get_auth_info(hrn)
gid = auth_info.get_gid_object()
def get_authority(hrn):
parts = hrn.split(".")\r
- return ".".join(parts[:-1])
+ return ".".join(parts[:-1])\r
def get_auth_type(type):
if (type=="slice") or (type=="user") or (type=="sa"):
parts = hrn.split(".")
return parts[-2] + "_" + parts[-1]
+# assuming hrn is the hrn of an authority, return the plc authority name
def hrn_to_pl_authname(hrn):
parts = hrn.split(".")
return parts[-1]
+# assuming hrn is the hrn of an authority, return the plc login_base
+def hrn_to_pl_login_base(hrn):
+ return hrn_to_pl_authname(hrn)
+
+++ /dev/null
-import sys
-from pg import DB
-from db import *
-from util import *
-
-PL_DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"
-
-#given a login_base or site_id (which are ids of a site in Planetlab), determines the hierarchical name of it in GENI
-def site_to_auth(id_or_loginbase):
- cnx = get_plDB_conn()
- site_id = None
- hrn = None
- loginbase = None
- if isinstance(id_or_loginbase, int):
- site_id = id_or_loginbase
- querystr = "SELECT login_base FROM sites WHERE site_id = "+str(id_or_loginbase)
- res = cnx.query(querystr).dictresult()
- if res:
- loginbase = res[0]['login_base']
- else:
- return None
- else:
- loginbase = id_or_loginbase
- #get site_id
- querystr = "SELECT site_id FROM sites WHERE login_base = '"+loginbase+"'"
- res = cnx.query(querystr).dictresult()
- if res:
- site_id = res[0]['site_id']
- else:
- return None
- #search login_base in trees
- (sr_tree, cr_tree) = get_tree_globals()
- hrn = site_to_auth_rec(loginbase, sr_tree.my_tree)
- if not hrn:
- hrn = site_to_auth_rec(loginbase, cr_tree.my_tree)
- if not hrn:
- return None
- else:
- return (site_id, hrn)
-
-def site_to_auth_rec(loginbase, treenode):
- if treenode.info.login_base and treenode.info.login_base == loginbase:
- return treenode.info.name
- else:
- for child in treenode.children:
- name = site_to_auth_rec(loginbase, child)
- if name:
- return name
- return None
-
-def hrn_to_loginbase(hrn, algorithm=0):
- hrn_arr = hrn.split('.')
- j = len(hrn_arr)-2
- alg_count = algorithm-1
- login_base = hrn_arr[len(hrn_arr)-1]
- while j>=0 and alg_count>=0:
- if alg_count == 0:
- login_base = login_base+hrn_arr[j]
- j = j-1
- alg_count = alg_count-1
- if len(login_base) > 20:
- return login_base[0:20]
- else:
- return login_base
-
-
-#given an email or person_id (which are ids of a person in Planetlab), determined the last portion of hierarchical name of it in GENI
-def person_to_user(email, algorithm = 0):
- hrn_suffix = ''
- if algorithm == 0:
- hrn_suffix = email.split('@')[0].replace('.','-')
- elif algorithm == 1:
- hrn_suffix = email.split('@')[0].replace('.','-')+'-'+email.split('@')[1].split('.')[0]
- elif algorithm == 2:
- hrn_suffix = email.replace('@','-')
- hrn_suffix = hrn_suffix.replace('.','-')
- return hrn_suffix
-
-def plslice_to_slice(slice_name):
- i = 0
- while slice_name[i]!='_':
- i = i+1
- return slice_name[i+1:len(slice_name)]
-
-def plnode_to_node(hostname, algorithm = 0):
- hrn_suffix = ''
- if algorithm == 0:
- hrn_suffix = hostname.split('.')[0]
- elif algorithm == 1:
- hrn_suffix = hostname.split('.')[0]+'-'+hostname.split('.')[1]
- elif algorithm == 2:
- hrn_suffix = hrn_suffix.replace('.','-')
- return hrn_suffix
-
-def check_exists_pl(cnx, pointer, type):
- exists = True
- if type == 'SA' or type == 'MA':
- res = cnx.query("SELECT deleted FROM sites WHERE site_id = "+str(pointer)).dictresult()
- if len(res)==0 or res[0]['deleted'] == 't':
- exists = False
- elif type == 'slice':
- res = cnx.query("SELECT is_deleted FROM slices WHERE slice_id = "+str(pointer)).dictresult()
- if len(res)==0 or res[0]['is_deleted'] == 't':
- exists = False
- elif type == 'user':
- res = cnx.query("SELECT deleted FROM persons WHERE person_id = "+str(pointer)).dictresult()
- if len(res)==0 or res[0]['deleted'] == 't':
- exists = False
- elif type == 'node':
- res = cnx.query("SELECT deleted FROM nodes WHERE node_id = "+str(pointer)).dictresult()
- if len(res)==0 or res[0]['deleted'] == 't':
- exists = False
- return exists
-
-def check_exists_geni(record, dbinfo):
- cnx = dbinfo[0]
- table = dbinfo[1]
- try:
- #lookup in GENI tables
- geni_res = cnx.query("SELECT * FROM "+table+" WHERE hrn = '"+get_leaf(record['g_params']["hrn"])+"' ").dictresult()
- if geni_res:
- return geni_res[0]
- else:
- return None
- except:
- return None
-
-#fill the geni table with the records in PL database
-#login_base: indicates the site in PL
-#tablename: the GENI table name
-#type: 'slice' or 'component' indicating the registry type of the GENI table
-def populate_pl_data(login_base, tablename, type):
- cnx = get_plDB_conn()
- site_id = cnx.query("SELECT site_id FROM sites WHERE login_base='"+login_base+"';").dictresult()[0]['site_id']
-
- if type == 'slice': #slice registry
- #populate user records
- querystr = "SELECT p.person_id, p.email FROM persons as p, person_site as ps WHERE p.person_id = ps.person_id AND ps.site_id = "+str(site_id)
- users = cnx.query(querystr).dictresult()
- for user in users:
- new_hrn = person_to_user(user['email'])
- existing = cnx.query("SELECT * FROM "+tablename+" WHERE hrn = '"+new_hrn+"'; ").dictresult()
- if len(existing) > 0:
- new_hrn = person_to_user(user['email'], 1)
- existing = cnx.query("SELECT * FROM "+tablename+" WHERE hrn = '"+new_hrn+"'; ").dictresult()
- if len(existing) > 0:
- new_hrn = person_to_user(user['email'], 2)
- cnx.query("INSERT INTO "+tablename+"(hrn,type,wrapperurl,pointer) VALUES('"+new_hrn+"','user','local',"+str(user['person_id'])+")")
- #populate slice records
- querystr = "SELECT slice_id, name FROM slices WHERE site_id = "+str(site_id)
- slices = cnx.query(querystr).dictresult()
- for slice in slices:
- slcname = slice['name'].split('_')
- if slcname[len(slcname)-1] != 'deleted':
- new_hrn = plslice_to_slice(slice['name'])
- existing = cnx.query("SELECT * FROM "+tablename+" WHERE hrn = '"+new_hrn+"'; ").dictresult()
- if len(existing) > 0:
- new_hrn = new_hrn+'-'+str(slice['slice_id'])
- cnx.query("INSERT INTO "+tablename+"(hrn,type,wrapperurl,pointer) VALUES('"+new_hrn+"','slice','local',"+str(slice['slice_id'])+")")
-
- if type == 'component': #component registry
- #populate node records
- querystr = "SELECT node_id, hostname FROM nodes WHERE site_id = "+str(site_id)
- nodes = cnx.query(querystr).dictresult()
- for node in nodes:
- new_hrn = plnode_to_node(node['hostname'], 0)
- existing = cnx.query("SELECT * FROM "+tablename+" WHERE hrn = '"+new_hrn+"'; ").dictresult()
- if len(existing) > 0:
- new_hrn = plnode_to_node(node['hostname'], 1)
- existing = cnx.query("SELECT * FROM "+tablename+" WHERE hrn = '"+new_hrn+"'; ").dictresult()
- if len(existing) > 0:
- new_hrn = plnode_to_node(node['hostname'], 2)
- cnx.query("INSERT INTO "+tablename+"(hrn,type,wrapperurl,pointer) VALUES('"+new_hrn+"','node','local',"+str(node['node_id'])+")")
-
from gid import *
##
-# GeniRecord is a tuple (Name, GID, Type, Info)
-# info is comprised of the following sub-fields
+# The GeniRecord class implements a Geni Record. A GeniRecord is a tuple
+# (Name, GID, Type, Info).
+#
+# Name specifies the HRN of the object
+# GID is the GID of the object
+# Type is user | sa | ma | slice | component
+#
+# Info is comprised of the following sub-fields
# pointer = a pointer to the record in the PL database
# pl_info = planetlab-specific info (when talking to client)
# geni_info = geni-specific info (when talking to client)
+#
+# The pointer is interpreted depending on the type of the record. For example,
+# if the type=="user", then pointer is assumed to be a person_id that indexes
+# into the persons table.
+#
+# A given HRN may have more than one record, provided that the records are
+# of different types. For example, planetlab.us.arizona may have both an SA
+# and a MA record, but cannot have two SA records.
class GeniRecord():
+
+ ##
+ # Create a Geni Record
+ #
+ # @param name if !=None, assign the name of the record
+ # @param gid if !=None, assign the gid of the record
+ # @param type one of user | sa | ma | slice | component
+ # @param pointer is a pointer to a PLC record
+ # @param dict if !=None, then fill in this record from the dictionary
+
def __init__(self, name=None, gid=None, type=None, pointer=None, dict=None):
self.dirty = True
self.pl_info = None
if "geni_info" in dict:
self.set_geni_info(dict["geni_info"])
+ ##
+ # Set the name of the record
+ #
+ # @param name is a string containing the HRN
+
def set_name(self, name):
self.name = name
self.dirty = True
+ ##
+ # Set the GID of the record
+ #
+ # @param gid is a GID object or the string representation of a GID object
+
def set_gid(self, gid):
if isinstance(gid, str):
self.gid = gid
self.gid = gid.save_to_string(save_parents=True)
self.dirty = True
+ ##
+ # Set the type of the record
+ #
+ # @param type is a string: user | sa | ma | slice | component
+
def set_type(self, type):
self.type = type
self.dirty = True
+ ##
+ # Set the pointer of the record
+ #
+ # @param pointer is an integer containing the ID of a PLC record
+
def set_pointer(self, pointer):
self.pointer = pointer
self.dirty = True
+ ##
+ # Set the PLC info of the record
+ #
+ # @param pl_info is a dictionary containing planetlab info
+
def set_pl_info(self, pl_info):
self.pl_info = pl_info
self.dirty = True
+ ##
+ # Set the geni info the record
+ #
+ # @param geni_info is a dictionary containing geni info
+
def set_geni_info(self, geni_info):
self.geni_info = geni_info
self.dirty = True
+ ##
+ # Return the pl_info of the record, or an empty dictionary if none exists
+
def get_pl_info(self):
if self.pl_info:
return self.pl_info
else:
return {}
+ ##
+ # Return the geni_info of the record, or an empty dictionary if none exists
+
def get_geni_info(self):
if self.geni_info:
return self.geni_info
else:
return {}
+ ##
+ # Return the name (HRN) of the record
+
def get_name(self):
return self.name
+ ##
+ # Return the type of the record
+
def get_type(self):
return self.type
+ ##
+ # Return the pointer of the record. The pointer is an integer that may be
+ # used to look up the record in the PLC database. The evaluation of pointer
+ # depends on the type of the record
+
def get_pointer(self):
return self.pointer
- # TODO: not the best name for the function, because we have things called gidObjects in the Cred
+ ##
+ # Return the GID of the record, in the form of a GID object
+ # TODO: not the best name for the function, because we have things called
+ # gidObjects in the Cred
+
def get_gid_object(self):
return GID(string=self.gid)
+ ##
+ # Return a key that uniquely identifies this record among all records in
+ # Geni. This key is used to uniquely identify the record in the Geni
+ # database.
+
def get_key(self):
return self.name + "#" + self.type
+ ##
+ # Returns a list of field names in this record. pl_info, geni_info are not
+ # included because they are not part of the record that is stored in the
+ # database, but are rather computed values from other entities
+
def get_field_names(self):
return ["name", "gid", "type", "pointer"]
+ ##
+ # Given a field name ("name", "gid", ...) return the value of that field.
+ #
+ # @param name is the name of field to be returned
+
def get_field_value_string(self, fieldname):
if fieldname == "key":
val = self.get_key()
else:
return str(val)
+ ##
+ # Given a list of field names, return a list of values for those fields.
+ #
+ # @param fieldnames is a list of field names
+
def get_field_value_strings(self, fieldnames):
strs = []
for fieldname in fieldnames:
strs.append(self.get_field_value_string(fieldname))
return strs
+ ##
+ # Return the record in the form of a dictionary
+
def as_dict(self):
dict = {}
names = self.get_field_names()
return dict
+ ##
+ # Dump the record to stdout
+ #
+ # @param dump_parents if true, then the parents of the GID will be dumped
+
def dump(self, dump_parents=False):
print "RECORD", self.name
print " hrn:", self.name
-# rights.py
+##
+# This Module implements rights and lists of rights for the Geni wrapper. Rights
+# are implemented by two classes:
#
-# support for privileges according to GENI specification
-
-# privilege_table:
+# Right - represents a single right
+#
+# RightList - represents a list of rights
#
-# a list of priviliges and what operations are allowed per privilege
+# A right may allow several different operations. For example, the "info" right
+# allows "listslices", "listcomponentresources", etc.
+##
+
+##
+# privilege_table is a list of priviliges and what operations are allowed
+# per privilege.
privilege_table = {"authority": ["*"],
"refresh": ["remove", "update"],
"info": ["listslices", "listcomponentresources", "getsliceresources"],
"ma": ["*"]}
-# a "Right" is a single privilege.
+##
+# The Right class represents a single privilege.
class Right:
+ ##
+ # Create a new right.
+ #
+ # @param kind is a string naming the right. For example "control"
+
def __init__(self, kind):
self.kind = kind
+ ##
+ # Test to see if this right object is allowed to perform an operation.
+ # Returns True if the operation is allowed, False otherwise.
+ #
+ # @param op_name is a string naming the operation. For example "listslices".
+
def can_perform(self, op_name):
allowed_ops = privilege_table.get(self.kind.lower(), None)
if not allowed_ops:
return (op_name.lower() in allowed_ops)
+ ##
+ # Test to see if this right is a superset of a child right. A right is a
+ # superset if every operating that is allowed by the child is also allowed
+ # by this object.
+ #
+ # @param child is a Right object describing the child right
+
def is_superset(self, child):
my_allowed_ops = privilege_table.get(self.kind.lower(), None)
child_allowed_ops = privilege_table.get(child.kind.lower(), None)
return True
-# a "RightList" is a list of privileges
+##
+# A RightList object represents a list of privileges.
class RightList:
+ ##
+ # Create a new rightlist object, containing no rights.
+ #
+ # @param string if string!=None, load the rightlist from the string
+
def __init__(self, string=None):
self.rights = []
if string:
self.load_from_string(string)
+ ##
+ # Add a right to this list
+ #
+ # @param right is either a Right object or a string describing the right
+
def add(self, right):
if isinstance(right, str):
right = Right(kind = right)
self.rights.append(right)
+ ##
+ # Load the rightlist object from a string
+
def load_from_string(self, string):
self.rights = []
for part in parts:
self.rights.append(Right(part))
+ ##
+ # Save the rightlist object to a string. It is saved in the format of a
+ # comma-separated list.
+
def save_to_string(self):
right_names = []
for right in self.rights:
return ",".join(right_names)
+ ##
+ # Check to see if some right in this list allows an operation. This is
+ # done by evaluating the can_perform function of each operation in the
+ # list.
+ #
+ # @param op_name is an operation to check, for example "listslices"
+
def can_perform(self, op_name):
for right in self.rights:
if right.can_perform(op_name):
return True
return False
+ ##
+ # Check to see if all of the rights in this rightlist are a superset
+ # of all the rights in a child rightlist. A rightlist is a superset
+ # if there is no operation in the child rightlist that cannot be
+ # performed in the parent rightlist.
+ #
+ # @param child is a rightlist object describing the child
+
def is_superset(self, child):
for child_right in child.rights:
allowed = False
+++ /dev/null
-#
-# certgen.py
-#
-# Copyright (C) Martin Sjogren and AB Strakt 2001, All rights reserved
-#
-# $Id: certgen.py,v 1.2 2004/07/22 12:01:25 martin Exp $
-#
-"""
-Certificate generation and validation module.
-"""
-
-from OpenSSL import crypto
-import time, calendar, datetime
-
-TYPE_RSA = crypto.TYPE_RSA
-TYPE_DSA = crypto.TYPE_DSA
-
-def createKeyPair(type, bits):
- """
- Create a public/private key pair.
-
- Arguments: type - Key type, must be one of TYPE_RSA and TYPE_DSA
- bits - Number of bits to use in the key
- Returns: The public/private key pair in a PKey object
- """
- pkey = crypto.PKey()
- pkey.generate_key(type, bits)
- return pkey
-
-def createCertRequest(pkey, name, digest="md5"):
- """
- Create a certificate request.
-
- Arguments: pkey - The key to associate with the request
- digest - Digestion method to use for signing, default is md5
- **name - The name of the subject of the request, possible
- arguments are:
- C - Country name
- ST - State or province name
- L - Locality name
- O - Organization name
- OU - Organizational unit name
- CN - Common name
- emailAddress - E-mail address
- Returns: The certificate request in an X509Req object
- """
- req = crypto.X509Req()
- subj = req.get_subject()
- for (key,value) in name.items():
- setattr(subj, key, value)
- req.set_pubkey(pkey)
- req.sign(pkey, digest)
- return req
-
-def createCertificate(req, (issuerCert, issuerKey), serial, (notBefore, notAfter), extensions=[], digest="md5"):
- """
- Generate a certificate given a certificate request.
-
- Arguments: req - Certificate reqeust to use
- issuerCert - The certificate of the issuer
- issuerKey - The private key of the issuer
- serial - Serial number for the certificate
- notBefore - Timestamp (relative to now) when the certificate
- starts being valid
- notAfter - Timestamp (relative to now) when the certificate
- stops being valid
- digest - Digest method to use for signing, default is md5
- Returns: The signed certificate in an X509 object
- """
- cert = crypto.X509()
- cert.set_serial_number(serial)
- cert.gmtime_adj_notBefore(notBefore)
- cert.gmtime_adj_notAfter(notAfter)
- cert.set_issuer(issuerCert.get_subject())
- cert.set_subject(req.get_subject())
- cert.set_pubkey(req.get_pubkey())
- if extensions:
- extList = []
- for name, critical, value in extensions:
- ext = crypto.X509Extension (name, critical, value)
- extList.append(ext)
- cert.add_extensions(extList)
- cert.sign(issuerKey, digest)
- return cert
-
-
-#checks if a certificate is valid in terms of validity periods
-def check_valid(usercert):
- """
- Method that ensures the issuer cert has
- valid, not_before and not_after fields
- """
- valid = True
- before_time = usercert.get_not_before()
- after_time = usercert.get_not_after()
- before_tuple = time.strptime(str(before_time), "%b %d %H:%M:%S %Y %Z")
- after_tuple = time.strptime(str(after_time), "%b %d %H:%M:%S %Y %Z")
- starts = datetime.timedelta(seconds=calendar.timegm(before_tuple))
- expires = datetime.timedelta(seconds=calendar.timegm(after_tuple))
- now = datetime.timedelta(seconds=time.time())
- time_delta = expires - now
-
- #cert has expired
- if time_delta.days < 0:
- valid = False
- #cert is not yet valid
- time_delta = now - starts
- if time_delta.days < 0:
- valid = False
-
- return valid
+++ /dev/null
-#!/usr/bin/env python
-
-"""
-Certificate generation module.
-"""
-
-from OpenSSL import crypto
-from os import chmod, remove
-from os.path import join
-
-from myap.tools import execute_cmd
-from myap.config import config
-
-TYPE_RSA = crypto.TYPE_RSA
-TYPE_DSA = crypto.TYPE_DSA
-
-YEAR = 60*60*24*365
-
-X509Attr = ( 'C', 'ST', 'L', 'O', 'OU', 'CN', 'emailAddress' )
-X509WinAttr = { 'C' : 'C',
- 'ST' : 'S',
- 'L' : 'L',
- 'O' : 'O',
- 'OU' : 'OU',
- 'CN' : 'CN',
- 'emailAddress' : 'E' }
-
-def createKeyPair(type, bits):
- """
- Create a public/private key pair.
-
- Arguments: type - Key type, must be one of TYPE_RSA and TYPE_DSA
- bits - Number of bits to use in the key
-
- Returns: The public/private key pair in a PKey object
- """
-
- pkey = crypto.PKey()
- pkey.generate_key(type, bits)
-
- return pkey
-
-def createCertRequest(pkey, subject, digest='md5'):
- """
- Create a certificate request.
-
- Arguments: pkey - The key to associate with the request
- subject - A dictionary with the subject of the request, possible
- key,value pairs are:
- C - Country name
- ST - State or province name
- L - Locality name
- O - Organization name
- OU - Organizational unit name
- CN - Common name
- emailAddress - E-mail address
- digest - Digestion method to use for signing, default is md5
-
- Returns: The certificate request in an X509Req object
- """
-
- req = crypto.X509Req()
- subj = req.get_subject()
-
- # Storing attributes in the correct order
- for attr in X509Attr:
- if subject.has_key(attr):
- setattr(subj, attr, subject[attr])
-
- req.set_pubkey(pkey)
- req.sign(pkey, digest)
-
- return req
-
-def createCertificate(req, (issuerKey, issuerCert), serial, (notBefore, notAfter), extensions=[], digest='md5'):
- """
- Generate a certificate given a certificate request.
-
- Arguments: req - Certificate reqeust to use
- issuerCert - The certificate of the issuer
- issuerKey - The private key of the issuer
- serial - Serial number for the certificate
- notBefore - Timestamp (relative to now) when the certificate
- starts being valid
- notAfter - Timestamp (relative to now) when the certificate
- stops being valid
- digest - Digest method to use for signing, default is md5
- isca - The certificate is a CA
-
- Returns: The signed certificate in an X509 object
- """
-
- cert = crypto.X509()
- cert.set_version(2)
-
- if extensions:
- X509Extensions = []
- for name, critical, value in extensions:
- X509Extensions.append(crypto.X509Extension(name, critical, value))
-
- cert.add_extensions(X509Extensions)
-
- cert.set_serial_number(serial)
- cert.gmtime_adj_notBefore(notBefore)
- cert.gmtime_adj_notAfter(notAfter)
- cert.set_issuer(issuerCert.get_subject())
- cert.set_subject(req.get_subject())
- cert.set_pubkey(req.get_pubkey())
- cert.sign(issuerKey, digest)
-
- return cert
-
-def createSignedCertificate(subject, serial, extensions=[], type=TYPE_RSA, bits=2048, cipher='DES-EDE3-CBC', passphrase='', years=5, capkey='', cacert='', capassphrase=''):
- """
- Generate a Signed Certificate.
-
- Arguments: subject - The subject of the request, see createCertRequest()
- type - (optional) Key type, see createKeyPair()
- bits - (optional) Number of bits to use in the key
- cipher - (optional) if encrypted PEM format, the cipher to use, see dump_privatekey()
- passphrase - (optional) if encrypted PEM format, the passphrase to use, see dump_privatekey()
- years - (optional) Number of years to use for validity, see X509()
- capkey - (optional) CA's private key (PEM formated string)
- cacert - (optional) CA's certificate (PEM formated string)
- capassphrase - (optional) if CA private key is in encrypted PEM format,
- the passphrase to use, see load_privatekey()
-
- Returns: Two PEM formated strings containing private key and signed certificate
- """
-
- pkey = createKeyPair(type, bits)
- req = createCertRequest(pkey, subject)
-
- if capkey and cacert:
- # Certificate will be signed by an Autority
- capkey = crypto.load_privatekey(crypto.FILETYPE_PEM, capkey, capassphrase)
- cacert = crypto.load_certificate(crypto.FILETYPE_PEM, cacert)
- else:
- # Self signed certificate
- capkey = pkey
- cacert = req
-
- cert = createCertificate(req, (capkey, cacert), serial, (0, years*YEAR), extensions=extensions)
-
- if passphrase:
- pkey = crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey, cipher, passphrase)
- else:
- pkey = crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey)
-
- cert = crypto.dump_certificate(crypto.FILETYPE_PEM, cert)
-
- return (pkey, cert)
-
-def getSubject(cert, for_win=False):
-
- cert = crypto.load_certificate(crypto.FILETYPE_PEM, cert)
- subj = cert.get_subject()
-
- subject = ''
- for attr in X509Attr:
- value = getattr(subj, attr)
- if value:
- if for_win:
- # Converting Attr to Windows Attr
- attr = X509WinAttr[attr]
- subject += '%s=%s, ' % (attr, value)
-
- subject = subject[:-2]
-
- return subject
-
-def convertPemToDer(pkey, cert, cipher='DES-EDE3-CBC', passphrase=''):
- """
- Convert two PEM formated strings (pkey, cert) onto two DER formated strings.
-
- Arguments: pkey - private key (PEM formated string)
- cert - certificate (PEM formated string)
- cipher - (optional) if encrypted PEM format, the cipher to use, see dump_privatekey()
- passphrase - (optional) if encrypted PEM format, the passphrase to use, see dump_privatekey()
-
- Returns: Two DER formated strings containing private key and signed certificate
- """
-
- pkey = crypto.load_privatekey(crypto.FILETYPE_PEM, pkey, passphrase)
- cert = crypto.load_certificate(crypto.FILETYPE_PEM, cert)
-
- if passphrase:
- pkey = crypto.dump_privatekey(crypto.FILETYPE_ASN1, pkey, cipher, passphrase)
- else:
- pkey = crypto.dump_privatekey(crypto.FILETYPE_ASN1, pkey)
-
- cert = crypto.dump_certificate(crypto.FILETYPE_ASN1, cert)
-
- return (pkey, cert)
-
-def convertDerToPem(pkey, cert, cipher='DES-EDE3-CBC', passphrase=''):
- """
- Convert two DER formated strings (pkey, cert) onto two PEM formated strings.
-
- Arguments: pkey - private key (DER formated string)
- cert - certificate (DER formated string)
- cipher - (optional) if encrypted DER format, the cipher to use, see dump_privatekey()
- passphrase - (optional) if encrypted DER format, the passphrase to use, see dump_privatekey()
-
- Returns: Two PEM formated strings containing private key and signed certificate
- """
-
- pkey = crypto.load_privatekey(crypto.FILETYPE_ASN1, pkey, passphrase)
- cert = crypto.load_certificate(crypto.FILETYPE_ASN1, cert)
-
- if passphrase:
- pkey = crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey, cipher, passphrase)
- else:
- pkey = crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey)
-
- cert = crypto.dump_certificate(crypto.FILETYPE_PEM, cert)
-
- return (pkey, cert)
-
-def dump_pkcs12(pkey, cert, cacert='', passphrase=''):
- """
-
- """
-
- # Storing all the params to a temp file
- temp_file = '/tmp/pkcs12'
-
- pkcs12 = pkey + cert + cacert
-
- f = open(temp_file, 'w')
- f.write(pkcs12)
- f.close()
- chmod(temp_file, 0600)
-
- # Create pkcs12 file with openssl
- cmd = 'openssl pkcs12 -export -in %s -passout pass:"%s"' % (temp_file, passphrase)
-
- exitcode, pkcs12 = execute_cmd(cmd)
- remove(temp_file)
-
- if exitcode:
- return pkcs12
-
- return None
-
-def newCertificate(db, ip):
-
- serial = db.get_last_serial_cert()
- ca = db.get_certificate(serial=0)
-
- # Creating the certificate for the ip
- serial += 1
- subject = config['SSL_DEFAULT']
- subject['CN'] = ip
- extensions = (('nsCertType', False, 'client'),
- ('keyUsage', False, 'dataEncipherment'),
- ('extendedKeyUsage', False, 'clientAuth,1.3.6.1.4.1.311.10.3.4.1'))
- pkey, cert = createSignedCertificate(subject, serial, extensions=extensions, bits=1024, capkey=ca['private_key'], cacert=ca['certificate'], capassphrase=config['SSL_CA_PASS'])
-
- # Adding it to the database
- db_cert = {}
- db_cert['serial'] = serial
- db_cert['private_key'] = pkey
- db_cert['certificate'] = cert
-
- return db.set_certificate(db_cert)
-
-def getPKCS12(db, reservation_id):
-
- ca = db.get_certificate(serial=0)
- reservation = db.get_reservation(reservation_id=reservation_id)
- certificate = db.get_certificate(certificate_id=reservation['certificate_id'])
-
- pkcs12 = dump_pkcs12(certificate['private_key'], certificate['certificate'], ca['certificate'])
-
- return pkcs12
-
-def revokeCertificate(db, certificate_id):
-
- return True
-
-def init(db):
-
- db.delete_certificates()
-
- # Creating the CA
- serial = 0
- subject = config['SSL_DEFAULT']
- extensions = (('basicConstraints', True, 'CA:true'),
- ('nsCertType', False, 'objCA,sslCA,objsign,client,server'),
- ('keyUsage', False, 'keyCertSign,cRLSign,nonRepudiation,keyEncipherment,dataEncipherment'),
- ('extendedKeyUsage', False, 'clientAuth,serverAuth,1.3.6.1.4.1.311.10.3.4.1')) # 1.3.6.1.4.1.311.10.3.4.1 is for VPN
-
- capkey, cacert = createSignedCertificate(subject, serial, extensions=extensions, passphrase=config['SSL_CA_PASS'])
-
- # Adding it to the database
- db_cert = {}
- db_cert['serial'] = serial
- db_cert['private_key'] = capkey
- db_cert['certificate'] = cacert
- if not db.set_certificate(db_cert):
- return False
-
- # Creating the certificate for the WebServer
- serial += 1
- subject['CN'] = config['SERVER_NAME']
- extensions = (('nsCertType', False, 'server'),
- ('keyUsage', False, 'keyEncipherment'),
- ('extendedKeyUsage', False, 'serverAuth'))
-
- pkey, cert = createSignedCertificate(subject, serial, extensions=extensions, bits=1024, capkey=capkey, cacert=cacert, capassphrase=config['SSL_CA_PASS'])
-
- # Adding it to the database
- db_cert = {}
- db_cert['serial'] = serial
- db_cert['private_key'] = pkey
- db_cert['certificate'] = cert
- if not db.set_certificate(db_cert):
- return False
-
- try:
- f = open(config['MYAP_HTTPD_PKEY'], 'w')
- f.write(pkey)
- f.close()
- chmod(config['MYAP_HTTPD_PKEY'], 0600)
-
- f = open(config['MYAP_HTTPD_CERT'], 'w')
- f.write(cert)
- f.close()
-
- except:
- return False
-
- # Creating the certificate for Racoon
- serial += 1
- subject['CN'] = 'Racoon Server'
- extensions = (('nsCertType', False, 'client,server'),
- ('keyUsage', False, 'keyEncipherment'),
- ('extendedKeyUsage', False, 'clientAuth,serverAuth,1.3.6.1.4.1.311.10.3.4.1'))
-
- pkey, cert = createSignedCertificate(subject, serial, extensions=extensions, bits=1024, capkey=capkey, cacert=cacert, capassphrase=config['SSL_CA_PASS'])
-
- # Adding it to the database
- db_cert = {}
- db_cert['serial'] = serial
- db_cert['private_key'] = pkey
- db_cert['certificate'] = cert
- if not db.set_certificate(db_cert):
- return False
-
- try:
- pkey_file = join(config['SSL_TOP_DIR'], config['RACOON_PKEY'])
- cert_file = join(config['SSL_TOP_DIR'], config['RACOON_CERT'])
-
- f = open(pkey_file, 'w')
- f.write(pkey)
- f.close()
- chmod(pkey_file, 0600)
-
- f = open(cert_file, 'w')
- f.write(cert)
- f.close()
-
- except:
- return False
-
- return True
-
+++ /dev/null
-#certificate generation functions
-
-from M2Crypto import X509
-from M2Crypto import EVP
-
-def createKeyPair(type, bits):
- """
- Create a public/private key pair.
-
- Arguments: type - Key type, must be one of TYPE_RSA and TYPE_DSA
- bits - Number of bits to use in the key
- Returns: The public/private key pair in a PKey object
- """
-
-
-
-
-
-
-
+++ /dev/null
-import sys
-from OpenSSL import crypto
-from M2Crypto import X509
-sys.path.append('../')
-sys.path.append('../..')
-from sec import *
-
-
-
-##osaka2 = X509.load_cert_string(crypto.dump_certificate(crypto.FILETYPE_PEM, osaka_acc))
-##usersoner2 = X509.load_cert_string(crypto.dump_certificate(crypto.FILETYPE_PEM, usersoner_acc))
-##
-##t1 = osaka2.as_text()
-##t2 = usersoner2.as_text()
-##
-##res = usersoner2.verify(osaka2.get_pubkey())
-##
-##print res
-
-#pl_pem = X509.load_cert('usersoner.cert')
-#pkey = pl_pem.get_pubkey().as_pem(cipher=None)
-
-#from pg import DB
-
-#dbname = 'plDB'
-#address = 'localhost'
-#port = 5433
-#user = 'postgres'
-#password = '111'
-#cnx = DB(dbname, address, port=port, user=user, passwd=password)
-#cnx.query("UPDATE planetlab$jp$osaka_sr SET pubkey = '"+pkey+"' WHERE hrn = 'usersoner'")
-
-#print pkey
-
-
-planetlab_cert = crypto.load_certificate(crypto.FILETYPE_PEM, open('planetlab.cert').read())
-planetlab_pkey = crypto.load_privatekey(crypto.FILETYPE_PEM, open('planetlab.pkey').read())
-planetlab_acc = create_acc(planetlab_cert, planetlab_pkey, planetlab_cert.get_pubkey(), 'planetlab', '28698598650165084658569185050284587399', 3)
-ac1 = crypto.dump_certificate(crypto.FILETYPE_PEM, planetlab_acc)
-open('planetlab_acc_file', 'w').write(ac1)
-
-##
-##res = c1_pem2.verify(c3_pem2.get_pubkey())
+++ /dev/null
-import sys
-from OpenSSL import crypto
-sys.path.append('../')
-sys.path.append('../..')
-from sec import *
-
-#id certificates
-
-create_self_cert('planetlab')
-create_self_cert('jp')
-create_self_cert('osaka')
-create_self_cert('usersoner')
-
-planetlab_cert = crypto.load_certificate(crypto.FILETYPE_PEM, open('planetlab.cert').read())
-jp_cert = crypto.load_certificate(crypto.FILETYPE_PEM, open('jp.cert').read())
-osaka_cert = crypto.load_certificate(crypto.FILETYPE_PEM, open('osaka.cert').read())
-usersoner_cert = crypto.load_certificate(crypto.FILETYPE_PEM, open('usersoner.cert').read())
-
-planetlab_pkey = crypto.load_privatekey(crypto.FILETYPE_PEM, open('planetlab.pkey').read())
-jp_pkey = crypto.load_privatekey(crypto.FILETYPE_PEM, open('jp.pkey').read())
-osaka_pkey = crypto.load_privatekey(crypto.FILETYPE_PEM, open('osaka.pkey').read())
-usersoner_pkey = crypto.load_privatekey(crypto.FILETYPE_PEM, open('usersoner.pkey').read())
-
-#accounting certificates
-
-planetlab_acc = create_acc(planetlab_cert, planetlab_pkey, planetlab_cert.get_pubkey(), 'planetlab', '77059b82-e826-11dc-9dc2-001ec2091968')
-jp_acc = create_acc(planetlab_cert, planetlab_pkey, jp_cert.get_pubkey(), 'planetlab.jp', '3fd66a4c-d574-4aa0-9ddd-3904af595bd2')
-osaka_acc = create_acc(jp_cert, jp_pkey, osaka_cert.get_pubkey(), 'planetlab.jp.osaka', '05b3c29b-0dae-4a95-b92b-0e01548f61e0')
-usersoner_acc = create_acc(osaka_cert, osaka_pkey, usersoner_cert.get_pubkey(), 'planetlab.jp.osaka.usersoner', '220828220198687580431599291716859620971')
-
-#credential certificates
-
-planetlab_cred = create_cred(planetlab_cert, planetlab_pkey, planetlab_cert.get_pubkey(), 'Registry credentials', '(0-0)(1-0)(2-0)(3-0)(4-0)(5-0)(6-0)(7-0)(8-0)(9-0)#0:reg:planetlab')
-jp_cred = create_cred(planetlab_cert, planetlab_pkey, jp_cert.get_pubkey(), 'Registry credentials', '(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)#0:reg:planetlab#1:reg:planetlab.jp')
-osaka_cred = create_cred(jp_cert, jp_pkey, osaka_cert.get_pubkey(), 'Registry credentials', '(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)#0:reg:planetlab.jp#1:reg:planetlab.jp.osaka')
-usersoner_cred = create_cred(osaka_cert, osaka_pkey, usersoner_cert.get_pubkey(), 'Registry credentials', '(0-0)(1-0)(2-0)(3-0)(4-0)(5-0)(6-0)(7-0)(8-0)(9-0)#0:reg:planetlab.jp.osaka')
-
-#acc and cred files
-
-ac1 = crypto.dump_certificate(crypto.FILETYPE_PEM, planetlab_acc)
-ac2 = crypto.dump_certificate(crypto.FILETYPE_PEM, jp_acc)
-ac3 = crypto.dump_certificate(crypto.FILETYPE_PEM, osaka_acc)
-ac4 = crypto.dump_certificate(crypto.FILETYPE_PEM, usersoner_acc)
-#open('planetlab_acc_file', 'w').write(ac1)
-#open('jp_acc_file', 'w').write(ac2+ac1)
-open('osaka_acc_file', 'w').write(ac3+ac2+ac1)
-open('usersoner_acc_file', 'w').write(ac4+ac3+ac2+ac1)
-
-cred1 = crypto.dump_certificate(crypto.FILETYPE_PEM, planetlab_cred)
-cred2 = crypto.dump_certificate(crypto.FILETYPE_PEM, jp_cred)
-cred3 = crypto.dump_certificate(crypto.FILETYPE_PEM, osaka_cred)
-cred4 = crypto.dump_certificate(crypto.FILETYPE_PEM, usersoner_cred)
-#open('planetlab_cred_file', 'w').write(cred1)
-#open('jp_cred_file', 'w').write(cred2+cred1)
-open('osaka_cred_file', 'w').write(cred3+cred2+cred1)
-open('usersoner_cred_file', 'w').write(cred4+cred3+cred2+cred1)
-
+++ /dev/null
------BEGIN CERTIFICATE-----
-MIIBiDCB8gIBADANBgkqhkiG9w0BAQQFADANMQswCQYDVQQDEwJqcDAeFw0wODAz
-MDMwMzQ0NTBaFw0xMzAzMDIwMzQ0NTBaMA0xCzAJBgNVBAMTAmpwMIGfMA0GCSqG
-SIb3DQEBAQUAA4GNADCBiQKBgQC5fCqy5k2JzHNLBOBf2Ptw25iyMBNu787yf0S/
-NrI9iesdV7cD2C0Jwrrn2nuur8J8CKR4gb1EKm3U6gSMnPSHM5dZ+XQN4RuGWciu
-nrVQ3RdEPccvVufrzd1sB8OFeT92DPlHT85GZ4WoijH3lupaXBq9IpiQ2sC74WID
-kA28ZwIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAFiJpvDxCK7MdCMaedh8mN6i4FVE
-GKk/nES7cc5MxH3F3nvYuluew0A7l83tYwq98E9yZz593mjQHxyIAGsNFaVALkWx
-ZEmK7afYTnXInTLRRZv00PuhRp+12zQ7gY2fkjYVMpgGdPB/n0NrP9pirBzEmht+
-FIudlteVKYY+VVm2
------END CERTIFICATE-----
+++ /dev/null
------BEGIN RSA PRIVATE KEY-----
-MIICXQIBAAKBgQC5fCqy5k2JzHNLBOBf2Ptw25iyMBNu787yf0S/NrI9iesdV7cD
-2C0Jwrrn2nuur8J8CKR4gb1EKm3U6gSMnPSHM5dZ+XQN4RuGWciunrVQ3RdEPccv
-Vufrzd1sB8OFeT92DPlHT85GZ4WoijH3lupaXBq9IpiQ2sC74WIDkA28ZwIDAQAB
-AoGBALdJMwhE+ynHlcXzs6QCzbPfyyuIxitBXMXTbSNl8QtOVb5RBtANtbOHcRna
-k40ysIPQJnXN/jB1nMJf3M716cpgOeBwECVLkGVpq7zTYsWdeh7lTEOh/aUbDgKZ
-nOnGqogKGaiQ92Fhs7ImyCHyb6e8SdFFHi1BAGGXQ5P0QXHBAkEA6fWvv/5fn7Jy
-2UyKMqO6LxGL08nzIzJNLU36WCTFfuFlXeQpoSZ7QqDCkZUY3zHNo4p5nBSzju4+
-lmczfIWhiwJBAMr1b317SeV8viOpn8rpfB0/IhLZ8EdPwsVsEMpIDcqpJZHCiLBl
-HrEQtu+PJGBN93gznR8rJgEKK3tYQBc99BUCQQDgwpbE66sR0G1lNJLPc1s6PLEI
-Fcru1TQvgeovI6RX8FFhkgAsQLvJlodVNNdgFIhpxG5v87NMbLTT6PEdf4NhAkAE
-QIIWcefJbASbwKj9WkjkX/c5x+EVzWD6O9paMoo/ba3A0P+GGog7E2uRt0D+14NQ
-vFwVVBUWvnzMt7uYAQ9FAkA7XNbDWBeW/7zIt9yrTx+dM+xN2fftV7RxMB1pSSEP
-Ugsm2nyCj6ZuEhHn8PjB9+bNfK/PrGC/qjTDyPH+zvYp
------END RSA PRIVATE KEY-----
+++ /dev/null
------BEGIN CERTIFICATE-----
-MIIBlzCCAQACAQAwDQYJKoZIhvcNAQEEBQAwFDESMBAGA1UEAxMJcGxhbmV0bGFi
-MB4XDTA4MDMyMTIyMDE0MVoXDTEzMDMyMDIyMDE0MVowFDESMBAGA1UEAxMJcGxh
-bmV0bGFiMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4nsgYgX1n8mUs0dPb
-krTFtThw5ULBPr45s7Al0tsaG80I/UpjZG07Q4QnaEfFu/2xWBsAC0S5HopbSS3w
-Ykr+OkQO4DNV0+RwRhGqHamhnjSl7Ar9svHzzgIFujl9vQdqoWzWXzW2eDkbtqb8
-elDnit1bwCC2yrRNoivuAFFSsQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAKWSfdwa
-bMWqViR5/aRR8tD6mQ7jwhKA6glr7vSCWvdKsHhKSZd2NrpCnyP5ew1c4E0XKwU0
-TPLwLDsIMUcy0lSojjAETy7mrIHlqPxCL8WP9Wp7U9No8jVbe1E/i89a/qahhL7v
-fvA5Nb91VeJXaE2hr7bG6so6aG8WIMm90d4A
------END CERTIFICATE-----
+++ /dev/null
------BEGIN RSA PRIVATE KEY-----
-MIICXAIBAAKBgQC4nsgYgX1n8mUs0dPbkrTFtThw5ULBPr45s7Al0tsaG80I/Upj
-ZG07Q4QnaEfFu/2xWBsAC0S5HopbSS3wYkr+OkQO4DNV0+RwRhGqHamhnjSl7Ar9
-svHzzgIFujl9vQdqoWzWXzW2eDkbtqb8elDnit1bwCC2yrRNoivuAFFSsQIDAQAB
-AoGAR6gxZ/mSkC7wACZtAXN+wKInBwKlF1ZgBQtuWi/uJMMXoN6W6d8H2pHJEHaU
-LPZbcGMPD8RP5z4oW2ga8YtlKYD2tKqulXm07yMIpbLs4+3FgFHzN4H5lCb511Zq
-EdVKtXAxp2X+H0wGB4g26UqvSp8/Kp4x2u63X48+5aRjODECQQDZ5WGrJFDLmHWt
-6NcvYYiJJ0jGwve8iRsVBOqT8wiAQ+7QFfnlnrwLxOsm2qCZokFrFmx0YnYmZ27y
-uaAI9TydAkEA2Oe7op+wcN5Xpa19yGy4/mnsGfGbxkWucBWmMTiJbq0NtSYdbAnL
-4DUnG+0SdtpA5OoXBnUQs2nXcWq/YCDQJQJAZCEIdMDHcAerbDNnTxqex4gJ5WyK
-s1S94TbVJQ+1hFuzTmQK5f2/pBjlhoFI89CgBznStNjaOmOllFzAsd0f8QJBAJ80
-X/W6bkA6Am0ZzVQZ8SLTzjcwrpy2MpYUXdqM29r/bCtFIZ1WB222tdD6jm3sPmuH
-IoVb0XlOu5KEvpkpHH0CQHnzGFbx4gj5fGanVgyMjd6FY0vJO15vpsrmAeYDbVfT
-4FeaALZcN5oA6xaD5xxL2+tvw7j/oy9UtMQRrcKYmcM=
------END RSA PRIVATE KEY-----
+++ /dev/null
------BEGIN CERTIFICATE-----
-MIIBlzCCAQACAQAwDQYJKoZIhvcNAQEEBQAwFDESMBAGA1UEAxMJdXNlcnNvbmVy
-MB4XDTA4MDMwMzAzNDQ1MVoXDTEzMDMwMjAzNDQ1MVowFDESMBAGA1UEAxMJdXNl
-cnNvbmVyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC9ax+M8gWEr1PsgPJM
-KP8nHWRJBnevXxMLmpFfz8kzC2CY1PQ3VzGClyp6v3ryv/Tp9W+otE7M9SCMx+aG
-ibTRMJFnYag1VJyIywX72fDuMTlvS3SMz1NPsda7PzqhmyRiE8c5wlgQWSNktker
-/wmEN2qfIC+ufBVsslsehkpkQQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAGT7dqbw
-wHNi33eT33qneUdbfYWH+fDM2sTIdiQXYhcBEyXXWwHNlW46sq/aCol8uSNhEjbK
-rDzAfGsIqNAeBHBeuG5FgEqt0mOtglyjqQ82v6keayIOYIUJ3f7Vw7YorPyGs8x7
-SxYqbGOvuPHnItV507Orj/fQOXW1ZerYFhrk
------END CERTIFICATE-----
+++ /dev/null
-import os, sys
-from OpenSSL import crypto
-from M2Crypto import X509
-from M2Crypto import SSL
-sys.path.append('../')
-from certgen import *
-from util import *
-from db import *
-from tree import *
-
-CRED_GRANT_TIME = 3600000 #in seconds
-ACC_GRANT_TIME = 10000000
-TOP_LEVEL_CERTS_DIR = "trusted_certs"
-MAX_CERT_SIZE = 1024
-MAX_CERT_CHAIN = 9
-
-creds= ["","","","","","","","","","","","","","","","","","","","","","","","",""]
-creds[0] = "register"
-creds[1] = "remove"
-creds[2] = "remove_self"
-creds[3] = "update"
-creds[4] = "update_self"
-creds[5] = "lookup"
-creds[6] = "lookup_self"
-creds[7] = "list"
-creds[8] = "getCredential"
-creds[9] = "getAccounting"
-creds[10] = "getTicket" # = embed privilege in the docs
-creds[11] = "splitTicket"
-creds[12] = "redeemTicket"
-creds[13] = "stop"
-creds[14] = "start"
-creds[15] = "delete"
-creds[16] = "listSlices"
-creds[17] = "getStatus"
-creds[18] = "getSlice"
-creds[19] = "refresh"
-creds[20] = "delegate"
-creds[21] = "instantiate"
-creds[22] = "bind"
-creds[23] = "control"
-
-class PeerInfo :
- def __init__(self):
- self.cert = None
- self.acc = Accounting() #accounting information
- self.cred = Credential() #credential information
-
-#info_certs looks like: [{'hrn':None, 'uuid':0}]
-class Accounting:
- def __init__(self):
- self.info_certs = []
- self.cert_chain = []
- def get_hrn(self):
- return self.info_certs[0]['hrn']
- def get_uuid(self):
- return self.info_certs[0]['uuid']
-
-#info_certs looks like: [{'operation_set':None, 'on_interfaces':None}]
-#operation_set looks like: [0:['register','update','update_self',..], 1:['getTicket', 'splitTicket',..],..]
-#on_interfaces looks like: [{'lbl':0, 'name':'planetlab.jp.jaist', 'type':'registry'},..{}]
-class Credential:
- def __init__(self):
- self.info_certs = [] #list of operations and list of sites on which operations can be performed
- self.cert_chain = []
- def get_cred(self):
- return self.info_certs[0]
-
-#type: 'accounting' or 'credential'
-#folder: directory of that the certificate should reside
-#reg_type: 'slice' or 'component'
-#hrn: name of the object to get certificates for
-#server: the server instance to do operations calls with in the internal tree
-#internal_tree: tree for internal cert renewals
-#auth_addr: authority to ask for certificates
-#sec: security module to perform auth. protocol with the remote peer
-#return 0: no renewal done, 1: renewal done, None: error
-def renew_cert(type, folder, reg_type, hrn, server, internal_tree, auth_addr, sec):
- #check if necessary to renew
- if type == 'accounting':
- fname = folder+'/acc_file'
- else:
- fname = folder+'/cred_file'
- if os.path.exists(fname) and is_valid_chain(fname):
- return 0
- else:
- parent_hrn = obtain_authority(hrn)
- hrn_suffix = get_leaf(hrn)
- id_file = folder+'/'+hrn_suffix+'.cert'
- #check the id file
- if not os.path.exists(folder) or not os.path.exists(id_file):
- print 'Id file for '+hrn+' does not exist.\n'
- return None
- #decide if remote call
- remote = True
- if internal_tree:
- dbinfo = determine_dbinfo(parent_hrn, internal_tree)
- if dbinfo:
- remote = False
- if not remote:
- if type == 'accounting':
- #obtain the accounting from parent, write to file
- g = {"hrn":""}
- g["hrn"] = parent_hrn
- g['registry'] = reg_type
- g["account_name"] = hrn
- p = {}
- record = {'g_params':g, 'p_params':p}
- dbinfo = determine_dbinfo(parent_hrn, internal_tree)
- parentkeyinfo = internal_tree.determine_keyinfo(parent_hrn, server, type)
- open(fname, 'w').write(server.getAccounting(record, dbinfo, parentkeyinfo, X509.load_cert(id_file)))
- else:
- #obtain the credential from parent, write to file
- g = {"hrn":""}
- g["hrn"] = parent_hrn
- if reg_type == 'slice':
- g['cred_name'] = 'registry:slc'
- else:
- g['cred_name'] = 'registry:comp'
- p = {}
- record = {'g_params':g, 'p_params':p}
- dbinfo = determine_dbinfo(parent_hrn, internal_tree)
- id = crypto.load_certificate(crypto.FILETYPE_PEM, open(id_file).read())
- peerinfo = [hrn, id]
- parentkeyinfo = internal_tree.determine_keyinfo(parent_hrn, server, type)
- open(fname, 'w').write(server.getCredential(record, dbinfo, parentkeyinfo, peerinfo))
- else: #if not local call
- if obtain_authority(hrn) == '': #we are at the root
- id_key_file = folder+'/'+hrn_suffix+'.pkey'
- id_cert = crypto.load_certificate(crypto.FILETYPE_PEM, open(id_file).read())
- id_pkey = crypto.load_privatekey(crypto.FILETYPE_PEM, open(id_key_file).read())
- peer_cred_str = open(fname).read()
- c_pem = X509.load_cert_string("-----BEGIN CERTIFICATE-----"+peer_cred_str.split("-----BEGIN CERTIFICATE-----")[1])
- if type == 'accounting':
- cert_uuid = c_pem.get_ext("subjectAltName").get_value().split('http://')[1].split('#')[2].split('uuid:')[1]
- acc = create_acc(id_cert, id_pkey, id_cert.get_pubkey(), hrn, cert_uuid)
- open(fname, 'w').write(crypto.dump_certificate(crypto.FILETYPE_PEM, acc))
- else:
- rights = c_pem.get_ext("subjectAltName").get_value().split('http://')[1].split('credential_set:')[1]
- cred = create_cred(id_cert, id_pkey, id_cert.get_pubkey(), 'Registry credentials', rights)
- open(fname, 'w').write(crypto.dump_certificate(crypto.FILETYPE_PEM, cred))
- else:
- operation = ''
- g = {"hrn":obtain_authority(hrn)}
- if type == 'accounting':
- operation = "getAccounting";
- #geni parameters
- g['registry'] = reg_type
- g["account_name"] = hrn
- else:
- operation = "getCredential"
- #geni parameters
- if reg_type == 'slice':
- g['cred_name'] = 'registry:slc'
- else:
- g['cred_name'] = 'registry:comp'
- p = {}
- message = {'opname':operation, 'g_params':g, 'p_params':p}
- #connect to authority
- server = SSL.Connection(sec.ctx)
- server.connect(auth_addr)
- peer = sec.auth_protocol(server)
- #do the query and get the result
- server.write(str(message))
- result = server.read(MAX_CERT_SIZE*MAX_CERT_CHAIN)
- open(fname, 'w').write(result)
- return 1
-
-#obtains a data structure for credentials out of a given credential string
-#return info_cert: {'operation_set':{'register','remove',..}, 'on_interfaces':{{'lbl':'0', 'type':'registry:slc','name':'planetlab.jp'}, ..}}
-def get_cred_info(credstr):
- info_cert = {'operation_set':{}, 'on_interfaces':{}}
- set = credstr.split('#')[1].split('credential_set:')[1]
- set_arr = set.split(')')
- for item in set_arr[0:len(set_arr)-1]:
- item = item.split('(')[1].split('-')
- if info_cert['operation_set'].has_key(item[1]):
- info_cert['operation_set'][item[1]].append(creds[int(item[0])])
- else:
- info_cert['operation_set'][item[1]] = [creds[int(item[0])]]
- interface_list = []
- arr = credstr.split('#')
- intlist = arr[2:len(arr)]
- for interface in intlist:
- iarr = interface.split(':')
- newint = {'lbl':iarr[0]}
- if iarr[1] == 'reg':
- if iarr[2] == 'slc':
- newint['type'] ='registry:slc'
- else:
- newint['type'] ='registry:comp'
- newint['name'] = iarr[3]
- elif iarr[1] == 'comp':
- newint['type'] ='component'
- newint['name'] = iarr[2]
- interface_list.append(newint)
- info_cert['on_interfaces'] = interface_list
- return info_cert
-
-#given two credential statements, check if the first one can delegate the second one
-#example: "'register' right on 'planetlab.jp' registry interface" is able to delegate a right called "'register' right on 'planetlab.jp.jaist' registry interface"
-def check_delegation(info_cert1, info_cert2):
- passed = False
- for interface in info_cert1['on_interfaces']:
- is_reg = interface['type'] == 'registry:slc' or interface['type'] == 'registry:comp'
- if is_reg and 'register' in info_cert1['operation_set'][interface['lbl']]:
- found = True
- for child_int in info_cert2['on_interfaces']:
- if child_int['type'] == interface['type'] and not check_authority(child_int['name'],interface['name']):
- found = False
- if found:
- passed = True
- break
- return passed
-
- """
-Create a credential certificate given the parameters:
- 'authcert': the authority certificate
- 'authkey': the authority key
- 'pubkey': the public key belonging to the object to which the credential will be granted
- 'cname': the name of the credential being generated. It should be 'registry credentials' or a silce name like 'planetlab.jp.slice1'
- 'rights': - the sequence representing the set of operations/rights on specific interfaces
- ex: (2-0)(4-0)(6-0)(7-0)(8-0)(9-0)(0-0)(1-1)(2-1)(3-1)(4-1)(5-1)(6-1)(7-1)(8-1)(9-1)#0:reg:planetlab.jp#1:reg:planetlab.jp.jaist
- 'time': time in seconds how long the life of credential is
-"""
-def create_cred(authcert, authkey, pubkey, cname, rights, time=CRED_GRANT_TIME):
- #calculate the credset
- if rights == "slice":
- rights = "(10-1)(11-1)(12-1)(13-1)(14-1)(15-1)(16-1)(17-1)(18-1)(23-1)"
- elif rights == "SA":
- rights = "(0-0)(1-0)(2-0)(3-0)(4-0)(5-0)(6-0)(7-0)(8-0)(9-0)(16-1)(17-1)(18-1)(19-1)"
- elif rights == "MA":
- rights = "(0-0)(1-0)(2-0)(3-0)(4-0)(5-0)(6-0)(7-0)(8-0)(9-0)(16-1)(17-1)(18-1)"
- else:
- # check if the rights is in correct format ######################
- rights = rights
- #create the CSR for the credential certificate
- key = createKeyPair(TYPE_RSA, 1024)
- certReq = createCertRequest(key, {"CN" : cname})
- certReq.set_pubkey(pubkey)
- #create the credential certificate, return
- content = "#credential_set:"+rights
- ext = ("subjectAltName", 1, "URI:http://"+content)
- exts = [ext]
- cert = createCertificate(certReq, (authcert, authkey), 0, (0, int(time)), exts)
- return cert
-
-"""
-Create an accountability certificate given the parameters:
- 'authc': the name of the authority certificate file
- 'authk': the name of the authority key file
- 'pubkey': the name of the GID file belonging to the object to which the accountability will be assigned
- 'name': the name of the object, which is the accountability information itself
- 'uuid': the uuid of the object
- 'time': the date and time when the life of accounting information
-"""
-def create_acc(authcert, authkey, pubkey, name, uuid, time=ACC_GRANT_TIME):
- #create the CSR for the credential certificate
- key = createKeyPair(TYPE_RSA, 1024)
- certReq = createCertRequest(key, {"CN" : "GENI Accounting"})
- certReq.set_pubkey(pubkey)
- #create the accountability certificate, write into file
- content = "#hrn:"+name+"#uuid:"+uuid
- ext = ("subjectAltName", 1, "URI:http://"+content)
- exts = [ext]
- cert = createCertificate(certReq, (authcert, authkey), 0, (0, int(time)), exts)
- return cert
-
-"""
-Create self signed certificate and private key.
-"""
-def create_self_cert(name):
- key = createKeyPair(TYPE_RSA, 1024)
- certReq = createCertRequest(key, {"CN":name})
- cert = createCertificate(certReq, (certReq, key), 0, (0, 60*60*24*365*5)) # five years
- open(name+'.pkey', 'w').write(crypto.dump_privatekey(crypto.FILETYPE_PEM, key))
- open(name+'.cert', 'w').write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert))
-
-def verify_callback(preverify_ok, ctx):
- return 1
-
-class Sec:
- def __init__(self, mode, id_file, id_key_file, acc_file, cred_file):
- self.top_level_certs = []
- self.mode = mode
- file_list = os.listdir(TOP_LEVEL_CERTS_DIR)
- for auth_file in file_list:
- # XXX SMBAKER: fix .svn directory
- if os.path.isfile(os.path.join(TOP_LEVEL_CERTS_DIR, auth_file)):
- self.top_level_certs.append(X509.load_cert(TOP_LEVEL_CERTS_DIR+"/"+auth_file))
-
- self.id_file = id_file
- self.id_key_file = id_key_file
- self.my_cert = crypto.load_certificate(crypto.FILETYPE_PEM, open(id_file).read())
- self.my_key = crypto.load_privatekey(crypto.FILETYPE_PEM, open(id_key_file).read())
- self.acc_file = acc_file
- self.cred_file = cred_file
- #ssl parameters
- self.ctx = SSL.Context()
- self.ctx.load_cert(self.id_file,self.id_key_file)
- self.ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, depth=9, callback=verify_callback)
-
- # - exchange the accounting chains, store peer's accounting in peer.acc
- # - check TTLs in certificates
- # - check validity of the chain, but do not check top level's trustedness
- #return 1: means there is a structural error in the chain
- #return 2: one of the TTLs in the chain not valid
- #return 3: public keys do not form a valid chain
- def exchange_accounting(self, conn, peer):
- peer_acc_str=None
- if self.mode == 'server':
- #receive acc chain
- peer_acc_str = conn.read(MAX_CERT_SIZE*MAX_CERT_CHAIN)
- #send the acc chain
- acc_str = open(self.acc_file).read() #read the certificate chain from file
- conn.write(acc_str)
- elif self.mode == 'client':
- #send the acc chain
- acc_str = open(self.acc_file).read() #read the certificate chain from file
- conn.write(acc_str)
- #receive acc chain
- peer_acc_str = conn.read(MAX_CERT_SIZE*MAX_CERT_CHAIN)
-
- #construct peer_acc data structure
- peer_acc = peer.acc
- if peer_acc_str[0:27] != "-----BEGIN CERTIFICATE-----":
- peer_acc.info_certs = "anonymous"
- else:
- try:
- #divide the received chain into certificates
- arr = peer_acc_str.split("-----BEGIN CERTIFICATE-----")
- arr = arr[1:len(arr)]
- for i in range(len(arr)):
- arr[i] = "-----BEGIN CERTIFICATE-----"+arr[i]
- for c_str in arr:
- c_pem = X509.load_cert_string(c_str)
- hrn = c_pem.get_ext("subjectAltName").get_value().split('http://')[1].split('#')[1].split('hrn:')[1]
- uuid = c_pem.get_ext("subjectAltName").get_value().split('http://')[1].split('#')[2].split('uuid:')[1]
- peer_acc.info_certs.append({'hrn':hrn, 'uuid':uuid})
- peer_acc.cert_chain.append(c_pem)
- except:
- print "No valid chain received.\n"
- return 1
- #if structure is ok, go on with other checks
- ttl_ok = True
- chain_ok = True
- #check ttl for the first certificate in the chain:
- if not (check_valid(peer_acc.cert_chain[0])):
- ttl_ok = False
- prevCert = None
- curCert = None
- for i in range(1, len(peer_acc.cert_chain)):
- prevCert = peer_acc.cert_chain[i-1]
- curCert = peer_acc.cert_chain[i]
- #check ttl
- if not check_valid(curCert):
- ttl_ok = False
- #chain validity checks
- if not prevCert.verify(curCert.get_pubkey()) :
- chain_ok = False
- if ttl_ok == False:
- return 2
- elif chain_ok == False:
- return 3
- return 0
-
- # - check the pubkey of first certificate if it matches the peer public key
- # - check the name hierarchy
- # - check the top level authority's trustedness
- # return 0: accounting verified
- # return 1: pubkey does not match peer pubkey
- # return 2: name hierarch does not imply hrn
- # return 3: top level authority is unknown
- # return 4: unidentified error
- def verify_accounting(self, peer):
- pubkey_ok = True
- hierarchy_ok = True
- trusted_auth = True
-
- if peer.acc.info_certs == 'anonymous':
- return 0
- try:
- #check the pubkey of the peer
- if peer.acc.cert_chain[0].get_pubkey().as_pem(cipher=None) != peer.cert.get_pubkey().as_pem(cipher=None):
- pubkey_ok = False
- else:
- #check the name hierarchy
- for i in range(len(peer.acc.info_certs)-1):
- if check_authority(peer.acc.info_certs[i]['hrn'], peer.acc.info_certs[i+1]['hrn']) == False:
- hierarchy_ok = False
-
- #check if the certificate ends with a sign of a trusted top level authority
- if hierarchy_ok:
- found = False
- last_cert_pubkey_pem = peer.acc.cert_chain[len(peer.acc.cert_chain)-1].get_pubkey().as_pem(cipher=None)
- for cert in self.top_level_certs:
- auth_pubkey_pem = cert.get_pubkey().as_pem(cipher=None)
- if last_cert_pubkey_pem == auth_pubkey_pem:
- found = True
- break
- if not found:
- trusted_auth = False
-
- if pubkey_ok == False:
- return 1
- elif hierarchy_ok == False:
- return 2
- elif trusted_auth == False:
- return 3
- return 0
- except Exception, e:
- print "Exception in verify_accounting:", e
- return 4
-
- # - exchange the credential chains, store peer's credential in peer.cred
- # - check TTLs in certificates
- # - check validity of the chain, but do not check top level's trustedness
- #return 1: means there is a structural error in the chain
- #return 2: one of the TTLs in the chain not valid
- #return 3: public keys do not form a valid chain
- def exchange_credential(self, conn, peer):
- peer_cred_str = None
- if self.mode == 'server':
- #receive cred chain
- peer_cred_str = conn.read(MAX_CERT_SIZE*MAX_CERT_CHAIN)
- #send the cred chain
- cred_str = open(self.cred_file).read() #read the certificate chain from file
- conn.write(cred_str)
- elif self.mode == 'client':
- #send the cred chain
- cred_str = open(self.cred_file).read() #read the certificate chain from file
- conn.write(cred_str)
- #receive cred chain
- peer_cred_str = conn.read(MAX_CERT_SIZE*MAX_CERT_CHAIN)
-
- #construct peer_cred data structure
- peer_cred = peer.cred
- if peer_cred_str[0:27] != "-----BEGIN CERTIFICATE-----":
- peer_cred.info_certs = "no_credential"
- else:
- try:
- #divide the received chain into certificates
- arr = peer_cred_str.split("-----BEGIN CERTIFICATE-----")
- arr = arr[1:len(arr)]
- for i in range(len(arr)):
- arr[i] = "-----BEGIN CERTIFICATE-----"+arr[i]
- for c_str in arr:
- c_pem = X509.load_cert_string(c_str)
- credstr = c_pem.get_ext("subjectAltName").get_value().split('http://')[1]
- peer_cred.info_certs.append(get_cred_info(credstr))
- peer_cred.cert_chain.append(c_pem)
- except Exception, e:
- print "Exception in exchange_credential:", e
- print "No valid chain received.\n"
- return 1
- #if structure is ok, go on with other checks
- ttl_ok = True
- chain_ok = True
- #check ttl for the first certificate in the chain:
- if not (check_valid(peer_cred.cert_chain[0])):
- ttl_ok = False
- prevCert = None
- curCert = None
- for i in range(1, len(peer_cred.cert_chain)):
- prevCert = peer_cred.cert_chain[i-1]
- curCert = peer_cred.cert_chain[i]
- #check ttl
- if not check_valid(curCert):
- ttl_ok = False
- #chain validity check
- if not prevCert.verify(curCert.get_pubkey()) :
- chain_ok = False
- if ttl_ok == False:
- return 2
- elif chain_ok == False:
- return 3
- return 0
-
- # - check the pubkey of first certificate if it matches the peer public key
- # - check the delegation hierarchy: the delegated rights must be granted by an authority of the entity
- # - check the top level authority's trustedness
- # return 0: credential verified
- # return 1: pubkey does not match peer pubkey
- # return 2: delegation hierarchy is invalid
- # return 3: top level authority is unknown
- # return 4: unidentified error
- def verify_credential(self, peer):
- pubkey_ok = True
- hierarchy_ok = True
- trusted_auth = True
-
- if peer.cred.info_certs == 'no_credential':
- return 0
- try:
- #check the pubkey of the peer
- if peer.cred.cert_chain[0].get_pubkey().as_pem(cipher=None) != peer.cert.get_pubkey().as_pem(cipher=None):
- pubkey_ok = False
- else:
- #check the delegation hierarchy
- for i in range(len(peer.cred.info_certs)-1):
- if not check_delegation(peer.cred.info_certs[i+1], peer.cred.info_certs[i]) :
- hierarchy_ok = False
-
- #check if the certificate ends with a sign of a trusted top level authority
- if hierarchy_ok:
- found = False
- last_cert_pubkey_pem = peer.cred.cert_chain[len(peer.cred.cert_chain)-1].get_pubkey().as_pem(cipher=None)
- for cert in self.top_level_certs:
- auth_pubkey_pem = cert.get_pubkey().as_pem(cipher=None)
- if last_cert_pubkey_pem == auth_pubkey_pem:
- found = True
- break
- if not found:
- trusted_auth = False
-
- if pubkey_ok == False:
- return 1
- elif hierarchy_ok == False:
- return 2
- elif trusted_auth == False:
- return 3
- return 0
- except:
- return 4
-
- def check_authorization(self, acc, cred, op_request):
- allow = False
- allow_self = False #admission for ops on only the caller itself
- try:
- opname = op_request['opname']
- #anonymously callable functions are allowed always
- if opname == 'getCredential' or opname == 'getAccounting':
- allow = True
- else:
- g_params = op_request['g_params']
- p_params = op_request['p_params']
- target_hrn = g_params['hrn']
- reg_type = ''
- rec_type = g_params['type']
- #determine which registry the call is on (slice or component)
- if rec_type == 'user' or rec_type == 'slice' or rec_type == 'SA':
- reg_type = 'slc'
- else:
- reg_type = 'comp'
- operation_set = cred.get_cred()['operation_set']
- on_interfaces = cred.get_cred()['on_interfaces']
- is_self_op = False
- if opname == "update" or opname == "remove" or opname == "lookup":
- is_self_op = True
- #check callable operations within the credential
- for interface in on_interfaces:
- if interface['type'] == 'registry:'+reg_type and check_authority(target_hrn, interface['name']) and operation_set.has_key(interface['lbl']):
- if opname in operation_set[interface['lbl']]:
- allow = True
- break
- elif is_self_op and opname + '_self' in operation_set[interface['lbl']] and acc.get_hrn() == target_hrn:
- allow_self = True
- #if operation is allowed in name, perform additional checks for parameters
- if allow or allow_self:
- if opname == 'update':
- if 'ttl' in g_params or 'uuid' in g_params or 'pointer' in g_params or (not allow and 'rights' in g_params):
- allow = False
- allow_self = False
- #return result
- if allow or allow_self:
- return True
- else:
- return False
- except Exception, e:
- print "exception in check_authorization:", e
- return False
-
- def auth_protocol(self, conn):
- if not conn.verify_ok():
- v = conn.get_verify_result()
- print "peer verification failed\n"
-
- peer = PeerInfo() #keep the peer data who is currently logged in
- #set the gid field
- peer_pem = conn.get_peer_cert()
- peer.cert = peer_pem
- #set the acc field and check it
- result1 = result2 = -1
- result1 = self.exchange_accounting(conn, peer)
- peer_decision = None
- if self.mode == 'server':
- peer_decision = conn.read()
- if result1 == 1:
- conn.write("ACC CHAIN_STRUCTURE_ERROR")
- elif result1 == 2:
- conn.write("ACC TTL_EXPIRED")
- elif result1 == 3:
- conn.write("ACC CHAIN_VERIFY_ERROR")
- else: #result = 0
- result2 = self.verify_accounting(peer)
- if result2 == 1:
- conn.write("ACC SSL_PUBKEY_MISMATCH")
- elif result2 == 2:
- conn.write("ACC HRN_HIERARCHY_MISMATCH")
- elif result2 == 3:
- conn.write("ACC UNKNOWN_AUTHORITY")
- elif result2 == 4:
- conn.write("ACC UN-IDENTIFIED_ERROR")
- else:
- conn.write("ACC OK")
- if self.mode == 'client':
- peer_decision = conn.read()
- if (result1 != 0) or (result2 != 0) or peer_decision != "ACC OK" :
- #close the connection and exit
- conn.close()
- return None
-
- #set the credential field and check it
- result1 = result2 = -1
- result1 = self.exchange_credential(conn,peer)
- peer_decision = None
- if self.mode == 'server':
- peer_decision = conn.read()
- if result1 == 1:
- conn.write("CRED CHAIN_STRUCTURE_ERROR")
- elif result1 == 2:
- conn.write("CRED TTL_EXPIRED")
- elif result1 == 3:
- conn.write("CRED CHAIN_VERIFY_ERROR")
- else: #result1 = 0
- result2 = self.verify_credential(peer)
- if result2 == 1:
- conn.write("CRED SSL_PUBKEY_MISMATCH")
- elif result2 == 2:
- conn.write("CRED INVALID_DELEGATION")
- elif result2 == 3:
- conn.write("CRED UNKNOWN_AUTHORITY")
- elif result2 == 4:
- conn.write("CRED UN-IDENTIFIED_ERROR")
- else:
- conn.write("CRED OK")
- if self.mode == 'client':
- peer_decision = conn.read()
- if (result1 != 0) or (result2 != 0) or peer_decision != "CRED OK" :
- #close the connection and exit
- conn.close()
- return None
- return peer
-
-def is_valid_chain(chain_file):
- chain_str = open(chain_file).read()
- if chain_str[0:27] != "-----BEGIN CERTIFICATE-----":
- return False
- try:
- #divide the received chain into certificates
- arr = chain_str.split("-----BEGIN CERTIFICATE-----")
- arr = arr[1:len(arr)]
- for i in range(len(arr)):
- arr[i] = "-----BEGIN CERTIFICATE-----"+arr[i]
- arr2 = []
- for c_str in arr:
- c_pem = X509.load_cert_string(c_str)
- if not check_valid(c_pem):
- return False
- return True
- except:
- return False
-