├── data ├── .cache │ └── .gitignore ├── PIE-selectively-enabled.list ├── F19p.txt.bz2 ├── RPM-GPG-KEY-fedora-19-primary ├── 1ACA3465.txt ├── f21541eb.txt ├── fd431d51.txt ├── RPM-GPG-KEY-fedora-19-secondary └── sgid-files-F19.txt ├── gen-setxid.sh ├── results ├── PIE-usage-F19-ALL.png ├── PIE-usage-F19-Web Server.png ├── PIE-usage-F19-GNOME-Desktop.png └── PIE-usage-F19-Development and Creative Workstation.png ├── static ├── assets │ ├── ico │ │ ├── favicon.ico │ │ ├── favicon.png │ │ ├── apple-touch-icon-114-precomposed.png │ │ ├── apple-touch-icon-144-precomposed.png │ │ ├── apple-touch-icon-57-precomposed.png │ │ └── apple-touch-icon-72-precomposed.png │ ├── img │ │ ├── less-logo-large.png │ │ ├── grid-baseline-20px.png │ │ ├── glyphicons-halflings.png │ │ ├── bootstrap-docs-readme.png │ │ ├── bootstrap-mdo-sfmoma-01.jpg │ │ ├── bootstrap-mdo-sfmoma-02.jpg │ │ ├── bootstrap-mdo-sfmoma-03.jpg │ │ ├── bs-docs-twitter-github.png │ │ ├── bs-docs-masthead-pattern.png │ │ ├── responsive-illustrations.png │ │ ├── bs-docs-bootstrap-features.png │ │ ├── glyphicons-halflings-white.png │ │ └── bs-docs-responsive-illustrations.png │ ├── js │ │ ├── google-code-prettify │ │ │ └── prettify.css │ │ ├── jquery.mousewheel-min.js │ │ ├── bootstrap-transition.js │ │ ├── html5shiv.js │ │ ├── bootstrap-alert.js │ │ ├── bootstrap-button.js │ │ ├── bootstrap-popover.js │ │ ├── README.md │ │ ├── bootstrap-affix.js │ │ ├── bootstrap-tab.js │ │ ├── application.js │ │ ├── bootstrap-dropdown.js │ │ ├── bootstrap-scrollspy.js │ │ ├── bootstrap-collapse.js │ │ ├── bootstrap-carousel.js │ │ ├── bootstrap-modal.js │ │ ├── jquery.jsonp.js │ │ ├── bootstrap-typeahead.js │ │ └── bootstrap-tooltip.js │ └── css │ │ └── jquery.terminal.css └── pages │ └── checksec.html ├── deps ├── python-debian_0.1.21+nmu2.tar.gz └── python3-chardet_2.0.1.orig.tar.gz ├── invoke_rpmgrill.sh ├── settings.py ├── fetch_ubuntu_repodata.sh ├── tester.py ├── orphan-files-finder.py ├── scripts ├── stuffer.py ├── package-list.py ├── exposed-list.py ├── badsoperms.py ├── report-generator.py ├── setuid-whitelist.py ├── analyzer.py ├── rpmdiff └── setxid-whitelist.py ├── av_scanner.py ├── pie.gnu ├── tasks.py ├── listener.py ├── chart-er-all.py ├── rpm-shell.py ├── chart-er.py ├── checksecsrv.py ├── majdoor.py ├── README.md ├── deb-scanner.py ├── deb-shell.py ├── bug-shell.py └── scanner.py /data/.cache/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /data/PIE-selectively-enabled.list: -------------------------------------------------------------------------------- 1 | bind 2 | 3 | -------------------------------------------------------------------------------- /data/F19p.txt.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/7h3rAm/checksec/master/data/F19p.txt.bz2 -------------------------------------------------------------------------------- /gen-setxid.sh: -------------------------------------------------------------------------------- 1 | ./scripts/setxid-whitelist.py | sort | uniq > F19-setxid-list-v2.txt 2 | -------------------------------------------------------------------------------- /results/PIE-usage-F19-ALL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/7h3rAm/checksec/master/results/PIE-usage-F19-ALL.png -------------------------------------------------------------------------------- /static/assets/ico/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/7h3rAm/checksec/master/static/assets/ico/favicon.ico -------------------------------------------------------------------------------- /static/assets/ico/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/7h3rAm/checksec/master/static/assets/ico/favicon.png -------------------------------------------------------------------------------- /deps/python-debian_0.1.21+nmu2.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/7h3rAm/checksec/master/deps/python-debian_0.1.21+nmu2.tar.gz -------------------------------------------------------------------------------- /results/PIE-usage-F19-Web Server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/7h3rAm/checksec/master/results/PIE-usage-F19-Web Server.png -------------------------------------------------------------------------------- /static/assets/img/less-logo-large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/7h3rAm/checksec/master/static/assets/img/less-logo-large.png -------------------------------------------------------------------------------- /deps/python3-chardet_2.0.1.orig.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/7h3rAm/checksec/master/deps/python3-chardet_2.0.1.orig.tar.gz -------------------------------------------------------------------------------- /results/PIE-usage-F19-GNOME-Desktop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/7h3rAm/checksec/master/results/PIE-usage-F19-GNOME-Desktop.png -------------------------------------------------------------------------------- /static/assets/img/grid-baseline-20px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/7h3rAm/checksec/master/static/assets/img/grid-baseline-20px.png -------------------------------------------------------------------------------- /static/assets/img/glyphicons-halflings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/7h3rAm/checksec/master/static/assets/img/glyphicons-halflings.png -------------------------------------------------------------------------------- /static/assets/img/bootstrap-docs-readme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/7h3rAm/checksec/master/static/assets/img/bootstrap-docs-readme.png -------------------------------------------------------------------------------- /static/assets/img/bootstrap-mdo-sfmoma-01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/7h3rAm/checksec/master/static/assets/img/bootstrap-mdo-sfmoma-01.jpg -------------------------------------------------------------------------------- /static/assets/img/bootstrap-mdo-sfmoma-02.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/7h3rAm/checksec/master/static/assets/img/bootstrap-mdo-sfmoma-02.jpg -------------------------------------------------------------------------------- /static/assets/img/bootstrap-mdo-sfmoma-03.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/7h3rAm/checksec/master/static/assets/img/bootstrap-mdo-sfmoma-03.jpg -------------------------------------------------------------------------------- /static/assets/img/bs-docs-twitter-github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/7h3rAm/checksec/master/static/assets/img/bs-docs-twitter-github.png -------------------------------------------------------------------------------- /static/assets/img/bs-docs-masthead-pattern.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/7h3rAm/checksec/master/static/assets/img/bs-docs-masthead-pattern.png -------------------------------------------------------------------------------- /static/assets/img/responsive-illustrations.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/7h3rAm/checksec/master/static/assets/img/responsive-illustrations.png -------------------------------------------------------------------------------- /static/assets/img/bs-docs-bootstrap-features.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/7h3rAm/checksec/master/static/assets/img/bs-docs-bootstrap-features.png -------------------------------------------------------------------------------- /static/assets/img/glyphicons-halflings-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/7h3rAm/checksec/master/static/assets/img/glyphicons-halflings-white.png -------------------------------------------------------------------------------- /invoke_rpmgrill.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cd ../rpmgrill/ 4 | 5 | perl -C63 -I$(pwd)/lib ./bin/nvr2rpmgrill $1 6 | perl -C63 -I$(pwd)/lib ./bin/rpmgrill $1 7 | -------------------------------------------------------------------------------- /static/assets/ico/apple-touch-icon-114-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/7h3rAm/checksec/master/static/assets/ico/apple-touch-icon-114-precomposed.png -------------------------------------------------------------------------------- /static/assets/ico/apple-touch-icon-144-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/7h3rAm/checksec/master/static/assets/ico/apple-touch-icon-144-precomposed.png -------------------------------------------------------------------------------- /static/assets/ico/apple-touch-icon-57-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/7h3rAm/checksec/master/static/assets/ico/apple-touch-icon-57-precomposed.png -------------------------------------------------------------------------------- /static/assets/ico/apple-touch-icon-72-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/7h3rAm/checksec/master/static/assets/ico/apple-touch-icon-72-precomposed.png -------------------------------------------------------------------------------- /static/assets/img/bs-docs-responsive-illustrations.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/7h3rAm/checksec/master/static/assets/img/bs-docs-responsive-illustrations.png -------------------------------------------------------------------------------- /results/PIE-usage-F19-Development and Creative Workstation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/7h3rAm/checksec/master/results/PIE-usage-F19-Development and Creative Workstation.png -------------------------------------------------------------------------------- /settings.py: -------------------------------------------------------------------------------- 1 | DEBUG = True 2 | SECRET_KEY = 'dummy' 3 | CSRF_ENABLED = True 4 | 5 | # database configuration 6 | MONGODB_HOST = '127.0.0.1' 7 | MONGODB_PORT = 27017 8 | MONGODB_DB = "test_database" 9 | -------------------------------------------------------------------------------- /fetch_ubuntu_repodata.sh: -------------------------------------------------------------------------------- 1 | for item in main multiverse restricted universe 2 | do 3 | rsync --progress -avrz --exclude='*.bz2' rsync://archive.ubuntu.com/ubuntu/dists/saucy/$item/binary-amd64/ data/$item 4 | done 5 | -------------------------------------------------------------------------------- /tester.py: -------------------------------------------------------------------------------- 1 | from tasks import * 2 | 3 | import sys 4 | 5 | process(sys.argv[1]) 6 | 7 | # process(420245) 8 | 9 | # process(418453) 10 | # process(418456) 11 | process(418022) # good 12 | # process(418447) 13 | # process.delay(418022) 14 | # process.delay(416465) 15 | #process.delay(416465) 16 | -------------------------------------------------------------------------------- /orphan-files-finder.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import rpm 4 | import os 5 | 6 | ts = rpm.TransactionSet() 7 | 8 | known_files = {} 9 | 10 | print("[+] Loading database...") 11 | 12 | ts.setVSFlags((rpm._RPMVSF_NOSIGNATURES|rpm._RPMVSF_NODIGESTS)) 13 | for hdr in ts.dbMatch(): 14 | fi = hdr.fiFromHeader() 15 | for f in fi: 16 | known_files[f] = True 17 | # print '%s-%s:%s-%s.%s' % (hdr['name'], 18 | # hdr['epochnum'],hdr['version'],hdr['release'], 19 | # hdr['arch']) 20 | 21 | paths = known_files.keys() 22 | 23 | print("[+] Scanning system...\n") 24 | for (path, _, files) in os.walk("/"): 25 | for fname in files: 26 | path = os.path.join(path, fname) 27 | if os.path.exists(path) and path not in paths: 28 | # is it excluded? 29 | if not path.startswith("/home"): 30 | print(path) 31 | -------------------------------------------------------------------------------- /scripts/stuffer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | 5 | try: 6 | import pymongo 7 | except ImportError: 8 | print >> sys.stderr, "Please install pymongo package" 9 | sys.exit(-1) 10 | 11 | import subprocess 12 | import os 13 | import json 14 | 15 | if len(sys.argv) < 2: 16 | print >> sys.stderr, "Usage: %s " % sys.argv[0] 17 | sys.exit(-1) 18 | 19 | 20 | from pymongo import Connection 21 | connection = Connection() 22 | 23 | db = connection.test_database 24 | collection = db.test_collection 25 | 26 | analysis = db.analysis 27 | 28 | with open(sys.argv[1]) as f: 29 | for line in f.readlines(): 30 | line = line.rstrip() 31 | try: 32 | data = json.loads(line) 33 | analysis.insert(data) 34 | except Exception, exc: 35 | print line, str(exc) 36 | sys.exit(1) 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /av_scanner.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import pyclamd 5 | 6 | cd = pyclamd.ClamdNetworkSocket() 7 | try: 8 | cd.ping() 9 | except pyclamd.ConnectionError: 10 | raise ValueError, "could not connect to clamd server either by unix or network socket" 11 | 12 | # print version 13 | # print "Version : \n{0}\n".format(cd.version()) 14 | 15 | # force a db reload 16 | # cd.reload() 17 | 18 | # print stats 19 | # print "\n{0}\n".format(cd.stats()) 20 | 21 | # write test file with EICAR test string 22 | open('/tmp/EICAR','w').write(cd.EICAR()) 23 | 24 | # write test file without virus pattern 25 | open('/tmp/NO_EICAR','w').write('no virus in this file') 26 | 27 | # scan files 28 | print "\n{0}\n".format(cd.scan_file('/tmp/EICAR')) 29 | print "\n{0}\n".format(cd.scan_file('/tmp/NO_EICAR')) 30 | 31 | # scan a stream 32 | print "\n{0}\n".format(cd.scan_stream(cd.EICAR())) 33 | 34 | -------------------------------------------------------------------------------- /static/assets/js/google-code-prettify/prettify.css: -------------------------------------------------------------------------------- 1 | .com { color: #93a1a1; } 2 | .lit { color: #195f91; } 3 | .pun, .opn, .clo { color: #93a1a1; } 4 | .fun { color: #dc322f; } 5 | .str, .atv { color: #D14; } 6 | .kwd, .prettyprint .tag { color: #1e347b; } 7 | .typ, .atn, .dec, .var { color: teal; } 8 | .pln { color: #48484c; } 9 | 10 | .prettyprint { 11 | padding: 8px; 12 | background-color: #f7f7f9; 13 | border: 1px solid #e1e1e8; 14 | } 15 | .prettyprint.linenums { 16 | -webkit-box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0; 17 | -moz-box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0; 18 | box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0; 19 | } 20 | 21 | /* Specify class=linenums on a pre to get line numbering */ 22 | ol.linenums { 23 | margin: 0 0 0 33px; /* IE indents via margin-left */ 24 | } 25 | ol.linenums li { 26 | padding-left: 12px; 27 | color: #bebec5; 28 | line-height: 20px; 29 | text-shadow: 0 1px 0 #fff; 30 | } -------------------------------------------------------------------------------- /static/assets/js/jquery.mousewheel-min.js: -------------------------------------------------------------------------------- 1 | (function(c){function g(a){var b=a||window.event,i=[].slice.call(arguments,1),e=0,h=0,f=0;a=c.event.fix(b);a.type="mousewheel";if(b.wheelDelta)e=b.wheelDelta/120;if(b.detail)e=-b.detail/3;f=e;if(b.axis!==undefined&&b.axis===b.HORIZONTAL_AXIS){f=0;h=-1*e}if(b.wheelDeltaY!==undefined)f=b.wheelDeltaY/120;if(b.wheelDeltaX!==undefined)h=-1*b.wheelDeltaX/120;i.unshift(a,e,h,f);return(c.event.dispatch||c.event.handle).apply(this,i)}var d=["DOMMouseScroll","mousewheel"];if(c.event.fixHooks)for(var j=d.length;j;)c.event.fixHooks[d[--j]]= 2 | c.event.mouseHooks;c.event.special.mousewheel={setup:function(){if(this.addEventListener)for(var a=d.length;a;)this.addEventListener(d[--a],g,false);else this.onmousewheel=g},teardown:function(){if(this.removeEventListener)for(var a=d.length;a;)this.removeEventListener(d[--a],g,false);else this.onmousewheel=null}};c.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})})(jQuery); 3 | -------------------------------------------------------------------------------- /pie.gnu: -------------------------------------------------------------------------------- 1 | set terminal png size 800,600 2 | # set terminal png nocrop enhanced font arial 8 size 800,600 3 | # set terminal png transparent nocrop enhanced font arial 8 size 420,320 4 | set output 'PIE-usage-F19.png' 5 | set boxwidth 0.9 absolute 6 | set grid ytics lt 0 lw 1 lc rgb "#bbbbbb" 7 | set grid xtics lt 0 lw 1 lc rgb "#bbbbbb" 8 | set style fill solid 1.00 border -1 9 | set style histogram clustered gap 1 title offset character 0, 0, 0 10 | set datafile missing '-' 11 | set offset graph 0.1, graph 0.1, graph 0.1, graph 0.0 12 | # set autoscale 13 | set style data histograms 14 | set xtics border in scale 1,0.5 nomirror offset character 0, 0, 0 15 | set xtics ("Stack Canary" 0.00000, "NX Stack" 1.00000, "RELRO" 2.00000, "PIE" 3.00000) 16 | set title "Fedora 19, package hardening report\n(only packages containing ELF objects are considered)" 17 | set ylabel "number of packages" 18 | set yrange [ 0.00000 : * ] noreverse nowriteback 19 | plot 'my.dat' u 1 ti col linecolor rgb "#00FF00", \ 20 | '' u 2 ti col linecolor rgb "#FF0000", \ 21 | '' u 3 ti col linecolor rgb "#FFFF00" 22 | -------------------------------------------------------------------------------- /scripts/package-list.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """Fast RPM analysis tool""" 4 | 5 | import sys 6 | 7 | try: 8 | import libarchive 9 | except ImportError: 10 | print >> sys.stderr, "Please install python-libarchive from PyPI" 11 | sys.exit(-1) 12 | 13 | try: 14 | import rpm 15 | except ImportError: 16 | print >> sys.stderr, "Please install rpm-python package" 17 | sys.exit(-1) 18 | 19 | import subprocess 20 | import os 21 | import json 22 | 23 | 24 | def analyze(rpmfile): 25 | """Analyse single RPM file""" 26 | 27 | if not rpmfile.endswith(".rpm"): 28 | return 29 | 30 | try: 31 | ts = rpm.TransactionSet() 32 | fd = os.open(rpmfile, os.O_RDONLY) 33 | h = ts.hdrFromFdno(fd) 34 | os.close(fd) 35 | except Exception, exc: 36 | print >> sys.stderr, rpmfile, str(exc) 37 | return 38 | 39 | package = h[rpm.RPMTAG_NAME] 40 | 41 | print package 42 | 43 | if len(sys.argv) < 2: 44 | print >> sys.stderr, "Usage: %s [output format (csv / json)]" % sys.argv[0] 45 | sys.exit(-1) 46 | 47 | path = sys.argv[1] 48 | 49 | if(os.path.isfile(path)): 50 | analyze(path) 51 | 52 | for (path, dirs, files) in os.walk(path): 53 | for fname in files: 54 | rpmfile = os.path.join(path, fname) 55 | #print >> sys.stderr, "Analyzing %s ..." % rpmfile 56 | analyze(rpmfile) 57 | -------------------------------------------------------------------------------- /data/RPM-GPG-KEY-fedora-19-primary: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP PUBLIC KEY BLOCK----- 2 | Version: GnuPG v1.4.11 (GNU/Linux) 3 | 4 | mQINBFC5a/0BEAD3LjUH329eJjBCdQ60m5wG9U/QToy/sEsx6+q/012wXPMFBMCW 5 | 1h53ISj1uEyHd++qMn71u/GtWnRTwvPaxUUqdNiFQpTMAmY41JIdXmOzUYj9u3h/ 6 | dLQJT7wKbKHQrfDnapT2O3eIyYuj07iPTtaIrUE8AZ/wVmrJ0xnLDeir2FfC3h3V 7 | mqFo7OAK193FdufYYT5YQlY4jJrgwo7KDjLEh9ZrB42Fj4+MXgjeX3K+gel/GwiS 8 | b/KahgB9bywUcstvDWoXfbhHmf0fw3SmRY+5B0wWp1un7uepsE+JJ69G4gwfgcln 9 | 49JrYBGFdMBuvX6e3Dw5hUZ+rRtUn911qIO9uPR+SCJqf4ttzs9U0VSdLDUfFAv+ 10 | Isb4WOXF8UF0QbN/Cl+EMs9eiN+MNCvYWRDcnsGTeEmIDhABqwfkrOXNpMHm1FNa 11 | P98QVc9TpBojes3KwmkTolAW92lgznYbpeN9nsv4BLT+hnBJGIegsgq78E1fa557 12 | l+am+qerljlHWapVB+107qdNBNxeOAUA6DdXH9B6XZju1+M4kjYrtzKraUCUMZZ9 13 | JebOKMerF++fjdSqmJM8LbNIwcfDtqBqMBBrbiIhlysiFBIItBOK+KCOQ+s95had 14 | J/kFbo1doFUc+k4+ltMwsQGhRoWeSpr3Xl5ohGCnF9k9PwnlBzGx8I+xWwARAQAB 15 | tCZGZWRvcmEgKDE5KSA8ZmVkb3JhQGZlZG9yYXByb2plY3Qub3JnPokCOAQTAQIA 16 | IgUCULlr/QIbDwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQB0d+ZftLGOYR 17 | mA/+KAam9+c6wmJauLOY5dHMxd5UxsfPz3YsTKNLVDwt/ohRze4hXcH/Wt4bOfk8 18 | FSO35xzP4ynXpUZDfrDJsz4QNOpGTIyQCJdCHr8n+RR6IDMSVF9e8uOMoCfwE/Nw 19 | erLD4KGI6S1+bffcEA6YTxQod+4WMEJlkLToTfEBtxksxGMoW3xdwINDT13jQivm 20 | zktoGbOQE6zSSNVaaA94xSw5AbiYXUqfIvvJBmCPeM89ctTC5tTyNsQAN8n0QJtD 21 | lKT3hPfT8H4gacqiecXBJ6fpuWMXY4t044JBPmOk5Nlr0TEJ3m0jmPc1A6f+h+/Y 22 | flBLVIGx+Bw+LIrfxAfrn03XLyleDEO9kvC7q1zxnezKdcxtVXfI5bDQZELWMT1b 23 | KVQvje3KuEZ0IrRwV3qKKucBNqd0k2F6O0ovLMorenLMyBl9SDpOWt67roJeANiq 24 | BFFJkNuDqBtHgzgY7053Lj7VMoIeOtBpRf6WM7m8MaI0gXTgjZrhPPynqdFmDtvd 25 | 6IqBYVFvUgIqPM36Scev2CMpok/g8KBzaHKljim+xSI4wziu3Kfxb854P/Df9WZd 26 | bCDWpFdPY5/dCnoMgTHGKLUumUMlfXif+fEykNt4Ic9Fibkzv+QSHQ5YYtoTfp9i 27 | o7puEJiQxkQsuX/CcXU9NDL6MeBBNS/b67EqnObAIRzroHY= 28 | =apZ8 29 | -----END PGP PUBLIC KEY BLOCK----- 30 | -------------------------------------------------------------------------------- /data/1ACA3465.txt: -------------------------------------------------------------------------------- 1 | pub 4096R/1ACA3465 2012-01-10 Fedora (17) 2 | 3 | -----BEGIN PGP PUBLIC KEY BLOCK----- 4 | Version: GnuPG v1.4.5 (GNU/Linux) 5 | 6 | mQINBE8MkeIBEADfn8QtElquxUAVvS8th7UnVmfkExw7jC7SVy7dGlXo5rgxqETM 7 | AZorpDIvAtKX5VMr/lUfODB6sSymh0e6EdvYQfHrpImO05F7WBq2DhRW74j1DRNu 8 | 8vohKPTsSZTEZo/mrUBDAAGtGOXcrsQxx4J2Ur73+r18ODd+v6O33YevlFmwmFYT 9 | uDcgdhxyxBdpJVES8MdxO349uP9bvrU+3KjpDDGHb/hMbY8az7lwLtBufRrAekhN 10 | 5Cg7+zm+I+wVGzgzSw0yrIh4hdVts4RKZIrl2N3VeZcCY4IrNZFd2Do6HhIwA7l/ 11 | /xpTEBTZ4BmnGP9iufUVa2h97/JmKy38rM88IovIcTSnYDG68k/NxUkC+dLriI4T 12 | BNc9kJLVo821x77WYViNXHscF8ujlf73HilfCnhEtNwViGO7x41guQrdv5k79UDf 13 | 1CylSZ+76vKXziz6uNHzIagiViNOvYHOoEH8jDNnubqFTxYXUNks5l3/byllQ0XK 14 | Oj9RarmjsMS3udRB6RCiEnzDbPge2S9gmdmY8MA3QeZ3aWoZJqygDQ0WNUOjPZ0E 15 | 80x+xbUyAK06/SCzs6bUx6GMXd5Iy5r3Gc+6LRt4WEG5r/vJEHPSj3qAoVqydsY0 16 | GjASPIQmYduCdi7Inf0w+2n+nJGPcK1k432xHD0z0kp1Q/xcOH/Tul3bcQARAQAB 17 | tCZGZWRvcmEgKDE3KSA8ZmVkb3JhQGZlZG9yYXByb2plY3Qub3JnPokCNgQTAQIA 18 | IAUCTwyR4gIbDwYLCQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJEFDpTJkayjRlKxAQ 19 | AICtQT+j8Sum1J86yBwso1wuzK2sHOXbfC1LCdQw2u6QLfKSUsCnQ5AL+oCnS491 20 | 5fjrYksT2siclLhgZX7/yF76XuYHHhRTO65NaPSCxxhN6S9zbExUPRoxFL1ay0cH 21 | p14WYI1/SGmKPcJmigV6n8+wGYl+zWlH9eiiFP/+JCxJ0ZvRg3mgT5zcPdIzTDOz 22 | 4rTE3WfH3qqxYhw2ttDPomBSdbgJw2N6bj46t8rljIDGdeKpFHYMVXpUp0gDkEoY 23 | bAiQhvZaa2F6mGMfXRdr4Phs562+tF/Qy/JaK8uafYZPHTtC16NHf87DYceLzvci 24 | W1KNBYGrEHm5NMguBlqP348FYMp+6hJDYMl38Qx3BK9bz6lW0G75tgaAZ+sxAFGs 25 | /MUcjChkF9OcF7Y7W6hY3IQb/+FgB5eNpBqfmZZ76ywpS+D0sIqxzWoILtlXdHeN 26 | eM4YiX0gvVQXwn9S89O5vWKxWYspywfgV/aXHk14O6k7oi8wInJOvgxZKEHUT4XU 27 | K7DyogL45VV9iYoWYIym2L17VBnINE/Kwmc/81nYigE0tTOwaR+qMFBSRlkOA4+X 28 | ZlIvb5Cft7CdC183FYLIM+B6xNSKE/OhavHZsRJrLZC1aAP8MNh8Cy7Jqrn1/Qjj 29 | 6sncrqaj/Yis4yAaINk4MrnbImN2MwzU70q0eR3kA6PY 30 | =3+4G 31 | -----END PGP PUBLIC KEY BLOCK----- 32 | -------------------------------------------------------------------------------- /data/f21541eb.txt: -------------------------------------------------------------------------------- 1 | 4096R/F21541EB 2009-02-24 Red Hat, Inc. (beta key 2) 2 | 3 | -----BEGIN PGP PUBLIC KEY BLOCK----- 4 | Version: GnuPG v1.2.6 (GNU/Linux) 5 | 6 | mQINBEmkAzABEAC2/c7bP1lHQ3XScxbIk0LQWe1YOiibQBRLwf8Si5PktgtuPibT 7 | kKpZjw8p4D+fM7jD1WUzUE0X7tXg2l/eUlMM4dw6XJAQ1AmEOtlwSg7rrMtTvM0A 8 | BEtI7Km6fC6sU6RtBMdcqD1cH/6dbsfh8muznVA7UlX+PRBHVzdWzj6y8h84dBjo 9 | gzcbYu9Hezqgj/lLzicqsSZPz9UdXiRTRAIhp8V30BD8uRaaa0KDDnD6IzJv3D9P 10 | xQWbFM4Z12GN9LyeZqmD7bpKzZmXG/3drvfXVisXaXp3M07t3NlBa3Dt8NFIKZ0D 11 | FRXBz5bvzxRVmdH6DtkDWXDPOt+Wdm1rZrCOrySFpBZQRpHw12eo1M1lirANIov7 12 | Z+V1Qh/aBxj5EUu32u9ZpjAPPNtQF6F/KjaoHHHmEQAuj4DLex4LY646Hv1rcv2i 13 | QFuCdvLKQGSiFBrfZH0j/IX3/0JXQlZzb3MuMFPxLXGAoAV9UP/Sw/WTmAuTzFVm 14 | G13UYFeMwrToOiqcX2VcK0aC1FCcTP2z4JW3PsWvU8rUDRUYfoXovc7eg4Vn5wHt 15 | 0NBYsNhYiAAf320AUIHzQZYi38JgVwuJfFu43tJZE4Vig++RQq6tsEx9Ftz3EwRR 16 | fJ9z9mEvEiieZm+vbOvMvIuimFVPSCmLH+bI649K8eZlVRWsx3EXCVb0nQARAQAB 17 | tDBSZWQgSGF0LCBJbmMuIChiZXRhIGtleSAyKSA8c2VjdXJpdHlAcmVkaGF0LmNv 18 | bT6JAjYEEwECACAFAkpSM+cCGwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRCT 19 | ioDK8hVB6/9tEAC0+KmzeKceXQ/GTUoU6jy9vtkFCFrmv+c7ol4XpdTt0QhqBOwy 20 | 6m2mKWwmm8KfYfy0cADQ4y/EcoXl7FtFBwYmkCuEQGXhTDn9DvVjhooIq59LEMBQ 21 | OW879RwwzRIZ8ebbjMUjDPF5MfPQqP2LBu9N4KvXlZp4voykwuuaJ+cbsKZR6pZ6 22 | 0RQKPHKP+NgUFC0fff7XY9cuOZZWFAeKRhLN2K7bnRHKxp+kELWb6R9ZfrYwZjWc 23 | MIPbTd1khE53L4NTfpWfAnJRtkPSDOKEGVlVLtLq4HEAxQt07kbslqISRWyXER3u 24 | QOJj64D1ZiIMz6t6uZ424VE4ry9rBR0Jz55cMMx5O/ni9x3xzFUgH8Su2yM0r3jE 25 | Rf24+tbOaPf7tebyx4OKe+JW95hNVstWUDyGbs6K9qGfI/pICuO1nMMFTo6GqzQ6 26 | DwLZvJ9QdXo7ujEtySZnfu42aycaQ9ZLC2DOCQCUBY350Hx6FLW3O546TAvpTfk0 27 | B6x+DV7mJQH7MGmRXQsE7TLBJKjq28Cn4tVp04PmybQyTxZdGA/8zY6pPl6xyVMH 28 | V68hSBKEVT/rlouOHuxfdmZva1DhVvUC6Xj7+iTMTVJUAq/4Uyn31P1OJmA2a0PT 29 | CAqWkbJSgKFccsjPoTbLyxhuMSNkEZFHvlZrSK9vnPzmfiRH0Orx3wYpMQ== 30 | =21pb 31 | -----END PGP PUBLIC KEY BLOCK----- 32 | -------------------------------------------------------------------------------- /data/fd431d51.txt: -------------------------------------------------------------------------------- 1 | pub 4096R/FD431D51 2009-10-22 2 | Key fingerprint = 567E 347A D004 4ADE 55BA 8A5F 199E 2F91 FD43 1D51 3 | uid Red Hat, Inc. (release key 2) 4 | 5 | -----BEGIN PGP PUBLIC KEY BLOCK----- 6 | Version: GnuPG v1.4.5 (GNU/Linux) 7 | 8 | mQINBErgSTsBEACh2A4b0O9t+vzC9VrVtL1AKvUWi9OPCjkvR7Xd8DtJxeeMZ5eF 9 | 0HtzIG58qDRybwUe89FZprB1ffuUKzdE+HcL3FbNWSSOXVjZIersdXyH3NvnLLLF 10 | 0DNRB2ix3bXG9Rh/RXpFsNxDp2CEMdUvbYCzE79K1EnUTVh1L0Of023FtPSZXX0c 11 | u7Pb5DI5lX5YeoXO6RoodrIGYJsVBQWnrWw4xNTconUfNPk0EGZtEnzvH2zyPoJh 12 | XGF+Ncu9XwbalnYde10OCvSWAZ5zTCpoLMTvQjWpbCdWXJzCm6G+/hx9upke546H 13 | 5IjtYm4dTIVTnc3wvDiODgBKRzOl9rEOCIgOuGtDxRxcQkjrC+xvg5Vkqn7vBUyW 14 | 9pHedOU+PoF3DGOM+dqv+eNKBvh9YF9ugFAQBkcG7viZgvGEMGGUpzNgN7XnS1gj 15 | /DPo9mZESOYnKceve2tIC87p2hqjrxOHuI7fkZYeNIcAoa83rBltFXaBDYhWAKS1 16 | PcXS1/7JzP0ky7d0L6Xbu/If5kqWQpKwUInXtySRkuraVfuK3Bpa+X1XecWi24JY 17 | HVtlNX025xx1ewVzGNCTlWn1skQN2OOoQTV4C8/qFpTW6DTWYurd4+fE0OJFJZQF 18 | buhfXYwmRlVOgN5i77NTIJZJQfYFj38c/Iv5vZBPokO6mffrOTv3MHWVgQARAQAB 19 | tDNSZWQgSGF0LCBJbmMuIChyZWxlYXNlIGtleSAyKSA8c2VjdXJpdHlAcmVkaGF0 20 | LmNvbT6JAjYEEwECACAFAkrgSTsCGwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAK 21 | CRAZni+R/UMdUWzpD/9s5SFR/ZF3yjY5VLUFLMXIKUztNN3oc45fyLdTI3+UClKC 22 | 2tEruzYjqNHhqAEXa2sN1fMrsuKec61Ll2NfvJjkLKDvgVIh7kM7aslNYVOP6BTf 23 | C/JJ7/ufz3UZmyViH/WDl+AYdgk3JqCIO5w5ryrC9IyBzYv2m0HqYbWfphY3uHw5 24 | un3ndLJcu8+BGP5F+ONQEGl+DRH58Il9Jp3HwbRa7dvkPgEhfFR+1hI+Btta2C7E 25 | 0/2NKzCxZw7Lx3PBRcU92YKyaEihfy/aQKZCAuyfKiMvsmzs+4poIX7I9NQCJpyE 26 | IGfINoZ7VxqHwRn/d5mw2MZTJjbzSf+Um9YJyA0iEEyD6qjriWQRbuxpQXmlAJbh 27 | 8okZ4gbVFv1F8MzK+4R8VvWJ0XxgtikSo72fHjwha7MAjqFnOq6eo6fEC/75g3NL 28 | Ght5VdpGuHk0vbdENHMC8wS99e5qXGNDued3hlTavDMlEAHl34q2H9nakTGRF5Ki 29 | JUfNh3DVRGhg8cMIti21njiRh7gyFI2OccATY7bBSr79JhuNwelHuxLrCFpY7V25 30 | OFktl15jZJaMxuQBqYdBgSay2G0U6D1+7VsWufpzd/Abx1/c3oi9ZaJvW22kAggq 31 | dzdA27UUYjWvx42w9menJwh/0jeQcTecIUd0d0rFcw/c1pvgMMl/Q73yzKgKYw== 32 | =zbHE 33 | -----END PGP PUBLIC KEY BLOCK----- 34 | 35 | -------------------------------------------------------------------------------- /static/assets/js/bootstrap-transition.js: -------------------------------------------------------------------------------- 1 | /* =================================================== 2 | * bootstrap-transition.js v2.3.1 3 | * http://twitter.github.com/bootstrap/javascript.html#transitions 4 | * =================================================== 5 | * Copyright 2012 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ========================================================== */ 19 | 20 | 21 | !function ($) { 22 | 23 | "use strict"; // jshint ;_; 24 | 25 | 26 | /* CSS TRANSITION SUPPORT (http://www.modernizr.com/) 27 | * ======================================================= */ 28 | 29 | $(function () { 30 | 31 | $.support.transition = (function () { 32 | 33 | var transitionEnd = (function () { 34 | 35 | var el = document.createElement('bootstrap') 36 | , transEndEventNames = { 37 | 'WebkitTransition' : 'webkitTransitionEnd' 38 | , 'MozTransition' : 'transitionend' 39 | , 'OTransition' : 'oTransitionEnd otransitionend' 40 | , 'transition' : 'transitionend' 41 | } 42 | , name 43 | 44 | for (name in transEndEventNames){ 45 | if (el.style[name] !== undefined) { 46 | return transEndEventNames[name] 47 | } 48 | } 49 | 50 | }()) 51 | 52 | return transitionEnd && { 53 | end: transitionEnd 54 | } 55 | 56 | })() 57 | 58 | }) 59 | 60 | }(window.jQuery); -------------------------------------------------------------------------------- /tasks.py: -------------------------------------------------------------------------------- 1 | from celery import Celery 2 | import majdoor 3 | import scanner 4 | import os 5 | import pymongo 6 | import json 7 | from pymongo import Connection 8 | import subprocess 9 | 10 | celery = Celery('tasks', broker='mongodb://localhost/queue') 11 | 12 | @celery.task 13 | def add(x, y): 14 | return x + y 15 | 16 | @celery.task 17 | def process(id): 18 | stuff = majdoor.fetch_koji_build(id) 19 | if stuff and len(stuff) == 3: 20 | package, nvr, urls = stuff 21 | else: 22 | print "??? majdoor skipped / failed", id 23 | return "OK" 24 | 25 | if not urls: 26 | return 27 | for arch, url in urls: 28 | basename = url.split('/')[-1] 29 | path = os.path.join("cache", nvr, basename) 30 | 31 | if path.endswith(".rpm") and not \ 32 | path.endswith(".src.rpm") and \ 33 | not "-debuginfo-" in path: 34 | output = scanner.analyze(path) 35 | print output 36 | 37 | connection = Connection() 38 | db = connection.test_database 39 | analysis = db.analysis 40 | analysis.insert(json.loads(output)) 41 | connection.close() 42 | 43 | # do rpmgrill stuff, spawn as we don't know how rpmgrill affets our env. 44 | basepath = os.path.join(os.path.realpath("cache"), nvr) 45 | print "Running rpmgrill on", basepath 46 | p = subprocess.Popen("./invoke_rpmgrill.sh %s" % basepath, 47 | stderr=subprocess.PIPE, shell=True) 48 | _, err = p.communicate() 49 | 50 | output = os.path.join(os.path.realpath("cache"), nvr, "rpmgrill.json") 51 | if not os.path.exists(output): 52 | print "!!! rpmgrill failed for", basepath 53 | print err 54 | else: 55 | with open(output) as f: 56 | data = f.read() 57 | # we store rpmgrill.json in a database 58 | connection = Connection() 59 | db = connection.test_database 60 | rpmgrill = db.rpmgrill 61 | entry = { "nvr" : nvr, "output" : data, "package" : package } 62 | rpmgrill.insert(entry) 63 | print "!!!", err 64 | 65 | return "OK" 66 | 67 | -------------------------------------------------------------------------------- /scripts/exposed-list.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """Output a list of "exposed" programs which are not hardened.""" 4 | 5 | import sys 6 | 7 | try: 8 | import pymongo 9 | except ImportError: 10 | print >> sys.stderr, "Please install pymongo package" 11 | sys.exit(-1) 12 | 13 | import subprocess 14 | import os 15 | import json 16 | import stat 17 | from pymongo import Connection 18 | 19 | groups = {} 20 | connection = Connection() 21 | 22 | def get_groups(): 23 | global groups 24 | for build in analysis.find(): 25 | groups[build["group"]] = groups.get(build["group"], 0) + 1 26 | 27 | checklist = ["Applications/CGI", "Network/Daemons", "Applications/Communications", "System", "Applications/Internet", "System Environment/Base", "System Environment/Daemons", "Applications/Databases"] 28 | 29 | def privileged_dangerous(): 30 | for item in checklist: 31 | print "\n" + item + "\n" 32 | for build in analysis.find(): 33 | for f in build["files"]: 34 | dangerous = False 35 | mode = f["mode"] 36 | if not build["group"] in item: 37 | continue 38 | if f.get("directory", False): 39 | #print "%s,%s,%s,directory,%s" % (build["package"], build["build"], f["name"], oct(f["mode"])) 40 | continue 41 | if not f.get("PIE", None): 42 | # print >> sys.stderr, "%s is not a an ELF file!" % f["name"] 43 | continue 44 | if f["PIE"] == off or f["NX"] == off or f["CANARY"] == off or f["RELRO"] == off: 45 | print "%s,%s,%s,%s,%s,%s,%s,%s" % (build["package"], build["build"], f["name"], f["NX"], f["CANARY"], f["RELRO"], f["PIE"], oct(f["mode"])) 46 | 47 | 48 | import argparse 49 | 50 | parser = argparse.ArgumentParser() 51 | 52 | parser.add_argument('-v', action="store_true", dest="verbose", help="enable verbose mode") 53 | parser.add_argument('-f', action="store", dest="prune_file", help="enable filter mode") 54 | 55 | results = parser.parse_args() 56 | 57 | off = "Disabled" 58 | verbose = results.verbose 59 | 60 | db = connection.test_database 61 | collection = db.test_collection 62 | 63 | analysis = db.analysis 64 | 65 | get_groups() 66 | 67 | privileged_dangerous() 68 | -------------------------------------------------------------------------------- /static/assets/css/jquery.terminal.css: -------------------------------------------------------------------------------- 1 | .terminal .terminal-output .format, .terminal .cmd .format, 2 | .terminal .cmd .prompt, .terminal .cmd .prompt div, .terminal .terminal-output div div{ 3 | display: inline-block; 4 | } 5 | .terminal .clipboard { 6 | position: absolute; 7 | bottom: 0; 8 | left: 0; 9 | opacity: 0.01; 10 | filter: alpha(opacity = 0.01); 11 | filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0.01); 12 | width: 2px; 13 | } 14 | .cmd > .clipboard { 15 | position: fixed; 16 | } 17 | .terminal { 18 | padding: 10px; 19 | position: relative; 20 | overflow: auto; 21 | } 22 | .cmd { 23 | padding: 0; 24 | margin: 0; 25 | height: 1.3em; 26 | margin-top: 3px; 27 | } 28 | .terminal .terminal-output div div, .terminal .prompt { 29 | display: block; 30 | line-height: 14px; 31 | height: auto; 32 | } 33 | .terminal .prompt { 34 | float: left; 35 | } 36 | 37 | .terminal { 38 | font-family: FreeMono, monospace; 39 | color: #aaa; 40 | background-color: #000; 41 | font-size: 12px; 42 | line-height: 14px; 43 | } 44 | .terminal-output > div { 45 | padding-top: 3px; 46 | } 47 | .terminal .terminal-output div span { 48 | display: inline-block; 49 | } 50 | .terminal .cmd span { 51 | float: left; 52 | /*display: inline-block; */ 53 | } 54 | .terminal .cmd span.inverted { 55 | background-color: #aaa; 56 | color: #000; 57 | } 58 | .terminal .terminal-output div div::-moz-selection, 59 | .terminal .terminal-output div span::-moz-selection, 60 | .terminal .terminal-output div div a::-moz-selection { 61 | background-color: #aaa; 62 | color: #000; 63 | } 64 | .terminal .terminal-output div div::selection, 65 | .terminal .terminal-output div div a::selection, 66 | .terminal .terminal-output div span::selection, 67 | .terminal .cmd > span::selection, 68 | .terminal .prompt span::selection { 69 | background-color: #aaa; 70 | color: #000; 71 | } 72 | .terminal .terminal-output div.error, .terminal .terminal-output div.error div { 73 | color: red; 74 | } 75 | .tilda { 76 | position: fixed; 77 | top: 0; 78 | left: 0; 79 | width: 100%; 80 | z-index: 1100; 81 | } 82 | .clear { 83 | clear: both; 84 | } 85 | .terminal a { 86 | color: #0F60FF; 87 | } 88 | .terminal a:hover { 89 | color: red; 90 | } 91 | -------------------------------------------------------------------------------- /listener.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | import json 5 | import pprint 6 | try: 7 | import zmq 8 | except ImportError: 9 | print >> sys.stderr, "Please install python-zmq rpm package" 10 | sys.exit(-1) 11 | 12 | try: 13 | from tasks import process 14 | except ImportError: 15 | print >> sys.stderr, "Please install celery from PyPI and koji rpm package" 16 | sys.exit(-1) 17 | 18 | 19 | def listen_and_print(): 20 | # You can listen to stg at "tcp://stg.fedoraproject.org:9940" 21 | endpoint = "tcp://hub.fedoraproject.org:9940" 22 | topic1 = 'org.fedoraproject.prod.buildsys.build.state.change' 23 | topic2 = 'org.fedoraproject.prod.bodhi.update.request.stable' 24 | topic3 = 'org.fedoraproject.prod.git.receive' 25 | topic4 = 'org.fedoraproject.prod.git.lookaside.new' 26 | topic5 = 'org.fedoraproject.prod.bodhi.update.request.testing' 27 | topic6 = 'org.fedoraproject.prod.bodhi.update.request.stable' 28 | 29 | ctx = zmq.Context() 30 | s = ctx.socket(zmq.SUB) 31 | s.connect(endpoint) 32 | 33 | # s.setsockopt(zmq.SUBSCRIBE, topic6) 34 | # s.setsockopt(zmq.SUBSCRIBE, topic5) 35 | # s.setsockopt(zmq.SUBSCRIBE, topic4) 36 | s.setsockopt(zmq.SUBSCRIBE, topic3) 37 | # s.setsockopt(zmq.SUBSCRIBE, topic2) 38 | s.setsockopt(zmq.SUBSCRIBE, topic1) 39 | 40 | poller = zmq.Poller() 41 | poller.register(s, zmq.POLLIN) 42 | 43 | while True: 44 | evts = poller.poll() # This blocks until a message arrives 45 | topic, msg = s.recv_multipart() 46 | print topic 47 | if topic == topic1: 48 | data = json.loads(msg) 49 | if "msg" in data: 50 | if "build_id" in data["msg"]: 51 | state = data["msg"]["new"] 52 | bid = data["msg"]["build_id"] 53 | name = data["msg"]["name"] 54 | if state != 1: 55 | print ">>> skipping", bid, "with state", state, "and name", name 56 | continue 57 | # print data 58 | print ">>> adding", bid, "with state", state, "and name", name 59 | process.delay(bid) 60 | elif topic == topic5 or topic == topic6: 61 | print msg 62 | 63 | if __name__ == "__main__": 64 | 65 | listen_and_print() 66 | -------------------------------------------------------------------------------- /static/assets/js/html5shiv.js: -------------------------------------------------------------------------------- 1 | /* 2 | HTML5 Shiv v3.6.2pre | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed 3 | */ 4 | (function(l,f){function m(){var a=e.elements;return"string"==typeof a?a.split(" "):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag(); 5 | a.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/\w+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c("'+a+'")'})+");return n}")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement("p");d=d.getElementsByTagName("head")[0]||d.documentElement;c.innerHTML="x"; 6 | c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML="";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a");var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode|| 7 | "undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",version:"3.6.2pre",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f);if(g)return a.createDocumentFragment(); 8 | for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d> sys.stderr, "Please install pymongo package" 9 | sys.exit(-1) 10 | 11 | import subprocess 12 | import os 13 | import json 14 | import stat 15 | from pymongo import Connection 16 | 17 | off = "Disabled" 18 | on = "Enabled" 19 | partial = "Partial" 20 | 21 | # DB stuff 22 | connection = Connection() 23 | db = connection.test_database 24 | collection = db.test_collection 25 | analysis = db.analysis 26 | 27 | # RELRO tracking 28 | no_relro = 0 29 | partial_relro = 0 30 | full_relro = 0 31 | 32 | # PIE tracking 33 | no_pie = 0 34 | pie = 0 35 | 36 | # NX tracking 37 | no_nx = 0 38 | nx = 0 39 | 40 | # Stack Canary tracking 41 | no_canary = 0 42 | canary = 0 43 | 44 | # read package list 45 | total_builds = 0 46 | pkg = analysis.find() 47 | count = pkg.count() 48 | total_builds = total_builds + count 49 | for build in pkg: 50 | out = {"PIE": off, "NX" : off, "RELRO" : off, "CANARY" : off} 51 | # print "[+]", build["nvr"], build["build"] 52 | applicable = False 53 | for f in build["files"]: 54 | out["package"] = build["package"] 55 | if f.get("directory", False): 56 | continue 57 | if not f.get("PIE", False): 58 | continue 59 | applicable = True 60 | if f["PIE"] == on: 61 | out["PIE"] = on 62 | if f["NX"] == on: 63 | out["NX"] = on 64 | if f["CANARY"] == on: 65 | out["CANARY"] = on 66 | if f["RELRO"] == on: 67 | out["RELRO"] = on 68 | elif f["RELRO"] == partial: 69 | if out["RELRO"] == off: # keep the best! 70 | out["RELRO"] = partial 71 | # dirty hack 72 | if applicable: 73 | # stats stuff 74 | if out["PIE"] == on: 75 | pie = pie + 1 76 | else: 77 | no_pie = no_pie + 1 78 | if out["NX"] == on: 79 | nx = nx + 1 80 | else: 81 | print out["package"] 82 | no_nx = no_nx + 1 83 | if out["CANARY"] == on: 84 | canary = canary + 1 85 | else: 86 | no_canary = no_canary + 1 87 | if out["RELRO"] == on: 88 | full_relro = full_relro + 1 89 | elif out["RELRO"] == partial: 90 | partial_relro = partial_relro + 1 91 | else: 92 | no_relro = no_relro + 1 93 | 94 | 95 | # plotting stuff starts 96 | import subprocess 97 | 98 | with open("my.dat", "wb") as f: 99 | f.write("Enabled\tDisabled\tPartial\n") 100 | # PIE status 101 | f.write("%s\t%s\t-\n" % (canary, no_canary)) 102 | f.write("%s\t%s\t-\n" % (nx, no_nx)) 103 | f.write("%s\t%s\t%s\n" % (full_relro, no_relro, partial_relro)) 104 | f.write("%s\t%s\t-\n" % (pie, no_pie)) 105 | 106 | p = subprocess.Popen("""gnuplot -e "load 'pie.gnu'" """, shell=True) 107 | 108 | print "\n[+++*] %s total builds processed" % total_builds 109 | -------------------------------------------------------------------------------- /static/assets/js/bootstrap-button.js: -------------------------------------------------------------------------------- 1 | /* ============================================================ 2 | * bootstrap-button.js v2.3.1 3 | * http://twitter.github.com/bootstrap/javascript.html#buttons 4 | * ============================================================ 5 | * Copyright 2012 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ============================================================ */ 19 | 20 | 21 | !function ($) { 22 | 23 | "use strict"; // jshint ;_; 24 | 25 | 26 | /* BUTTON PUBLIC CLASS DEFINITION 27 | * ============================== */ 28 | 29 | var Button = function (element, options) { 30 | this.$element = $(element) 31 | this.options = $.extend({}, $.fn.button.defaults, options) 32 | } 33 | 34 | Button.prototype.setState = function (state) { 35 | var d = 'disabled' 36 | , $el = this.$element 37 | , data = $el.data() 38 | , val = $el.is('input') ? 'val' : 'html' 39 | 40 | state = state + 'Text' 41 | data.resetText || $el.data('resetText', $el[val]()) 42 | 43 | $el[val](data[state] || this.options[state]) 44 | 45 | // push to event loop to allow forms to submit 46 | setTimeout(function () { 47 | state == 'loadingText' ? 48 | $el.addClass(d).attr(d, d) : 49 | $el.removeClass(d).removeAttr(d) 50 | }, 0) 51 | } 52 | 53 | Button.prototype.toggle = function () { 54 | var $parent = this.$element.closest('[data-toggle="buttons-radio"]') 55 | 56 | $parent && $parent 57 | .find('.active') 58 | .removeClass('active') 59 | 60 | this.$element.toggleClass('active') 61 | } 62 | 63 | 64 | /* BUTTON PLUGIN DEFINITION 65 | * ======================== */ 66 | 67 | var old = $.fn.button 68 | 69 | $.fn.button = function (option) { 70 | return this.each(function () { 71 | var $this = $(this) 72 | , data = $this.data('button') 73 | , options = typeof option == 'object' && option 74 | if (!data) $this.data('button', (data = new Button(this, options))) 75 | if (option == 'toggle') data.toggle() 76 | else if (option) data.setState(option) 77 | }) 78 | } 79 | 80 | $.fn.button.defaults = { 81 | loadingText: 'loading...' 82 | } 83 | 84 | $.fn.button.Constructor = Button 85 | 86 | 87 | /* BUTTON NO CONFLICT 88 | * ================== */ 89 | 90 | $.fn.button.noConflict = function () { 91 | $.fn.button = old 92 | return this 93 | } 94 | 95 | 96 | /* BUTTON DATA-API 97 | * =============== */ 98 | 99 | $(document).on('click.button.data-api', '[data-toggle^=button]', function (e) { 100 | var $btn = $(e.target) 101 | if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') 102 | $btn.button('toggle') 103 | }) 104 | 105 | }(window.jQuery); -------------------------------------------------------------------------------- /rpm-shell.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import sys 5 | import json 6 | from yum.mdparser import MDParser 7 | from yum import repoMDObject 8 | import cmd 9 | 10 | blurb = """ 11 | $ pip install requests 12 | """ 13 | 14 | try: 15 | import requests 16 | except ImportError as exc: 17 | print(exc) 18 | print("Dependencies not met, use following steps!") 19 | print(blurb) 20 | sys.exit(-1) 21 | 22 | 23 | BASE_URL = "http://dl.fedoraproject.org/pub/fedora/linux/development/rawhide/x86_64/os/" 24 | database = {} 25 | sections = {} 26 | 27 | from scanner import analyze 28 | 29 | 30 | def fetch(url, destination): 31 | r = requests.get(url) 32 | with open(destination, "wb") as f: 33 | f.write(r.content) 34 | 35 | 36 | def load(): 37 | repomdpath = os.path.join(os.path.dirname(os.path.realpath(__file__)), 38 | "data", "repodata", "repomd.xml") 39 | rmdo = repoMDObject.RepoMD("rawhide", repomdpath) 40 | plocation = rmdo.repoData["primary"].location[1] 41 | plocation = os.path.join(os.path.dirname(os.path.realpath(__file__)), 42 | "data", plocation) 43 | parser = MDParser(plocation) 44 | for pkg in parser: 45 | database[pkg["name"]] = dict(pkg) 46 | 47 | print 'read: %s packages (%s suggested)' % (parser.count, parser.total) 48 | 49 | 50 | class Fedora(cmd.Cmd): 51 | def do_search(self, package): 52 | for key in database.keys(): 53 | if package in key: 54 | print(key) 55 | 56 | def do_analyze(self, package): 57 | try: 58 | filename = os.path.basename(database[package]["location_href"]) 59 | except: 60 | print("package not found!") 61 | return 62 | 63 | destination = os.path.join(os.path.dirname(os.path.realpath(__file__)), 64 | "data", ".cache", filename) 65 | url = BASE_URL + database[package]["location_href"] 66 | if not os.path.exists(destination): 67 | print(url, "=>", destination) 68 | fetch(url, destination) 69 | data = json.loads(analyze(destination, show_errors=False)) 70 | print json.dumps(data, sort_keys=True, indent=4, 71 | separators=(',', ': ')) 72 | 73 | def do_describe(self, package): 74 | print "description:", database[package]["description"] 75 | print "group:", database[package]["group"] 76 | print "ver + rel:", database[package]["ver"], database[package]["rel"] 77 | 78 | def do_dump(self, line): 79 | print(database.keys()) 80 | 81 | def do_about(self, line): 82 | print("rpm-shell v0.01 ;)") 83 | 84 | def do_sections(self, line=None): 85 | for key in database.keys(): 86 | v = database[key] 87 | l = sections.get(v["group"], []) 88 | l.append(key) 89 | sections[v["group"]] = l 90 | print(sections.keys()) 91 | 92 | def do_section(self, line): 93 | self.do_sections() 94 | for key in sections.keys(): 95 | if line in key: 96 | print("List for", key, ":", sections[key]) 97 | 98 | def preloop(self): 99 | print("Loading database ...") 100 | load() 101 | 102 | def do_EOF(self, line): 103 | return True 104 | 105 | 106 | if __name__ == "__main__": 107 | Fedora().cmdloop() 108 | -------------------------------------------------------------------------------- /chart-er.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | 5 | try: 6 | import pymongo 7 | except ImportError: 8 | print >> sys.stderr, "Please install pymongo package" 9 | sys.exit(-1) 10 | 11 | import subprocess 12 | import os 13 | import json 14 | import stat 15 | from pymongo import Connection 16 | 17 | off = "Disabled" 18 | on = "Enabled" 19 | partial = "Partial" 20 | 21 | # DB stuff 22 | connection = Connection() 23 | db = connection.test_database 24 | collection = db.test_collection 25 | analysis = db.analysis 26 | 27 | # RELRO tracking 28 | no_relro = 0 29 | partial_relro = 0 30 | full_relro = 0 31 | 32 | # PIE tracking 33 | no_pie = 0 34 | pie = 0 35 | 36 | # NX tracking 37 | no_nx = 0 38 | nx = 0 39 | 40 | # Stack Canary tracking 41 | no_canary = 0 42 | canary = 0 43 | 44 | # read package list 45 | total_builds = 0 46 | with open(sys.argv[1], "rb") as f: 47 | for item in f.readlines(): 48 | item = item.strip() 49 | pkg = analysis.find({"package" : item}) 50 | count = pkg.count() 51 | total_builds = total_builds + count 52 | for build in pkg: 53 | out = {"PIE": off, "NX" : off, "RELRO" : off, "CANARY" : off} 54 | print "[+]", build["nvr"], build["build"] 55 | applicable = False 56 | for f in build["files"]: 57 | out["package"] = build["package"] 58 | if f.get("directory", False): 59 | continue 60 | if not f.get("PIE", False): 61 | continue 62 | applicable = True 63 | if f["PIE"] == on: 64 | out["PIE"] = on 65 | if f["NX"] == on: 66 | out["NX"] = on 67 | if f["CANARY"] == on: 68 | out["CANARY"] = on 69 | if f["RELRO"] == on: 70 | out["RELRO"] = on 71 | elif f["RELRO"] == partial: 72 | if out["RELRO"] == off: # keep the best! 73 | out["RELRO"] = partial 74 | # dirty hack 75 | if applicable: 76 | # stats stuff 77 | if out["PIE"] == on: 78 | pie = pie + 1 79 | else: 80 | no_pie = no_pie + 1 81 | if out["NX"] == on: 82 | nx = nx + 1 83 | else: 84 | no_nx = no_nx + 1 85 | if out["CANARY"] == on: 86 | canary = canary + 1 87 | else: 88 | no_canary = no_canary + 1 89 | if out["RELRO"] == on: 90 | full_relro = full_relro + 1 91 | elif out["RELRO"] == partial: 92 | partial_relro = partial_relro + 1 93 | else: 94 | no_relro = no_relro + 1 95 | 96 | 97 | # plotting stuff starts 98 | import subprocess 99 | 100 | with open("my.dat", "wb") as f: 101 | f.write("Enabled\tDisabled\tPartial\n") 102 | # PIE status 103 | f.write("%s\t%s\t-\n" % (canary, no_canary)) 104 | f.write("%s\t%s\t-\n" % (nx, no_nx)) 105 | f.write("%s\t%s\t%s\n" % (full_relro, no_relro, partial_relro)) 106 | f.write("%s\t%s\t-\n" % (pie, no_pie)) 107 | 108 | p = subprocess.Popen("""gnuplot -e "load 'pie.gnu'" """, shell=True) 109 | 110 | print "\n[+++*] %s total builds processed" % total_builds 111 | -------------------------------------------------------------------------------- /static/assets/js/bootstrap-popover.js: -------------------------------------------------------------------------------- 1 | /* =========================================================== 2 | * bootstrap-popover.js v2.3.1 3 | * http://twitter.github.com/bootstrap/javascript.html#popovers 4 | * =========================================================== 5 | * Copyright 2012 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * =========================================================== */ 19 | 20 | 21 | !function ($) { 22 | 23 | "use strict"; // jshint ;_; 24 | 25 | 26 | /* POPOVER PUBLIC CLASS DEFINITION 27 | * =============================== */ 28 | 29 | var Popover = function (element, options) { 30 | this.init('popover', element, options) 31 | } 32 | 33 | 34 | /* NOTE: POPOVER EXTENDS BOOTSTRAP-TOOLTIP.js 35 | ========================================== */ 36 | 37 | Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, { 38 | 39 | constructor: Popover 40 | 41 | , setContent: function () { 42 | var $tip = this.tip() 43 | , title = this.getTitle() 44 | , content = this.getContent() 45 | 46 | $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title) 47 | $tip.find('.popover-content')[this.options.html ? 'html' : 'text'](content) 48 | 49 | $tip.removeClass('fade top bottom left right in') 50 | } 51 | 52 | , hasContent: function () { 53 | return this.getTitle() || this.getContent() 54 | } 55 | 56 | , getContent: function () { 57 | var content 58 | , $e = this.$element 59 | , o = this.options 60 | 61 | content = (typeof o.content == 'function' ? o.content.call($e[0]) : o.content) 62 | || $e.attr('data-content') 63 | 64 | return content 65 | } 66 | 67 | , tip: function () { 68 | if (!this.$tip) { 69 | this.$tip = $(this.options.template) 70 | } 71 | return this.$tip 72 | } 73 | 74 | , destroy: function () { 75 | this.hide().$element.off('.' + this.type).removeData(this.type) 76 | } 77 | 78 | }) 79 | 80 | 81 | /* POPOVER PLUGIN DEFINITION 82 | * ======================= */ 83 | 84 | var old = $.fn.popover 85 | 86 | $.fn.popover = function (option) { 87 | return this.each(function () { 88 | var $this = $(this) 89 | , data = $this.data('popover') 90 | , options = typeof option == 'object' && option 91 | if (!data) $this.data('popover', (data = new Popover(this, options))) 92 | if (typeof option == 'string') data[option]() 93 | }) 94 | } 95 | 96 | $.fn.popover.Constructor = Popover 97 | 98 | $.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, { 99 | placement: 'right' 100 | , trigger: 'click' 101 | , content: '' 102 | , template: '

