<s> import os <EOL> import json <EOL> import logging <EOL> import Configuration <EOL> import Exceptions <EOL> import Package <EOL> log = logging . getLogger ( '<STR_LIT>' ) <EOL> SYSTEM_MANIFEST_FILE = "<STR_LIT>" <EOL> SEQUENCE_KEY = "<STR_LIT>" <EOL> PACKAGES_KEY = "<STR_LIT>" <EOL> SIGNATURE_KEY = "<STR_LIT>" <EOL> NOTES_KEY = "<STR_LIT>" <EOL> TRAIN_KEY = "<STR_LIT>" <EOL> VERSION_KEY = "<STR_LIT>" <EOL> TIMESTAMP_KEY = "<STR_LIT>" <EOL> SCHEME_KEY = "<STR_LIT>" <EOL> NOTICE_KEY = "<STR_LIT>" <EOL> SWITCH_KEY = "<STR_LIT>" <EOL> REBOOT_KEY = "<STR_LIT>" <EOL> SCHEME_V1 = "<STR_LIT>" <EOL> class ChecksumFailException ( Exception ) : <EOL> pass <EOL> def MakeString ( obj ) : <EOL> retval = json . dumps ( obj , sort_keys = True , indent = <NUM_LIT:4> , separators = ( '<STR_LIT:U+002C>' , '<STR_LIT>' ) , cls = ManifestEncoder ) <EOL> return retval <EOL> def DiffManifests ( m1 , m2 ) : <EOL> """<STR_LIT>""" <EOL> return_diffs = { } <EOL> def DiffPackages ( old_packages , new_packages ) : <EOL> retval = [ ] <EOL> old_list = { } <EOL> for P in old_packages : <EOL> old_list [ P . Name ( ) ] = P <EOL> for P in new_packages : <EOL> if P . Name ( ) in old_list : <EOL> if old_list [ P . Name ( ) ] . Version ( ) != P . Version ( ) : <EOL> retval . append ( ( P , "<STR_LIT>" , old_list [ P . Name ( ) ] ) ) <EOL> old_list . pop ( P . Name ( ) ) <EOL> else : <EOL> retval . append ( ( P , "<STR_LIT>" , None ) ) <EOL> for P in old_list . itervalues ( ) : <EOL> retval . insert ( <NUM_LIT:0> , ( P , "<STR_LIT>" , None ) ) <EOL> return retval <EOL> package_diffs = DiffPackages ( m1 . Packages ( ) , m2 . Packages ( ) ) <EOL> if len ( package_diffs ) > <NUM_LIT:0> : <EOL> return_diffs [ "<STR_LIT>" ] = package_diffs <EOL> reboot_required = False <EOL> for pkg , op , old in package_diffs : <EOL> if op == "<STR_LIT>" : <EOL> continue <EOL> elif op == "<STR_LIT>" : <EOL> if pkg . RequiresReboot ( ) == True : <EOL> reboot_required = True <EOL> elif op == "<STR_LIT>" : <EOL> upd = pkg . Update ( old . Version ( ) ) <EOL> if upd : <EOL> if upd . RequiresReboot ( ) == True : <EOL> reboot_required = True <EOL> else : <EOL> if pkg . RequiresReboot ( ) == True : <EOL> reboot_required = True <EOL> return_diffs [ "<STR_LIT>" ] = reboot_required <EOL> if m1 . Train ( ) != m2 . Train ( ) : <EOL> return_diffs [ "<STR_LIT>" ] = ( m1 . Train ( ) , m2 . Train ( ) ) <EOL> if m1 . Sequence ( ) != m2 . Sequence ( ) : <EOL> return_diffs [ "<STR_LIT>" ] = ( m1 . Sequence ( ) , m2 . Sequence ( ) ) <EOL> return return_diffs <EOL> def CompareManifests ( m1 , m2 ) : <EOL> """<STR_LIT>""" <EOL> diffs = DiffManifests ( m1 , m2 ) <EOL> if "<STR_LIT>" in diffs : <EOL> return diffs [ "<STR_LIT>" ] <EOL> return [ ] <EOL> class ManifestEncoder ( json . JSONEncoder ) : <EOL> def default ( self , obj ) : <EOL> if isinstance ( obj , Package . Package ) : <EOL> return obj . dict ( ) <EOL> elif isinstance ( obj , Manifest ) : <EOL> return obj . dict ( ) <EOL> else : <EOL> return json . JSONEncoder . default ( self , obj ) <EOL> class Manifest ( object ) : <EOL> _config = None <EOL> _root = None <EOL> _notes = None <EOL> _train = None <EOL> _packages = None <EOL> _signature = None <EOL> _version = None <EOL> _scheme = SCHEME_V1 <EOL> _notice = None <EOL> _switch = None <EOL> _timestamp = None <EOL> _requireSignature = False <EOL> def __init__ ( self , configuration = None , require_signature = False ) : <EOL> if configuration is None : <EOL> self . _config = Configuration . Configuration ( ) <EOL> else : <EOL> self . _config = configuration <EOL> self . _requireSignature = require_signature <EOL> self . _dict = { } <EOL> return <EOL> def dict ( self ) : <EOL> return self . _dict <EOL> def String ( self ) : <EOL> retval = MakeString ( self . dict ( ) ) <EOL> return retval <EOL> def LoadFile ( self , file ) : <EOL> self . _dict = json . load ( file ) <EOL> self . Validate ( ) <EOL> return <EOL> def LoadPath ( self , path ) : <EOL> with open ( path , "<STR_LIT:r>" ) as f : <EOL> self . LoadFile ( f ) <EOL> return <EOL> def StoreFile ( self , f ) : <EOL> f . write ( self . String ( ) ) <EOL> def StorePath ( self , path ) : <EOL> with open ( path , "<STR_LIT:w>" ) as f : <EOL> self . StoreFile ( f ) <EOL> return <EOL> def Save ( self , root ) : <EOL> if root is None : <EOL> root = self . _root <EOL> if root is None : <EOL> prefix = "<STR_LIT>" <EOL> else : <EOL> prefix = root <EOL> self . StorePath ( prefix + SYSTEM_MANIFEST_FILE ) <EOL> def Validate ( self ) : <EOL> from . import SIGNATURE_FAILURE <EOL> if SEQUENCE_KEY not in self . _dict : <EOL> raise Exceptions . ManifestInvalidException ( "<STR_LIT>" ) <EOL> if TRAIN_KEY not in self . _dict : <EOL> raise Exceptions . ManifestInvalidException ( "<STR_LIT>" ) <EOL> if PACKAGES_KEY not in self . _dict or len ( self . _dict [ PACKAGES_KEY ] ) == <NUM_LIT:0> : <EOL> raise Exceptions . ManifestInvalidException ( "<STR_LIT>" ) <EOL> if self . _config and self . _config . UpdateServerSigned ( ) == False : <EOL> log . debug ( "<STR_LIT>" % <EOL> ( self . _config . UpdateServerName ( ) , <EOL> self . _config . UpdateServerURL ( ) ) ) <EOL> return True <EOL> if SIGNATURE_KEY not in self . _dict : <EOL> if self . _requireSignature and SIGNATURE_FAILURE : <EOL> log . debug ( "<STR_LIT>" ) <EOL> else : <EOL> if self . _requireSignature : <EOL> if not self . VerifySignature ( ) : <EOL> if self . _requireSignature and SIGNATURE_FAILURE : <EOL> raise Exceptions . ManifestInvalidSignature ( "<STR_LIT>" ) <EOL> if not self . _requireSignature : <EOL> log . debug ( "<STR_LIT>" ) <EOL> elif not SIGNATURE_FAILURE : <EOL> log . debug ( "<STR_LIT>" ) <EOL> return True <EOL> def Notice ( self ) : <EOL> if NOTICE_KEY not in self . _dict : <EOL> if ( SWITCH_KEY in self . _dict ) : <EOL> return "<STR_LIT>" % ( self . Train ( ) , self . NewTrain ( ) ) <EOL> else : <EOL> return None <EOL> else : <EOL> return self . _dict [ NOTICE_KEY ] <EOL> def SetNotice ( self , n ) : <EOL> self . _dict [ NOTICE_KEY ] = n <EOL> if n is None : <EOL> self . _dict . pop ( NOTICE_KEY ) <EOL> return <EOL> def Scheme ( self ) : <EOL> if SCHEME_KEY in self . _dict : <EOL> return self . _dict [ SCHEME_KEY ] <EOL> else : <EOL> return None <EOL> def SetScheme ( self , s ) : <EOL> self . _dict [ SCHEME_KEY ] = s <EOL> return <EOL> def Sequence ( self ) : <EOL> return self . _dict [ SEQUENCE_KEY ] <EOL> def SetSequence ( self , seq ) : <EOL> self . _dict [ SEQUENCE_KEY ] = seq <EOL> return <EOL> def SetNote ( self , name , location ) : <EOL> if NOTES_KEY not in self . _dict : <EOL> self . _dict [ NOTES_KEY ] = { } <EOL> if location . startswith ( self . _config . UpdateServerURL ( ) ) : <EOL> location = location [ len ( location ) : ] <EOL> self . _dict [ NOTES_KEY ] [ name ] = location <EOL> def Notes ( self , raw = False ) : <EOL> if NOTES_KEY in self . _dict : <EOL> rv = { } <EOL> for name in self . _dict [ NOTES_KEY ] . keys ( ) : <EOL> loc = self . _dict [ NOTES_KEY ] [ name ] <EOL> if raw is False and not loc . startswith ( self . _config . UpdateServerURL ( ) ) : <EOL> loc = "<STR_LIT>" % ( self . _config . UpdateServerURL ( ) , self . Train ( ) , loc ) <EOL> rv [ name ] = loc <EOL> return rv <EOL> return None <EOL> def SetNotes ( self , notes ) : <EOL> self . _dict [ NOTES_KEY ] = { } <EOL> if notes is None : <EOL> self . _dict . pop ( NOTES_KEY ) <EOL> else : <EOL> for name , loc in notes . iteritems ( ) : <EOL> if loc . startswith ( self . _config . UpdateServerURL ( ) ) : <EOL> loc = loc [ len ( self . _config . UpdateServerURL ( ) ) : ] <EOL> self . _dict [ NOTES_KEY ] [ name ] = os . path . basename ( loc ) <EOL> return <EOL> def Note ( self , name ) : <EOL> if NOTES_KEY not in self . _dict : <EOL> return None <EOL> notes = self . _dict [ NOTES_KEY ] <EOL> if name not in notes : <EOL> return None <EOL> loc = notes [ name ] <EOL> if not loc . startswith ( self . _config . UpdateServerURL ( ) ) : <EOL> loc = self . _config . UpdateServerURL + loc <EOL> return loc <EOL> def Train ( self ) : <EOL> if TRAIN_KEY not in self . _dict : <EOL> raise Exceptions . ManifestInvalidException ( "<STR_LIT>" ) <EOL> return self . _dict [ TRAIN_KEY ] <EOL> def SetTrain ( self , train ) : <EOL> self . _dict [ TRAIN_KEY ] = train <EOL> return <EOL> def Packages ( self ) : <EOL> pkgs = [ ] <EOL> for p in self . _dict [ PACKAGES_KEY ] : <EOL> pkg = Package . Package ( p ) <EOL> pkgs . append ( pkg ) <EOL> return pkgs <EOL> def AddPackage ( self , pkg ) : <EOL> if PACKAGES_KEY not in self . _dict : <EOL> self . _dict [ PACKAGES_KEY ] = [ ] <EOL> self . _dict [ PACKAGES_KEY ] . append ( pkg . dict ( ) ) <EOL> return <EOL> def AddPackages ( self , list ) : <EOL> if PACKAGES_KEY not in self . _dict : <EOL> self . _dict [ PACKAGES_KEY ] = [ ] <EOL> for p in list : <EOL> self . AddPackage ( p ) <EOL> return <EOL> def SetPackages ( self , list ) : <EOL> self . _dict [ PACKAGES_KEY ] = [ ] <EOL> self . AddPackages ( list ) <EOL> return <EOL> def VerifySignature ( self ) : <EOL> from . import IX_ROOT_CA_FILE , UPDATE_CERT_FILE , VERIFIER_HELPER , IX_CRL <EOL> from . import SIGNATURE_FAILURE <EOL> if self . Signature ( ) is None : <EOL> return not SIGNATURE_FAILURE <EOL> else : <EOL> import subprocess <EOL> import tempfile <EOL> if not os . path . isfile ( IX_ROOT_CA_FILE ) or not os . path . isfile ( UPDATE_CERT_FILE ) or not os . path . isfile ( VERIFIER_HELPER ) : <EOL> log . debug ( "<STR_LIT>" ) <EOL> return False <EOL> crl_file = tempfile . NamedTemporaryFile ( suffix = "<STR_LIT>" ) <EOL> if crl_file is None : <EOL> log . debug ( "<STR_LIT>" ) <EOL> else : <EOL> try : <EOL> if not self . _config . TryGetNetworkFile ( url = IX_CRL , <EOL> pathname = crl_file . name , <EOL> reason = "<STR_LIT>" ) : <EOL> log . error ( "<STR_LIT>" % IX_CRL ) <EOL> crl_file . close ( ) <EOL> crl_file = None <EOL> except BaseException as e : <EOL> log . debug ( "<STR_LIT>" % str ( e ) ) <EOL> crl_file . close ( ) <EOL> crl_file = None <EOL> tdata = None <EOL> verify_cmd = [ VERIFIER_HELPER , <EOL> "<STR_LIT>" , UPDATE_CERT_FILE , <EOL> "<STR_LIT>" , IX_ROOT_CA_FILE , <EOL> "<STR_LIT>" , self . Signature ( ) ] <EOL> if crl_file : <EOL> verify_cmd . extend ( [ "<STR_LIT>" , crl_file . name ] ) <EOL> else : <EOL> log . debug ( "<STR_LIT>" % IX_CRL ) <EOL> log . debug ( "<STR_LIT>" % verify_cmd ) <EOL> temp = self . dict ( ) . copy ( ) <EOL> if SIGNATURE_KEY in temp : temp . pop ( SIGNATURE_KEY ) <EOL> canonical = MakeString ( temp ) <EOL> if len ( canonical ) < <NUM_LIT:10> * <NUM_LIT> : <EOL> verify_cmd . append ( canonical ) <EOL> else : <EOL> tdata = tempfile . NamedTemporaryFile ( ) <EOL> tdata . write ( canonical ) <EOL> verify_cmd . extend ( [ "<STR_LIT>" , tdata . name ] ) <EOL> rv = False <EOL> try : <EOL> subprocess . check_call ( verify_cmd ) <EOL> log . debug ( "<STR_LIT>" ) <EOL> rv = True <EOL> except subprocess . CalledProcessError as e : <EOL> rv = False <EOL> log . error ( "<STR_LIT>" % e . returncode ) <EOL> if tdata : <EOL> tdata . close ( ) <EOL> os . remove ( tdata . name ) <EOL> return rv <EOL> return False <EOL> def Signature ( self ) : <EOL> if SIGNATURE_KEY in self . _dict : <EOL> return self . _dict [ SIGNATURE_KEY ] <EOL> def SetSignature ( self , signed_hash ) : <EOL> self . _dict [ SIGNATURE_KEY ] = signed_hash <EOL> return <EOL> def SignWithKey ( self , key_data ) : <EOL> if key_data is None : <EOL> if SIGNATURE_KEY in self . _dict : <EOL> self . _dict . pop ( SIGNATURE_KEY ) <EOL> else : <EOL> import OpenSSL . crypto as Crypto <EOL> from base64 import b64encode as base64 <EOL> if isinstance ( key_data , Crypto . PKey ) : <EOL> key = key_data <EOL> else : <EOL> key = Crypto . load_privatekey ( Crypto . FILETYPE_PEM , key_data ) <EOL> temp = self . dict ( ) <EOL> if SIGNATURE_KEY in temp : temp . pop ( SIGNATURE_KEY ) <EOL> tstr = MakeString ( temp ) <EOL> signed_value = base64 ( Crypto . sign ( key , tstr , "<STR_LIT>" ) ) <EOL> self . _dict [ SIGNATURE_KEY ] = signed_value <EOL> return <EOL> def Version ( self ) : <EOL> if VERSION_KEY in self . _dict : <EOL> return self . _dict [ VERSION_KEY ] <EOL> else : <EOL> return None <EOL> def SetVersion ( self , version ) : <EOL> self . _dict [ VERSION_KEY ] = version <EOL> return <EOL> def SetTimeStamp ( self , ts ) : <EOL> self . _dict [ TIMESTAMP_KEY ] = ts <EOL> def TimeStamp ( self ) : <EOL> if TIMESTAMP_KEY in self . _dict : <EOL> return self . _dict [ TIMESTAMP_KEY ] <EOL> return <NUM_LIT:0> <EOL> def NewTrain ( self ) : <EOL> if SWITCH_KEY in self . _dict : <EOL> return self . _dict [ SWITCH_KEY ] <EOL> else : <EOL> return None <EOL> def SetReboot ( self , reboot ) : <EOL> self . _dict [ REBOOT_KEY ] = reboot <EOL> if reboot is None : <EOL> self . _dict . pop ( REBOOT_KEY ) <EOL> def Reboot ( self ) : <EOL> if REBOOT_KEY in self . _dict : <EOL> return self . _dict [ REBOOT_KEY ] <EOL> return None </s>
