3 'j__@srddlZddlZddlZddlZddlZddlZddlZddlmZddl m Z m Z m Z ddZ GdddZdS)N)ProcessPoolExecutor)file_is_binarysos_get_command_outputfile_is_certificatec Cstj|}tjj|d}ttddd|_xp|jD]d}tjj||j}tjj |}tjj |}tjj ||g}||krt d|d||j ||q6Wtjj||jj dd j d d SQRXdS) NZcleanerZfully_trusted_filtercSs|S)N)memberpathrr/usr/lib/python3.6/__init__.py#sz!extract_archive..z"Attempted path traversal in tarflez != /z.tarr)tarfileopenosrjoingetattrZextraction_filterZ getmembersnameabspath commonprefix Exceptionextractsplit) archive_pathtmpdirarchiverrZ member_pathZ abs_directoryZ abs_targetprefixrrr extract_archives    rc@sxeZdZdZdZdZdZdZdZdZ iZ ddZ ddZ d d Z d d Zd dZdRddZddZeddZeddZeddZddZddZddZd d!ZdSd"d#ZdTd$d%ZdUd&d'ZdVd(d)Zd*d+Zed,d-Z d.d/Z!d0d1Z"d2d3Z#d4d5Z$dWd6d7Z%d8d9Z&d:d;Z'dd?Z)d@dAZ*dBdCZ+dDdEZ,dFdGZ-dHdIZ.dJdKZ/dLdMZ0dNdOZ1dPdQZ2dS)XSoSObfuscationArchiveaA representation of an extracted archive or an sos archive build directory which is used by SoSCleaner. Each archive that needs to be obfuscated is loaded into an instance of this class. All report-level operations should be contained within this class. rZ undeterminedFcCs||_|j|_||_|jjdd jdd|_|j|_tjd|_tjd|_ |j |_ d|_ |j d|_||_||_f|_|jd |jd |jdS) Nr r z.tarrsossos_uiFzLoaded z as type r )rfinal_archive_pathrr archive_nameui_namelogging getLoggersoslogui_log_load_skip_list skip_list is_extracted _load_self archive_rootkeep_binary_filestreat_certificatesparserslog_info description)selfrrr.r/rrr __init__Cs    zSoSObfuscationArchive.__init__cCsVxP|jD]F}y|j|}Wqtk rL}z|jd|WYdd}~XqXqW|S)NzError obfuscating string data: )r0Zparse_string_for_keysrr1)r3Z string_dataparsererrrrr obfuscate_stringWs  &z&SoSObfuscationArchive.obfuscate_stringcCs|j|jdd}|j|jdd|}||kr|j|d}tjj||}tjj|shtj||n&|jtj|}tj |tj ||dS)Nr r rr r ) r7rreplacerrrislinkrenamereadlinkremovesymlink)r3Z short_namefilenameZ_ob_short_nameZ _ob_filenamearc_pathZ_ob_pathZ _target_obrrr obfuscate_filenameas  z(SoSObfuscationArchive.obfuscate_filenamecCs ||_dS)N)r0)r3r0rrr set_parsersxsz!SoSObfuscationArchive.set_parserscCs4tjd|_tjd|_x|jD] }|jq WdS)Nrr )r%r&r'r(r0Zload_map_entries)r3r5rrr load_parser_entries{s   z)SoSObfuscationArchive.load_parser_entriesNcCsd}|js||fS|dkr"|j}x^|D]V}y|j|\}}||7}Wq(tk r|}z|jd||jWYdd}~Xq(Xq(W||fS)aRun a line through each of the obfuscation parsers, keeping a cumulative total of substitutions done on that particular line. Positional arguments: :param line str: The raw line as read from the file being processed :param parsers: A list of parser objects to obfuscate with. If None, use all. Returns the fully obfuscated line and the number of substitutions made rNzfailed to parse line: )stripr0Z parse_liner log_debugr)r3liner0countr5_countr6rrr obfuscate_lines  *z$SoSObfuscationArchive.obfuscate_linec 's|jxp|D]f}|jdtjd|ytjj||jd|jrRw|j rp|j rp|j w|jrt |s|j rwtjj |rwt |}|r|dkr|j w|jdkrw|jdkr|j w|jdkr|j|}tjj||jdfdd |jD}|s8|jd p,|d w|jd pF|d }tjd|jd}t|ddddx}xp|D]h}y&|j||\}} || 7}|j|Wn:tk r} z|jdd| WYdd} ~ XnXq|WWdQRX|jd |rtj|j||j|WdQRX|j|Wqtk rv} z&|jdtjd|d| WYdd} ~ XqXqW|j|j|j fS)Nz pid=z: obfuscating )startZcertificatekeyZkeepr<Z obfuscatecs(g|] }tfdd|jDs|qS)c3s|]}|jVqdS)N)match).0_skip)rel_namerr szGSoSObfuscationArchive.obfuscate_arc_files...)anyZ skip_patterns)rKZ_p)rMrr sz=SoSObfuscationArchive.obfuscate_arc_files..zSkipping obfuscation of z" due to matching file skip patternz Obfuscating rw)modedirrzutf-8r8)encodingerrorszUnable to obfuscate z: z': caught exception on obfuscating file )!rBrDrgetpidrrelpathextracted_pathshould_skip_filer.should_remove_file remove_filerr9rr/certificate_to_textr0tempfileZNamedTemporaryFilerrrHwriterseekshutilZcopyfilerupdate_sub_countr@files_obfuscated_counttotal_sub_countremoved_file_count) r3flistr>Zis_certificateZ_parsersZsubsZtfilefnamerEZcntr6r)rMr obfuscate_arc_filesst              8 6z)SoSObfuscationArchive.obfuscate_arc_filescCstdS)z=Check if the archive is a well-known type we directly supportN)NotImplementedError)clsr?rrr check_is_typesz#SoSObfuscationArchive.check_is_typecCsd|jjjkS)Nr) __class____name__lower)r3rrr is_sosszSoSObfuscationArchive.is_soscCs d|jkS)NZinsights) type_name)r3rrr is_insightssz!SoSObfuscationArchive.is_insightscCs|jrtj|j|_dS)N) is_tarfilerrrtarobj)r3rrr r,sz SoSObfuscationArchive._load_selfcCsgS)a/Return a list of ObfuscationArchives that represent additional archives found within the target archive. For example, an archive from `sos collect` will return a list of ``SoSReportArchive`` objects. This should be overridden by individual types of ObfuscationArchive's r)r3rrr get_nested_archivessz)SoSObfuscationArchive.get_nested_archivescCs>|jr0|jj}|jr|jStjj|jp.tjStjj |j S)z|Set the root path for the archive that should be prepended to any filenames given to methods in this class. ) rrrsZ firstmemberisdirrrrdirnameseprr)r3Ztoplevelrrr get_archive_root s z&SoSObfuscationArchive.get_archive_rootcCs"|jj|jddd|dS)z9Helper to easily format ui messages on a per-report basisz :z<50 N)r(infor$)r3msgrrr report_msgsz SoSObfuscationArchive.report_msgcCs&d|rd|ndd|jd|S)Nz[cleaner:r![z]] )r#)r3r{callerrrr _fmt_log_msgsz"SoSObfuscationArchive._fmt_log_msgcCs|jj|j||dS)N)r'debugr)r3r{rrrr rDszSoSObfuscationArchive.log_debugcCs|jj|j||dS)N)r'rzr)r3r{rrrr r1 szSoSObfuscationArchive.log_infocCs|jj|j||dS)N)r'errorr)r3r{rrrr log_error#szSoSObfuscationArchive.log_errorcCsddddddgS)zyProvide a list of files and file regexes to skip obfuscation on Returns: list of files and file regexes z proc/kallsymsz sosreport-z sys/firmwarezsys/fszsys/kernel/debugz sys/moduler)r3rrr r)&s z%SoSObfuscationArchive._load_skip_listc Cs&y tj|jStk r dSXdS)NF)rrrrr)r3rrr rr4s z SoSObfuscationArchive.is_tarfilecCsB|d}|jd|dtd|dt|tj||S)zConvert a certificate to text. This is used when cleaner encounters a certificate file and the option 'treat_certificates' is 'obfuscate'. z.textzConverting certificate file 'z ' to textz openssl storeutl -r -noout -out z -text -certs )r1rstrrr<)r3rgZout_fnrrr r];s   z)SoSObfuscationArchive.certificate_to_textcCs<|j|}|r8|jd|dtj||jd7_dS)zRemove a file from the archive. This is used when cleaner encounters a binary file, which we cannot reliably obfuscate. zRemoving binary file 'z' from archiver N) get_file_pathr1rr<re)r3rgZ full_fnamerrr r\Hs   z!SoSObfuscationArchive.remove_filecCs6|js&|js|j|_tjj|j|Stjj|j|S)zBased on the type of archive we're dealing with, do whatever that archive requires to a provided **relative** filepath to be able to access it within the archive )r+r-rxrrrrY)r3rgrrr format_file_nameSs  z&SoSObfuscationArchive.format_file_namecCs|jdkrZ|jrZ|j|}y|jj|jjdStk rV|jd|ddSXn`y(t |j|ddd }|jSQRXWn6t k r}z|jd |d |dSd}~XnXdS) zReturn the content from the specified fname. Particularly useful for tarball-type archives so we can retrieve prep file contents prior to extracting the entire archive Fzutf-8zUnable to retrieve z: no such file in archiver!rT)rUNzFailed to get contents of z: ) r+rrrrsZ extractfilereaddecodeKeyErrorrDrr)r3rgr>Zto_readr6rrr get_file_content^s   z&SoSObfuscationArchive.get_file_contentc Cs~|jr,|s|jd|j|_d|_d|_n|j|_tjdkrh|j dxtj |jD]\}}}yx8|D]0}tj j ||}tj |j}tj||t jBqpWx|D]~}tj j ||} tj j|  stj j| rqtj| tj stj| tj r|j d| j|jd tj| t jt jBqWWq\tk rb} z|j d| WYdd} ~ Xq\Xq\W|j d|jdS) Nz Extracting...Trz)Verifying permissions of archive contentszAdding owner rw permissions to r z!Error while trying to set perms: zExtracted path is r )rrr| extract_selfrYr+rsrrgetuidrDwalkrrstatst_modechmodS_IRWXUexistsr9accessR_OKW_OKrS_IRUSRS_IWUSRr) r3quietrvdirsfiles_dirZ_dirnameZ _dir_permsr>rgr6rrr rus6      &zSoSObfuscationArchive.extractcCs.|jj|j|}||_tj|j|||_dS)zRename the top-level directory to new_name, which should be an obfuscated string that scrubs the hostname from the top-level dir which would be named after the unobfuscated sos report N)rYr8r#rr:)r3new_name_pathrrr rename_top_dirsz$SoSObfuscationArchive.rename_top_dircCs|jr|jjdrdSdSdS)zReturn the compression type used by the archive, if any. This is then used by SoSCleaner to generate a policy-derived compression command to repack the archive xzZgzN)rrrendswith)r3rrr get_compressions  z%SoSObfuscationArchive.get_compressionc Csd}|jd}i}|rL|d|7}|d|7}|dkrDddi}ndd i}|jd |tj|fd |i|$}|j|jtjj|jd d WdQRX|S)zIPack the extracted archive as a tarfile to then be re-compressed rQz-obfuscated.tarr}.rZpresetZ compresslevelzBuilding tar file rRr )ZarcnameN) rYrDrraddrrrr#)r3methodrRZtarpathZ compr_argsZtarrrr build_tar_files   z$SoSObfuscationArchive.build_tar_filecCsy|j||_Wn4tk rD}z|jd|WYdd}~XnX|jd|jy |jWn<tk r}z |jd||jdWYdd}~XnXdS)zExecute the compression command, and set the appropriate final archive path for later reference by SoSCleaner on a per-archive basis z(Exception while re-compressing archive: NzCompressed to z'Failed to remove extraction directory: z/Failed to remove temporary extraction directory)rr"rrDremove_extracted_pathr|)r3rr6rrr compresss zSoSObfuscationArchive.compressc Csty"|jd|jtj|jWnLtk rntj|jtjtj j |jr^tj |jn tj|jYnXdS)zAfter the tarball has been re-compressed, remove the extracted path so that we don't take up that duplicate space any longer during execution z Removing N) rDrYraZrmtreeOSErrorrrrrrisfiler<)r3rrr rsz+SoSObfuscationArchive.remove_extracted_pathc Cs2td }|jt|j|j}|j}|SQRXdS)z}Extract an archive into our tmpdir so that we may inspect it or iterate through its contents for obfuscation r N)rZsubmitrrrresult)r3Z_poolZ _path_futurerrrr rs   z"SoSObfuscationArchive.extract_selfccs|xvtj|jD]f\}}}x,|D]$}tjj||}tjj|r|VqWx,|D]$}tjj||}tjj|rL|VqLWqWdS)z.Iterator for a list of symlinks in the archiveN)rrrYrrr9)r3rvrrrZ_dirpathr>_fnamerrr get_symlinkss     z"SoSObfuscationArchive.get_symlinksccsTxNtj|jD]>\}}}x2|D]*}tjj||jd}tjj|s|VqWqWdS)zIterator for a list of files in the archive, to allow clean to iterate over. Will not include symlinks, as those are handled separately r N)rrrYrrlstripr9)r3rv_rr>rrrr get_filess   zSoSObfuscationArchive.get_filescCs.g}x$tj|jD]\}}}|j|qW|S)z3Return a list of all directories within the archive)rrrYappend)r3Zdir_listrvrrrr get_directory_listsz(SoSObfuscationArchive.get_directory_listcCs |jd7_|j|7_dS)zCalled when a file has finished being parsed and used to track total substitutions made and number of files that had changes made r N)rcrd)r3rFrrr rb sz&SoSObfuscationArchive.update_sub_countcCs*tjj|j|jd}tjj|r&|SdS)zReturn the filepath of a specific file within the archive so that it may be selectively inspected if it exists r r!)rrrrYrr)r3rgrrrr rsz#SoSObfuscationArchive.get_file_pathcCsZtjj|j| r,tjj|j| r,dSx(|jD]}|j|sNtj||r4dSq4WdS)a%Checks the provided filename against a list of filepaths to not perform obfuscation on, as defined in self.skip_list Positional arguments: :param filename str: Filename relative to the extracted archive root TF) rrrrr9r* startswithrerJ)r3r>rLrrr rZs  z&SoSObfuscationArchive.should_skip_filec CsVddddddddd g }x|D]}tj||rd SqW|j|}tjj|rRt|Sd S) aaDetermine if the file should be removed or not, due to an inability to reliably obfuscate that file based on the filename. :param fname: Filename relative to the extracted archive root :type fname: ``str`` :returns: ``True`` if the file cannot be reliably obfuscated :rtype: ``bool`` z.*\.gz$z.*\.xz$z .*\.bzip2$z .*\.tar\..*z.*\.txz$z.*\.tgz$z.*\.bin$z .*\.journal$z.*\~$TF)rrJrrrrr)r3rgZobvious_removesZ_arc_regZ _full_pathrrr r[-s     z(SoSObfuscationArchive.should_remove_file)N)N)N)N)N)F)3rm __module__ __qualname____doc__rcrdrerpr2Z is_nestedZ prep_filesr4r7r@rArBrHrh classmethodrkpropertyrorqr,rtrxr|rrDr1rr)rrr]r\rrrrrrrrrrrrrbrrZr[rrrr r3s\  R              &     r)r%rrarrr^rconcurrent.futuresrZ sos.utilitiesrrrrrrrrr  s