' 103 | }) 104 | 105 | 106 | /* POPOVER NO CONFLICT 107 | * =================== */ 108 | 109 | $.fn.popover.noConflict = function () { 110 | $.fn.popover = old 111 | return this 112 | } 113 | 114 | }(window.jQuery); 115 | -------------------------------------------------------------------------------- /static/assets/js/README.md: -------------------------------------------------------------------------------- 1 | ## 2.0 BOOTSTRAP JS PHILOSOPHY 2 | These are the high-level design rules which guide the development of Bootstrap's plugin apis. 3 | 4 | --- 5 | 6 | ### DATA-ATTRIBUTE API 7 | 8 | We believe you should be able to use all plugins provided by Bootstrap purely through the markup API without writing a single line of javascript. 9 | 10 | We acknowledge that this isn't always the most performant and sometimes it may be desirable to turn this functionality off altogether. Therefore, as of 2.0 we provide the ability to disable the data attribute API by unbinding all events on the body namespaced with `'data-api'`. This looks like this: 11 | 12 | $('body').off('.data-api') 13 | 14 | To target a specific plugin, just include the plugins name as a namespace along with the data-api namespace like this: 15 | 16 | $('body').off('.alert.data-api') 17 | 18 | --- 19 | 20 | ### PROGRAMMATIC API 21 | 22 | We also believe you should be able to use all plugins provided by Bootstrap purely through the JS API. 23 | 24 | All public APIs should be single, chainable methods, and return the collection acted upon. 25 | 26 | $(".btn.danger").button("toggle").addClass("fat") 27 | 28 | All methods should accept an optional options object, a string which targets a particular method, or null which initiates the default behavior: 29 | 30 | $("#myModal").modal() // initialized with defaults 31 | $("#myModal").modal({ keyboard: false }) // initialized with now keyboard 32 | $("#myModal").modal('show') // initializes and invokes show immediately afterqwe2 33 | 34 | --- 35 | 36 | ### OPTIONS 37 | 38 | Options should be sparse and add universal value. We should pick the right defaults. 39 | 40 | All plugins should have a default object which can be modified to effect all instance's default options. The defaults object should be available via `$.fn.plugin.defaults`. 41 | 42 | $.fn.modal.defaults = { … } 43 | 44 | An options definition should take the following form: 45 | 46 | *noun*: *adjective* - describes or modifies a quality of an instance 47 | 48 | examples: 49 | 50 | backdrop: true 51 | keyboard: false 52 | placement: 'top' 53 | 54 | --- 55 | 56 | ### EVENTS 57 | 58 | All events should have an infinitive and past participle form. The infinitive is fired just before an action takes place, the past participle on completion of the action. 59 | 60 | show | shown 61 | hide | hidden 62 | 63 | --- 64 | 65 | ### CONSTRUCTORS 66 | 67 | Each plugin should expose it's raw constructor on a `Constructor` property -- accessed in the following way: 68 | 69 | 70 | $.fn.popover.Constructor 71 | 72 | --- 73 | 74 | ### DATA ACCESSOR 75 | 76 | Each plugin stores a copy of the invoked class on an object. This class instance can be accessed directly through jQuery's data API like this: 77 | 78 | $('[rel=popover]').data('popover') instanceof $.fn.popover.Constructor 79 | 80 | --- 81 | 82 | ### DATA ATTRIBUTES 83 | 84 | Data attributes should take the following form: 85 | 86 | - data-{{verb}}={{plugin}} - defines main interaction 87 | - data-target || href^=# - defined on "control" element (if element controls an element other than self) 88 | - data-{{noun}} - defines class instance options 89 | 90 | examples: 91 | 92 | // control other targets 93 | data-toggle="modal" data-target="#foo" 94 | data-toggle="collapse" data-target="#foo" data-parent="#bar" 95 | 96 | // defined on element they control 97 | data-spy="scroll" 98 | 99 | data-dismiss="modal" 100 | data-dismiss="alert" 101 | 102 | data-toggle="dropdown" 103 | 104 | data-toggle="button" 105 | data-toggle="buttons-checkbox" 106 | data-toggle="buttons-radio" -------------------------------------------------------------------------------- /data/RPM-GPG-KEY-fedora-19-secondary: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP PUBLIC KEY BLOCK----- 2 | Version: GnuPG v1.4.11 (GNU/Linux) 3 | 4 | mQINBFDSg/8BEACyQvgSivrn6IMAPvAPzSQi873WdiIiORZoE3M42yGwnm48H8W1 5 | Iiui2aRrogEhgw5HzzKI7NWMN7PY2wyIglN4CX9WeiSRdSPGBkNyNtJMfU4igujQ 6 | bMMV/hHhDyP0uTOIzyqXqWNHJ12gcg+97ML2pr5LHobiWn/GhF2QuNMBC5m7mw9G 7 | nNoaVItcEX1rxdyktb0bZAPfSLSDfzCetkrOfHS0uuUwnADTrO2hcVBUQvvi4yYi 8 | iHx5vD3J+nTFpidKBCkShtoRXaYwrkdm+TnUemxGjGtRj6tAXYSsEz3Hvk4AIthp 9 | PNbvzhpVvnrRnymUyurN7d+lcMgr3KE3VwZmDSjfVW9DKVXlWhSEHl8+zcearQsJ 10 | cefygt9WmV+Tj9IdIn9xqPgeUeOEwRCdF/VYBkG9kOedLgd9VZoO5iF3AyCxOMuk 11 | Sf66iNZIA9elIkIusV+C3mQ39ujcd4Cfwi931doGkoaxKM2Z1ShcrB4b2ySpJ6/Y 12 | YPPLUBAtVa5UzmU77TqE4T4epAa600nTeTFplbTm2DM4Xv13OEfUfoEU/8cDP7e3 13 | GfQp+IBEHIWmO8W3/tkywzZ70EJE/4NSiaW+a37L9PLP3awuilBUA6OvOe4cmlvp 14 | mWq6uLlTdyxNtMGP70+OmZ6xg2/giTt+rJiqKuUPFZBYTIainMQuBFIc1wARAQAB 15 | tDBGZWRvcmEgU2Vjb25kYXJ5ICgxOSkgPGZlZG9yYUBmZWRvcmFwcm9qZWN0Lm9y 16 | Zz6JAjgEEwECACIFAlDSg/8CGw8GCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJ 17 | EAVi62+6CUBobnEQAJpp7iMUf5s6gi8mnXCHX8BETjQDyUCmsWRY1J4m/VeeNW3O 18 | 8zVSj5AFmlayd2koiNmTpsLqUWlFf/tULCXcS0Bmwjd+Yw1UpLV9lz2nUXiybX7L 19 | IoD9cR1uw/qLHitsfCRXWOyvedAuFrurXskUh7VHe+YRRKMd40fekWca5mY7YYM8 20 | iR+0y4RwqN6Ax5HwdCril8621vxI0HEIqCVhU47K8gWxNWnmirh1qKVmel3gs6sw 21 | +vQpMgbxXR5ifubEMENIsP3LvPFathMm5sg8di3EtEiV9b5y1MxumEZXe6LfBI9m 22 | xOQUCFP0ni5+e4OeJ9XUdFuMjOfsVQlqSI7V9JmaE8Alwl/0S9rd5t2xEPBDfcYl 23 | 2f6vyIpPGnO/YkYd89ExenlmKHuz7cGpL9ivN0bRopAsGAFxIQSEQLyqH1LsM8E5 24 | 0xKEHG2BZTkiegRUnUuSwicQG2gD8QHAQU5TUA4Ct/nt47t5EBLk6zWLeKJKjjcQ 25 | m4GXxSQtpB1oY2ykegJLkaumR2OGt+dKJt3yo/Qlr/6CG+gMAyYsqbNntXqKHCG9 26 | h8zdWt8nf2oicqbVQQpCrySB8NHcHBmTy8++7UoM0QEiBztg95onjnY8LPIkW1mN 27 | Y0OruSi/sly23S/QHcx9Qp2QYcS9cTby/rvTeQIQnIIfpKPG/RKxNYJw5LB7uQQN 28 | BFDSg/8QEACO2KjO2g2cwtM5sCieboVyhqIwAQBDX+Lm3fm8ay+M9pgC2gpfjb1g 29 | qX8+zro9NMIn4xFvlML+oe6CCzO9g9Eg9gMojvW0z2XNRMS0oCtb2DI9fmEn00YB 30 | FrPaij9pXgbmlWnRX/6KsM651qWPKf/CKquitrOpcgztZOq2QvNznO0iu9tDXwKa 31 | evnGXsqUrez3cWBBq7f/NaZRvky2yoQ9R02fTPYur79viuMTe3Cdc6MWNwSQkwbk 32 | nNalbRsisJThO/9+KGf6u6NvhqimdLMhXzkD02oOw7nw/5HNh/j7eeJvgU0Iwr8A 33 | HHo/kOqG17w+VT3wWWJKek2HqRhiHd6dR4dujUlgnbmmc2m/iF+CKj1i+prQv6GS 34 | JLJRsJjNWSbmVuiVxVOsbboyhwtPdWs0XWGdMAQQNnjg57EM+9GQ3qH2NUr2DzdD 35 | rAv0J/Kab4TYnzHbiZ/774GYvjhZwIQr74F/WMncASDaCL+GfptIqY+nna94fIWQ 36 | /4JkdiZFUpsus5J1fQdj2qovmhsaehcGFfFZSST8LVmROaEC6qejyTtoupHdNTBg 37 | A0+SUlDsq0MZUASIzaRD5tLJc0Cz6zl2jScsmEFualmIrsuUJkVQ+hZjK6akCu+o 38 | 1Q2s7i1QZO0Ws08YcisUZR9arsLc7vMjO+x4sVZWyN1j8RwS2A6OFwADBw/+MAl9 39 | 9bbzblLa9mV2iXGJDBmUri4+DBUSTjt45VCTVlJdjfeu1NvozpfVZnCZ9UZqKTg6 40 | 5NXwPi4dHZzvkYW9zIcvgAjuJYMjnxAPOBDj/VivOJ35GOxG17Vd6lf+5wxvKtjG 41 | fO00IGgCkb/hxmMGm2vxMBZIhT71HoNESRi8LCTP8as2u5rMo073QAsEvnBLGXGU 42 | WayuN6T7Pn0tEZBMmnKQmco8fzLbKtz/9wmvDCshVpnOK/+rsOE4av5qzuwsg+5S 43 | xywUkDfa4yL6qYLSauwSQXBGdOh8qmv6vAOMrjvxxY9OPEM2iyEgIob4a26/47/7 44 | k/4bjIbzKa9nOvoBQQlyciy827U8tsL5KI5TvWEUD9igD/l8TjvR6puueWwlnBxp 45 | gxXJltA0M/C6thr/sBu2xjJbvgP5bXFQ/VJEYJaCAzeh9FWfbWrpxCdD0tjCYld3 46 | hJF1aZ+bWOZW2ii0tk186r/vBqjFeFTiGmBMBqYndmoXwSKVFC1p00f9y+NrDQth 47 | IgBIaVZ2FZuPDKBe6cLe2mslE7SLKwdArfrhj+TiL7OjDIpcncZVc8fWIBoTeeQV 48 | jKYeqrWEbBU14tLkYUElyQ1nIieKPOpRmwVsGpxRq1C50NGStqTCEdugj/pecd6W 49 | r5Z8ALFWU54DCZ15qzMM1M/Zu3+u1g9kDoveXDGJAh8EGAECAAkFAlDSg/8CGwwA 50 | CgkQBWLrb7oJQGjZwQ//RsolORqR2/ee+y1txPt6dj8Fxu4ly4LvQyhnnaqfUj9v 51 | g7nUq8UbC5tNfqFy5mII1AWm8V+jOEseKm6EQ72mVdfi3Kt5VPDz3DatMjPeOOKE 52 | 3kwN1fHKGv3YZnnM4B4VhzCmlbfmF0KM/66yh9zdGpMN6kHaE8dmT3cxCrMCQzb9 53 | pYVz+4ExH/hv3CTj6G6Zxm9o9m4fNKhW+rV3g8Yc4ROALO/WPMto5i8j6byNvh99 54 | d3k+LOg/zQ1CWU+pWEv4RrjjOYJJ2WFdKyf78fddIlDt0jiZynofYT0JoZKTc88e 55 | Cz26RNp+ybq6jT944XLzVlX26GoklZpWzh3paZBk8ZOmO1lA91StAm9aC96l46jf 56 | bNU3BfJjffHfMV5rld6Z80vk7FMep8RBKgNfPrgWTOE4UW8PkrdJ0kq0g20gqYa3 57 | 6QDenmrRciNlCdkzWeY9hPZpGgNyb4JIc04FvjgU4x4gZvBHqP45l9xbxC3zyq/1 58 | kt+09wuY2U+F6VP0Iu9ktRRrujHLy1mHqkabyYppI98ljBUjxYxh6NsIvoTBzBR/ 59 | BWGR8HrGqZ7Kq3lCwqNdGvjG2Vv/l4zG0wg54BZa5uXoed0BmHq5NBAI9JFRUIB7 60 | UKu0yZnTeU/cTLpJDdV/dsFuUXPjaMIvrFFrmi0w6W/clkrgaOYyifq4DOdn++8= 61 | =cM40 62 | -----END PGP PUBLIC KEY BLOCK----- 63 | -------------------------------------------------------------------------------- /static/assets/js/bootstrap-affix.js: -------------------------------------------------------------------------------- 1 | /* ========================================================== 2 | * bootstrap-affix.js v2.3.1 3 | * http://twitter.github.com/bootstrap/javascript.html#affix 4 | * ========================================================== 5 | * Copyright 2012 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ========================================================== */ 19 | 20 | 21 | !function ($) { 22 | 23 | "use strict"; // jshint ;_; 24 | 25 | 26 | /* AFFIX CLASS DEFINITION 27 | * ====================== */ 28 | 29 | var Affix = function (element, options) { 30 | this.options = $.extend({}, $.fn.affix.defaults, options) 31 | this.$window = $(window) 32 | .on('scroll.affix.data-api', $.proxy(this.checkPosition, this)) 33 | .on('click.affix.data-api', $.proxy(function () { setTimeout($.proxy(this.checkPosition, this), 1) }, this)) 34 | this.$element = $(element) 35 | this.checkPosition() 36 | } 37 | 38 | Affix.prototype.checkPosition = function () { 39 | if (!this.$element.is(':visible')) return 40 | 41 | var scrollHeight = $(document).height() 42 | , scrollTop = this.$window.scrollTop() 43 | , position = this.$element.offset() 44 | , offset = this.options.offset 45 | , offsetBottom = offset.bottom 46 | , offsetTop = offset.top 47 | , reset = 'affix affix-top affix-bottom' 48 | , affix 49 | 50 | if (typeof offset != 'object') offsetBottom = offsetTop = offset 51 | if (typeof offsetTop == 'function') offsetTop = offset.top() 52 | if (typeof offsetBottom == 'function') offsetBottom = offset.bottom() 53 | 54 | affix = this.unpin != null && (scrollTop + this.unpin <= position.top) ? 55 | false : offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? 56 | 'bottom' : offsetTop != null && scrollTop <= offsetTop ? 57 | 'top' : false 58 | 59 | if (this.affixed === affix) return 60 | 61 | this.affixed = affix 62 | this.unpin = affix == 'bottom' ? position.top - scrollTop : null 63 | 64 | this.$element.removeClass(reset).addClass('affix' + (affix ? '-' + affix : '')) 65 | } 66 | 67 | 68 | /* AFFIX PLUGIN DEFINITION 69 | * ======================= */ 70 | 71 | var old = $.fn.affix 72 | 73 | $.fn.affix = function (option) { 74 | return this.each(function () { 75 | var $this = $(this) 76 | , data = $this.data('affix') 77 | , options = typeof option == 'object' && option 78 | if (!data) $this.data('affix', (data = new Affix(this, options))) 79 | if (typeof option == 'string') data[option]() 80 | }) 81 | } 82 | 83 | $.fn.affix.Constructor = Affix 84 | 85 | $.fn.affix.defaults = { 86 | offset: 0 87 | } 88 | 89 | 90 | /* AFFIX NO CONFLICT 91 | * ================= */ 92 | 93 | $.fn.affix.noConflict = function () { 94 | $.fn.affix = old 95 | return this 96 | } 97 | 98 | 99 | /* AFFIX DATA-API 100 | * ============== */ 101 | 102 | $(window).on('load', function () { 103 | $('[data-spy="affix"]').each(function () { 104 | var $spy = $(this) 105 | , data = $spy.data() 106 | 107 | data.offset = data.offset || {} 108 | 109 | data.offsetBottom && (data.offset.bottom = data.offsetBottom) 110 | data.offsetTop && (data.offset.top = data.offsetTop) 111 | 112 | $spy.affix(data) 113 | }) 114 | }) 115 | 116 | 117 | }(window.jQuery); -------------------------------------------------------------------------------- /static/assets/js/bootstrap-tab.js: -------------------------------------------------------------------------------- 1 | /* ======================================================== 2 | * bootstrap-tab.js v2.3.1 3 | * http://twitter.github.com/bootstrap/javascript.html#tabs 4 | * ======================================================== 5 | * Copyright 2012 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ======================================================== */ 19 | 20 | 21 | !function ($) { 22 | 23 | "use strict"; // jshint ;_; 24 | 25 | 26 | /* TAB CLASS DEFINITION 27 | * ==================== */ 28 | 29 | var Tab = function (element) { 30 | this.element = $(element) 31 | } 32 | 33 | Tab.prototype = { 34 | 35 | constructor: Tab 36 | 37 | , show: function () { 38 | var $this = this.element 39 | , $ul = $this.closest('ul:not(.dropdown-menu)') 40 | , selector = $this.attr('data-target') 41 | , previous 42 | , $target 43 | , e 44 | 45 | if (!selector) { 46 | selector = $this.attr('href') 47 | selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 48 | } 49 | 50 | if ( $this.parent('li').hasClass('active') ) return 51 | 52 | previous = $ul.find('.active:last a')[0] 53 | 54 | e = $.Event('show', { 55 | relatedTarget: previous 56 | }) 57 | 58 | $this.trigger(e) 59 | 60 | if (e.isDefaultPrevented()) return 61 | 62 | $target = $(selector) 63 | 64 | this.activate($this.parent('li'), $ul) 65 | this.activate($target, $target.parent(), function () { 66 | $this.trigger({ 67 | type: 'shown' 68 | , relatedTarget: previous 69 | }) 70 | }) 71 | } 72 | 73 | , activate: function ( element, container, callback) { 74 | var $active = container.find('> .active') 75 | , transition = callback 76 | && $.support.transition 77 | && $active.hasClass('fade') 78 | 79 | function next() { 80 | $active 81 | .removeClass('active') 82 | .find('> .dropdown-menu > .active') 83 | .removeClass('active') 84 | 85 | element.addClass('active') 86 | 87 | if (transition) { 88 | element[0].offsetWidth // reflow for transition 89 | element.addClass('in') 90 | } else { 91 | element.removeClass('fade') 92 | } 93 | 94 | if ( element.parent('.dropdown-menu') ) { 95 | element.closest('li.dropdown').addClass('active') 96 | } 97 | 98 | callback && callback() 99 | } 100 | 101 | transition ? 102 | $active.one($.support.transition.end, next) : 103 | next() 104 | 105 | $active.removeClass('in') 106 | } 107 | } 108 | 109 | 110 | /* TAB PLUGIN DEFINITION 111 | * ===================== */ 112 | 113 | var old = $.fn.tab 114 | 115 | $.fn.tab = function ( option ) { 116 | return this.each(function () { 117 | var $this = $(this) 118 | , data = $this.data('tab') 119 | if (!data) $this.data('tab', (data = new Tab(this))) 120 | if (typeof option == 'string') data[option]() 121 | }) 122 | } 123 | 124 | $.fn.tab.Constructor = Tab 125 | 126 | 127 | /* TAB NO CONFLICT 128 | * =============== */ 129 | 130 | $.fn.tab.noConflict = function () { 131 | $.fn.tab = old 132 | return this 133 | } 134 | 135 | 136 | /* TAB DATA-API 137 | * ============ */ 138 | 139 | $(document).on('click.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) { 140 | e.preventDefault() 141 | $(this).tab('show') 142 | }) 143 | 144 | }(window.jQuery); -------------------------------------------------------------------------------- /checksecsrv.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | 5 | try: 6 | from flask import Flask 7 | from flask import Response 8 | from flask import request 9 | from flask import jsonify 10 | except ImportError: 11 | print >> sys.stderr, "Please install flask from PyPI" 12 | sys.exit(-1) 13 | 14 | import pymongo 15 | from bson.json_util import dumps 16 | import json 17 | 18 | app = Flask(__name__) 19 | app.config.from_pyfile('settings.py') 20 | 21 | # connect to the database 22 | connection = pymongo.Connection(app.config['MONGODB_HOST'], 23 | app.config['MONGODB_PORT']) 24 | 25 | collection = connection[app.config['MONGODB_DB']].analysis 26 | collection_grill = connection[app.config['MONGODB_DB']].rpmgrill 27 | 28 | @app.route("/") 29 | def home(): 30 | return ":-)" 31 | 32 | @app.route('/packages/') 33 | @app.route('/packages//') 34 | def packages(package=None): 35 | callback = request.args.get('callback', False) 36 | 37 | if not package: 38 | fltr = request.args.get('filter', "index") 39 | if fltr == "everything": 40 | ret = collection.find() 41 | else: 42 | ret = collection.distinct("package") 43 | else: 44 | spec = { 45 | "package" : package 46 | } 47 | fltr = request.args.get('fuzzy', None) 48 | if fltr: 49 | # do fuzzy matching of package names 50 | fltr = request.args.get('filter', "index") 51 | if fltr == "everything": 52 | ret = collection.find({'package': {'$regex': '%s' % package}}) 53 | else: 54 | ret = [] 55 | output = collection.find({'package': {'$regex': '%s' % package}}) 56 | for item in output: 57 | ret.append(item["package"]) 58 | else: 59 | ret = collection.find(spec) 60 | 61 | if (isinstance(ret, list) and len(ret) != 0) or \ 62 | (not isinstance(ret, list) and ret.count() != 0): 63 | output = dumps(ret, sort_keys=True, indent=4) 64 | if callback: 65 | output = str(callback) + '(' + str(output) + ')' 66 | return Response(response=output, status=200, 67 | mimetype="application/json") 68 | 69 | return Response(response=dumps([]), status=404, 70 | mimetype="application/json") 71 | 72 | @app.route('/grill/') 73 | @app.route('/grill//') 74 | def grill(package=None): 75 | callback = request.args.get('callback', False) 76 | 77 | if not package: 78 | fltr = request.args.get('filter', "index") 79 | if fltr == "everything": 80 | ret = collection_grill.find() 81 | else: 82 | ret = collection_grill.distinct("package") 83 | else: 84 | spec = { 85 | "package" : package 86 | } 87 | fltr = request.args.get('fuzzy', None) 88 | if fltr: 89 | # do fuzzy matching of package names 90 | fltr = request.args.get('filter', "index") 91 | if fltr == "everything": 92 | ret = collection_grill.find({'package': {'$regex': '%s' % package}}) 93 | else: 94 | ret = [] 95 | output = collection_grill.find({'package': {'$regex': '%s' % package}}) 96 | for item in output: 97 | ret.append(item["package"]) 98 | else: 99 | ret = collection_grill.find(spec) 100 | 101 | if (isinstance(ret, list) and len(ret) != 0) or \ 102 | (not isinstance(ret, list) and ret.count() != 0): 103 | output = [] 104 | for r in ret: 105 | entry = json.loads(r["output"]) 106 | entry["opackage"] = r["package"] 107 | entry["nvr"] = r["nvr"] 108 | output.append(entry) 109 | output = dumps(output, sort_keys=True, indent=4) 110 | if callback: 111 | output = str(callback) + '(' + str(output) + ')' 112 | return Response(response=output, status=200, 113 | mimetype="application/json") 114 | 115 | return Response(response=dumps([]), status=404, 116 | mimetype="application/json") 117 | 118 | 119 | if __name__ == "__main__": 120 | app.run(host='0.0.0.0', debug=True) 121 | -------------------------------------------------------------------------------- /scripts/badsoperms.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from checksec import process_file, Elf 4 | from elftools.common.exceptions import ELFError 5 | 6 | import sys 7 | import cStringIO 8 | 9 | try: 10 | import libarchive 11 | except ImportError: 12 | print >> sys.stderr, "Please install python-libarchive from PyPI" 13 | sys.exit(-1) 14 | 15 | try: 16 | import rpm 17 | except ImportError: 18 | print >> sys.stderr, "Please install rpm-python package" 19 | sys.exit(-1) 20 | 21 | import os 22 | import json 23 | import stat 24 | import multiprocessing 25 | import threading 26 | from collections import defaultdict 27 | 28 | # global stuff 29 | data = {} 30 | lock = threading.Lock() 31 | 32 | def analyze(rpmfile, show_errors=False, opformat="json"): 33 | """Analyse single RPM file""" 34 | if not os.path.exists(rpmfile): 35 | print >> sys.stderr, "%s doesn't exists!" % rpmfile 36 | return 37 | 38 | if not rpmfile.endswith(".rpm"): 39 | print >> sys.stderr, "skipping %s " % rpmfile 40 | return 41 | 42 | try: 43 | a = libarchive.Archive(rpmfile) 44 | except Exception, exc: 45 | print >> sys.stderr, rpmfile, str(exc) 46 | return 47 | 48 | try: 49 | ts = rpm.TransactionSet() 50 | ts.setVSFlags(rpm._RPMVSF_NOSIGNATURES) 51 | fd = os.open(rpmfile, os.O_RDONLY) 52 | h = ts.hdrFromFdno(fd) 53 | os.close(fd) 54 | except Exception, exc: 55 | print >> sys.stderr, rpmfile, str(exc) 56 | return 57 | 58 | for entry in a: 59 | directory = False 60 | size = entry.size 61 | 62 | if not entry.pathname.endswith(".so"): 63 | continue 64 | 65 | # print entry.pathname 66 | # check for executable flag 67 | if (entry.mode & 0111): 68 | print package, entry.pathname 69 | 70 | a.close() 71 | 72 | 73 | def profile_main(): 74 | # Run 'main' redirecting its output to readelfout.txt 75 | # Saves profiling information in readelf.profile 76 | PROFFILE = 'readelf.profile' 77 | import cProfile 78 | cProfile.run('main()', PROFFILE) 79 | 80 | # Dig in some profiling stats 81 | import pstats 82 | p = pstats.Stats(PROFFILE) 83 | p.sort_stats('cumulative').print_stats(200) 84 | 85 | 86 | def output_callback(result): 87 | pass 88 | 89 | def main(): 90 | if len(sys.argv) < 2: 91 | sys.stderr.write("Usage: %s " \ 92 | "[output format (csv / json)] [existing JSON file]\n" \ 93 | % sys.argv[0]) 94 | sys.exit(-1) 95 | 96 | path = sys.argv[1] 97 | 98 | if (len(sys.argv) > 2): 99 | opformat = sys.argv[2] 100 | else: 101 | opformat = "csv" 102 | 103 | parallel = True 104 | # parallel = False 105 | if parallel: 106 | p = multiprocessing.Pool(2) # FIXME add autodetection? 107 | 108 | # pruning code to make analysis faster 109 | if (len(sys.argv) > 3): 110 | with open(sys.argv[3]) as f: 111 | for line in f.readlines(): 112 | line = line.rstrip() 113 | try: 114 | build = json.loads(line) 115 | data[build["build"]] = build 116 | except Exception as exc: 117 | print(str(exc)) 118 | sys.exit(1) 119 | 120 | outputmap = {} 121 | if(os.path.isfile(path)): 122 | sys.stderr.write("Analyzing %s ...\n" % path) 123 | out = analyze(path, opformat=opformat) 124 | else: 125 | for (path, _, files) in os.walk(path): 126 | for fname in files: 127 | rpmfile = os.path.join(path, fname) 128 | #if os.path.basename(rpmfile) in data: 129 | # print >> sys.stderr, "Skipping", rpmfile 130 | # pass 131 | if parallel: 132 | outputmap[rpmfile] = p.apply_async(analyze, 133 | (rpmfile, False, opformat), 134 | callback = output_callback) 135 | else: 136 | out = analyze(path, opformat=opformat) 137 | 138 | if parallel: 139 | p.close() 140 | p.join() 141 | 142 | if __name__ == "__main__": 143 | main() 144 | # profile_main() 145 | -------------------------------------------------------------------------------- /scripts/report-generator.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """Output a list of "exposed" programs which are not hardened.""" 4 | 5 | import sys 6 | 7 | try: 8 | import pkgwat.api 9 | except ImportError: 10 | print >> sys.stderr, "Please install pkgwat package" 11 | sys.exit(-1) 12 | 13 | try: 14 | import pymongo 15 | except ImportError: 16 | print >> sys.stderr, "Please install pymongo package" 17 | sys.exit(-1) 18 | 19 | try: 20 | import xlwt 21 | except ImportError: 22 | print >> sys.stderr, "Please install xlwto package" 23 | sys.exit(-1) 24 | 25 | import subprocess 26 | import os 27 | import json 28 | import stat 29 | import csv 30 | from pymongo import Connection 31 | 32 | def get_packager(package): 33 | data = pkgwat.api.search(package) 34 | print >> sys.stderr, "Fetching info for", package 35 | fdata = data["rows"][0] 36 | return fdata.get(u"devel_owner", "?") 37 | 38 | connection = Connection() 39 | 40 | row = 2 41 | 42 | def privileged_dangerous(): 43 | global row 44 | row += 2 45 | for build in analysis.find(): 46 | 47 | # find if setuid / setgid stuff exists in this package 48 | analyze_this = False 49 | for f in build["files"]: 50 | mode = f["mode"] 51 | if (mode & stat.S_ISUID) or (mode & stat.S_ISGID): 52 | if f["PIE"] == off or f["NX"] == off or f["CANARY"] == off or f["RELRO"] == off: 53 | analyze_this = True 54 | if f["CATEGORY"] == "None": 55 | f["CATEGORY"] = "exec" 56 | 57 | daemon = build.get("daemon", False) 58 | if not daemon and not analyze_this: 59 | continue 60 | 61 | fetched = False 62 | 63 | for f in build["files"]: 64 | dangerous = False 65 | mode = f["mode"] 66 | if f.get("directory", False): 67 | continue 68 | if not f.get("PIE", None): 69 | continue 70 | category = f["CATEGORY"] 71 | if category == "None": 72 | category = "daemon" 73 | if f["PIE"] == off or f["NX"] == off or f["CANARY"] == off or f["RELRO"] == off: 74 | if not fetched: 75 | # packager = get_packager(build["package"]) 76 | packager = "Not Fetched" 77 | fetched = True 78 | output = "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s" % (build["package"], build["build"], f["name"], f["NX"], f["CANARY"], f["RELRO"], f["PIE"], oct(f["mode"]), category, packager) 79 | for col, data in enumerate(output.split(",")): 80 | if "Disabled" in data or "network-ip" in data or "network-local" in data: 81 | sheet.write(row, col, data, st) 82 | else: 83 | sheet.write(row, col, data) 84 | writer.writerow(output.split(",")) 85 | csvf.flush() 86 | row += 1 87 | 88 | # Create workbook and worksheet 89 | wbk = xlwt.Workbook() 90 | sheet = wbk.add_sheet('F19 unhardened files') 91 | st = xlwt.easyxf('pattern: pattern solid, fore_colour red;') 92 | headerst = xlwt.easyxf('pattern: pattern solid, fore_colour 22;') 93 | 94 | # write header 95 | header_fields = ['Package', 'Build', 'File', 'NX', 'CANARY', 'RELRO', 'PIE', 'mode', 'CATEGORY', 'Packager', 'Notes', 'Comments'] 96 | 97 | for col in range(0, len(header_fields)): 98 | sheet.write(0, col, header_fields[col], headerst) 99 | 100 | # hardcoded widths :( 101 | widths = [25, 35, 30, 10, 10, 8, 8, 8, 25, 25] 102 | for i in range(0, 10): 103 | sheet.col(i).width = 256 * widths[i] 104 | 105 | import argparse 106 | 107 | parser = argparse.ArgumentParser() 108 | 109 | parser.add_argument('-v', action="store_true", dest="verbose", help="enable verbose mode") 110 | parser.add_argument('-f', action="store", dest="prune_file", help="enable filter mode") 111 | 112 | results = parser.parse_args() 113 | 114 | off = "Disabled" 115 | verbose = results.verbose 116 | 117 | db = connection.test_database 118 | collection = db.test_collection 119 | 120 | analysis = db.analysis 121 | 122 | csvf = open("analysis.csv", "w") 123 | writer = csv.writer(csvf) 124 | writer.writerow(header_fields) 125 | 126 | 127 | privileged_dangerous() 128 | 129 | wbk.save('reformatted.data.xls') 130 | -------------------------------------------------------------------------------- /majdoor.py: -------------------------------------------------------------------------------- 1 | import koji 2 | import urlgrabber 3 | import urlgrabber.progress 4 | import os 5 | import re 6 | 7 | # these are fixed 8 | topurl = 'http://kojipkgs.fedoraproject.org' 9 | server = 'http://koji.fedoraproject.org/kojihub' 10 | work_url = 'http://kojipkgs.fedoraproject.org/work' 11 | lookup = {'i386' : 'i686'} 12 | 13 | # this one is not 14 | build_target = "f19" 15 | 16 | def download_url(package, nvr, urls): 17 | for arch, url in urls: 18 | arch = lookup.get(arch, arch) 19 | basename = url.split('/')[-1] 20 | 21 | # log files are special 22 | if basename.endswith(".log"): 23 | basepath = os.path.join("cache", nvr, arch) 24 | else: 25 | basepath = os.path.join("cache", nvr) 26 | path = os.path.join(basepath, basename) 27 | print "[*]", path 28 | try: 29 | os.makedirs(basepath) 30 | except: 31 | pass 32 | 33 | # fetch stuff 34 | if os.path.exists(path): 35 | continue 36 | prog_meter = urlgrabber.progress.TextMeter() 37 | urlgrabber.grabber.urlgrab(url, path, progress_obj=prog_meter) 38 | 39 | def fetch_koji_build(build): 40 | """ 41 | build ==> buildID or NVR 42 | """ 43 | 44 | if build.isdigit(): 45 | build = int(build) 46 | 47 | urls = [] # output 48 | 49 | pathinfo = koji.PathInfo(topdir=topurl) 50 | session = koji.ClientSession(server) 51 | info = session.getBuild(build) 52 | # print session.listArchives(build) 53 | # rpms = session.listRPMs(buildID=info['id']) 54 | # if not rpms: 55 | # print ":-(" 56 | # for rpm in rpms: 57 | # fname = pathinfo.rpm(rpm) 58 | # url = pathinfo.build(info) + '/' + fname 59 | # print url 60 | 61 | if not info: 62 | return 63 | 64 | task_id = info["task_id"] 65 | nvr = info.get("nvr", str(task_id)) 66 | package = info.get("name", str(task_id)) 67 | 68 | task = session.getTaskInfo(task_id, request=True) 69 | if not task: 70 | return 71 | 72 | found = False 73 | for item in task["request"]: 74 | if not isinstance(item, str): 75 | continue 76 | if re.match(build_target, item): 77 | found = True 78 | break 79 | if not found: 80 | print "skipping", build, task["request"] 81 | return 82 | 83 | if not task: 84 | print('Invalid task ID: %i' % task_id) 85 | elif task['state'] in (koji.TASK_STATES['FREE'], koji.TASK_STATES['OPEN']): 86 | print('Task %i has not completed' % task['id']) 87 | elif task['state'] != koji.TASK_STATES['CLOSED']: 88 | print('Task %i did not complete successfully' % task['id']) 89 | 90 | if task['method'] == 'build': 91 | print 'Getting rpms from children of task %i: %s' % (task['id'], koji.taskLabel(task)) 92 | tasks = session.listTasks(opts={'parent': task_id, 'method': 'buildArch', 'state': [koji.TASK_STATES['CLOSED']], 93 | 'decode': True}) 94 | elif task['method'] == 'buildArch': 95 | tasks = [task] 96 | else: 97 | print('Task %i is not a build or buildArch task' % task['id']) 98 | 99 | for task in tasks: 100 | print ">>>>", task, task['id'] 101 | arch = task.get('arch', 'unkwown') 102 | output = session.listTaskOutput(task['id']) 103 | print ">>>>", arch, output 104 | # logs = [filename for filename in output if filename.endswith('.log')] 105 | for item in output: 106 | base_path = koji.pathinfo.taskrelpath(task['id']) 107 | file_url = "%s/%s/%s" % (work_url, base_path, item) 108 | urls.append((arch, file_url)) 109 | # print file_url 110 | # urls.append(file_url) 111 | 112 | # rpms = session.listRPMs(buildID=info['id']) 113 | # pathinfo = koji.PathInfo(topdir=topurl) 114 | # for rpm in rpms: 115 | # fname = koji.pathinfo.rpm(rpm) 116 | # url = os.path.join(pathinfo.build(info), fname) 117 | # print url 118 | # skip SRPMs and 32-bit RPMs 119 | # if not url.endswith("src.rpm") and not url.endswith("686.rpm"): 120 | # urls.append(url) 121 | 122 | print "Getting", urls 123 | 124 | if not urls: 125 | return 126 | 127 | download_url(package, nvr, urls) 128 | 129 | return package, nvr, urls 130 | -------------------------------------------------------------------------------- /scripts/setuid-whitelist.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | {"files": [{"name": "/usr/bin/tex", "RPATH": "Enabled", "RELRO": "Partial", "CANARY": "Enabled", "PIE": "Disabled", "NX": "Enabled", "RUNPATH": "Disabled", "mode": 33261, "size": 320800}], "build": "texlive-tex-bin-2012-0.svn26912.8.20121115_r28267.fc18.x86_64.rpm", "package": "texlive-tex-bin"} 5 | {"files": [{"name": "/usr/bin/pbs_wish", "RPATH": "Disabled", "RELRO": "Partial", "CANARY": "Enabled", "PIE": "Disabled", "NX": "Enabled", "RUNPATH": "Disabled", "mode": 33261, "size": 31840}, {"name": "/usr/lib64/xpbs/bin/xpbs_datadump", "RPATH": "Disabled", "RELRO": "Partial", "CANARY": "Enabled", "PIE": "Disabled", "NX": "Enabled", "RUNPATH": "Disabled", "mode": 33261, "size": 23248}, {"name": "/usr/lib64/xpbs/bin/xpbs_scriptload", "RPATH": "Disabled", "RELRO": "Partial", "CANARY": "Enabled", "PIE": "Disabled", "NX": "Enabled", "RUNPATH": "Disabled", "mode": 33261, "size": 18896}], "build": "torque-gui-3.0.4-1.fc17.x86_64.rpm", "package": "torque-gui"} 6 | """ 7 | 8 | import sys 9 | 10 | try: 11 | import pymongo 12 | except ImportError: 13 | print >> sys.stderr, "Please install pymongo package" 14 | sys.exit(-1) 15 | 16 | import subprocess 17 | import os 18 | import json 19 | import stat 20 | from pymongo import Connection 21 | 22 | 23 | connection = Connection() 24 | 25 | def percentage(keyword="PIE"): 26 | piecount = 0 27 | total = 0 28 | 29 | for build in analysis.find(): 30 | for f in build["files"]: 31 | total = total + 1 32 | mode = f["mode"] 33 | if f[keyword] not in off: 34 | piecount = piecount +1 35 | else: 36 | if verbose: 37 | print "%s,%s,%s" % (build["package"], f["name"], build["build"]) 38 | #print "[No %s]" % keyword, build["package"], f["name"], build["build"] 39 | 40 | # print "[-] Out of %d binaries, %d have %s enabled" % (total, piecount, keyword) 41 | 42 | def privileged_dangerous(prune=None): 43 | for build in analysis.find(): 44 | for f in build["files"]: 45 | dangerous = False 46 | mode = f["mode"] 47 | if prune: 48 | if not prune_list.get(build["package"], False): 49 | continue 50 | if f.get("directory", False): 51 | print "%s,%s,%s,directory,%s" % (build["package"], build["build"], f["name"], oct(f["mode"])) 52 | continue 53 | if (mode & stat.S_ISUID) or (mode & stat.S_ISGID): 54 | # if f["PIE"] == off or f["NX"] == off or f["CANARY"] == off or f["RELRO"] == off: 55 | # print >> sys.stderr, "%s,%s,%s,%s,%s,%s,%s" % (build["package"], build["build"], f["name"], f["NX"], f["CANARY"], f["RELRO"], f["PIE"]) 56 | # else: 57 | print "%s,%s,%s,%s,%s,%s,%s,%s" % (build["package"], build["build"], f["name"], f["NX"], f["CANARY"], f["RELRO"], f["PIE"], oct(f["mode"])) 58 | 59 | 60 | def privileged_nopie(): 61 | setuid = 0 62 | pie = 0 63 | 64 | for build in analysis.find(): 65 | #print build["package"] 66 | for f in build["files"]: 67 | mode = f["mode"] 68 | #print mode 69 | if mode & 04000: 70 | setuid = setuid + 1 71 | if f["PIE"] != off: 72 | pie = pie + 1 73 | else: 74 | if verbose: 75 | print >> sys.stderr, "[No PIE]", f["name"], build["package"], build["build"] 76 | 77 | # print "[-] Out of %d setuid binaries, %d have PIE enabled" % (setuid, pie) 78 | 79 | import argparse 80 | 81 | parser = argparse.ArgumentParser() 82 | 83 | parser.add_argument('-v', action="store_true", dest="verbose", help="enable verbose mode") 84 | parser.add_argument('-f', action="store", dest="prune_file", help="enable filter mode") 85 | 86 | results = parser.parse_args() 87 | 88 | off = "Disabled" 89 | verbose = results.verbose 90 | 91 | db = connection.test_database 92 | collection = db.test_collection 93 | 94 | analysis = db.analysis 95 | 96 | # make prune_list 97 | prune_list = {} 98 | 99 | if results.prune_file: 100 | with open(results.prune_file, "r") as f: 101 | for line in f.readlines(): 102 | prune_list[line.strip()] = True 103 | 104 | privileged_dangerous(results.prune_file) 105 | # percentage() 106 | # percentage("NX") 107 | # percentage("CANARY") 108 | # percentage("RELRO") 109 | # privileged_nopie() 110 | -------------------------------------------------------------------------------- /scripts/analyzer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | {"files": [{"name": "/usr/bin/tex", "RPATH": "Enabled", "RELRO": "Partial", "CANARY": "Enabled", "PIE": "Disabled", "NX": "Enabled", "RUNPATH": "Disabled", "mode": 33261, "size": 320800}], "build": "texlive-tex-bin-2012-0.svn26912.8.20121115_r28267.fc18.x86_64.rpm", "package": "texlive-tex-bin"} 5 | {"files": [{"name": "/usr/bin/pbs_wish", "RPATH": "Disabled", "RELRO": "Partial", "CANARY": "Enabled", "PIE": "Disabled", "NX": "Enabled", "RUNPATH": "Disabled", "mode": 33261, "size": 31840}, {"name": "/usr/lib64/xpbs/bin/xpbs_datadump", "RPATH": "Disabled", "RELRO": "Partial", "CANARY": "Enabled", "PIE": "Disabled", "NX": "Enabled", "RUNPATH": "Disabled", "mode": 33261, "size": 23248}, {"name": "/usr/lib64/xpbs/bin/xpbs_scriptload", "RPATH": "Disabled", "RELRO": "Partial", "CANARY": "Enabled", "PIE": "Disabled", "NX": "Enabled", "RUNPATH": "Disabled", "mode": 33261, "size": 18896}], "build": "torque-gui-3.0.4-1.fc17.x86_64.rpm", "package": "torque-gui"} 6 | """ 7 | 8 | import sys 9 | 10 | try: 11 | import pymongo 12 | except ImportError: 13 | print >> sys.stderr, "Please install pymongo package" 14 | sys.exit(-1) 15 | 16 | import subprocess 17 | import os 18 | import json 19 | import stat 20 | from pymongo import Connection 21 | 22 | 23 | connection = Connection() 24 | 25 | def percentage(keyword="PIE"): 26 | piecount = 0 27 | total = 0 28 | 29 | for build in analysis.find(): 30 | for f in build["files"]: 31 | total = total + 1 32 | mode = f["mode"] 33 | if f[keyword] not in off: 34 | piecount = piecount +1 35 | else: 36 | if verbose: 37 | print "%s,%s,%s" % (build["package"], f["name"], build["build"]) 38 | #print "[No %s]" % keyword, build["package"], f["name"], build["build"] 39 | 40 | # print "[-] Out of %d binaries, %d have %s enabled" % (total, piecount, keyword) 41 | 42 | def privileged_dangerous(prune=None): 43 | 44 | query = { "files": { "$elemMatch" : { "directory": { "$ne" : False } } } } 45 | 46 | for build in analysis.find(query): 47 | # for build in analysis.find(): 48 | for f in build["files"]: 49 | dangerous = False 50 | mode = f["mode"] 51 | if prune: 52 | if not prune_list.get(build["package"], False): 53 | continue 54 | # if f.get("directory", False): 55 | # print "%s,%s,%s,directory,%s" % (build["package"], build["build"], f["name"], oct(f["mode"])) 56 | # continue 57 | if (mode & stat.S_ISUID) or (mode & stat.S_ISGID): 58 | if f["PIE"] == off or f["NX"] == off or f["CANARY"] == off or f["RELRO"] == off: 59 | print "%s,%s,%s,%s,%s,%s,%s,%s" % (build["package"], build["build"], f["name"], f["NX"], f["CANARY"], f["RELRO"], f["PIE"], oct(f["mode"])) 60 | else: 61 | print >> sys.stderr, "%s,%s,%s,%s,%s,%s,%s,%s" % (build["package"], build["build"], f["name"], f["NX"], f["CANARY"], f["RELRO"], f["PIE"], oct(f["mode"])) 62 | 63 | 64 | def privileged_nopie(): 65 | setuid = 0 66 | pie = 0 67 | 68 | for build in analysis.find(): 69 | # print build["package"] 70 | for f in build["files"]: 71 | mode = f["mode"] 72 | #print mode 73 | if mode & 04000: 74 | setuid = setuid + 1 75 | if f["PIE"] != off: 76 | pie = pie + 1 77 | else: 78 | if verbose: 79 | print >> sys.stderr, "[No PIE]", f["name"], build["package"], build["build"] 80 | 81 | # print "[-] Out of %d setuid binaries, %d have PIE enabled" % (setuid, pie) 82 | 83 | import argparse 84 | 85 | parser = argparse.ArgumentParser() 86 | 87 | parser.add_argument('-v', action="store_true", dest="verbose", help="enable verbose mode") 88 | parser.add_argument('-f', action="store", dest="prune_file", help="enable filter mode") 89 | 90 | results = parser.parse_args() 91 | 92 | off = "Disabled" 93 | verbose = results.verbose 94 | 95 | db = connection.test_database 96 | collection = db.test_collection 97 | 98 | analysis = db.analysis 99 | 100 | # make prune_list 101 | prune_list = {} 102 | 103 | if results.prune_file: 104 | with open(results.prune_file, "r") as f: 105 | for line in f.readlines(): 106 | prune_list[line.strip()] = True 107 | 108 | privileged_dangerous(results.prune_file) 109 | # percentage() 110 | # percentage("NX") 111 | # percentage("CANARY") 112 | # percentage("RELRO") 113 | # privileged_nopie() 114 | -------------------------------------------------------------------------------- /static/assets/js/application.js: -------------------------------------------------------------------------------- 1 | // NOTICE!! DO NOT USE ANY OF THIS JAVASCRIPT 2 | // IT'S ALL JUST JUNK FOR OUR DOCS! 3 | // ++++++++++++++++++++++++++++++++++++++++++ 4 | 5 | !function ($) { 6 | 7 | $(function(){ 8 | 9 | var $window = $(window) 10 | 11 | // Disable certain links in docs 12 | $('section [href^=#]').click(function (e) { 13 | e.preventDefault() 14 | }) 15 | 16 | // side bar 17 | setTimeout(function () { 18 | $('.bs-docs-sidenav').affix({ 19 | offset: { 20 | top: function () { return $window.width() <= 980 ? 290 : 210 } 21 | , bottom: 270 22 | } 23 | }) 24 | }, 100) 25 | 26 | // make code pretty 27 | window.prettyPrint && prettyPrint() 28 | 29 | // add-ons 30 | $('.add-on :checkbox').on('click', function () { 31 | var $this = $(this) 32 | , method = $this.attr('checked') ? 'addClass' : 'removeClass' 33 | $(this).parents('.add-on')[method]('active') 34 | }) 35 | 36 | // add tipsies to grid for scaffolding 37 | if ($('#gridSystem').length) { 38 | $('#gridSystem').tooltip({ 39 | selector: '.show-grid > [class*="span"]' 40 | , title: function () { return $(this).width() + 'px' } 41 | }) 42 | } 43 | 44 | // tooltip demo 45 | $('.tooltip-demo').tooltip({ 46 | selector: "a[data-toggle=tooltip]" 47 | }) 48 | 49 | $('.tooltip-test').tooltip() 50 | $('.popover-test').popover() 51 | 52 | // popover demo 53 | $("a[data-toggle=popover]") 54 | .popover() 55 | .click(function(e) { 56 | e.preventDefault() 57 | }) 58 | 59 | // button state demo 60 | $('#fat-btn') 61 | .click(function () { 62 | var btn = $(this) 63 | btn.button('loading') 64 | setTimeout(function () { 65 | btn.button('reset') 66 | }, 3000) 67 | }) 68 | 69 | // carousel demo 70 | $('#myCarousel').carousel() 71 | 72 | // javascript build logic 73 | var inputsComponent = $("#components.download input") 74 | , inputsPlugin = $("#plugins.download input") 75 | , inputsVariables = $("#variables.download input") 76 | 77 | // toggle all plugin checkboxes 78 | $('#components.download .toggle-all').on('click', function (e) { 79 | e.preventDefault() 80 | inputsComponent.attr('checked', !inputsComponent.is(':checked')) 81 | }) 82 | 83 | $('#plugins.download .toggle-all').on('click', function (e) { 84 | e.preventDefault() 85 | inputsPlugin.attr('checked', !inputsPlugin.is(':checked')) 86 | }) 87 | 88 | $('#variables.download .toggle-all').on('click', function (e) { 89 | e.preventDefault() 90 | inputsVariables.val('') 91 | }) 92 | 93 | // request built javascript 94 | $('.download-btn .btn').on('click', function () { 95 | 96 | var css = $("#components.download input:checked") 97 | .map(function () { return this.value }) 98 | .toArray() 99 | , js = $("#plugins.download input:checked") 100 | .map(function () { return this.value }) 101 | .toArray() 102 | , vars = {} 103 | , img = ['glyphicons-halflings.png', 'glyphicons-halflings-white.png'] 104 | 105 | $("#variables.download input") 106 | .each(function () { 107 | $(this).val() && (vars[ $(this).prev().text() ] = $(this).val()) 108 | }) 109 | 110 | $.ajax({ 111 | type: 'POST' 112 | , url: /\?dev/.test(window.location) ? 'http://localhost:3000' : 'http://bootstrap.herokuapp.com' 113 | , dataType: 'jsonpi' 114 | , params: { 115 | js: js 116 | , css: css 117 | , vars: vars 118 | , img: img 119 | } 120 | }) 121 | }) 122 | }) 123 | 124 | // Modified from the original jsonpi https://github.com/benvinegar/jquery-jsonpi 125 | $.ajaxTransport('jsonpi', function(opts, originalOptions, jqXHR) { 126 | var url = opts.url; 127 | 128 | return { 129 | send: function(_, completeCallback) { 130 | var name = 'jQuery_iframe_' + jQuery.now() 131 | , iframe, form 132 | 133 | iframe = $('