Skip to content

Commit bbf40ea

Browse files
committed
added support for certificate chain download
1 parent 1122e2e commit bbf40ea

File tree

6 files changed

+40
-32
lines changed

6 files changed

+40
-32
lines changed

CHANGELOG.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99
### Added
1010
- Upcoming changes...
1111

12-
## [1.4.0] - 2023-01-01
12+
## [1.4.2] - 2023-03-09
13+
### Fixed
14+
- Fixed issue with custom certificate when scanning (--ca-cert)
15+
### Added
16+
- Added support to download full certificate chain with:
17+
- `cert_download.sh`
18+
- `scanoss-py utils cdl`
19+
20+
## [1.4.0] - 2023-03-01
1321
### Added
1422
- Added support for fast winnowing (15x improvement) thanks to a contribution from [tardyp](https://github.com/tardyp)
1523
- This is enabled by a supporting package; [scanoss_winnowing](https://github.com/scanoss/scanoss-winnowing.py).
@@ -209,3 +217,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
209217
[1.3.6]: https://github.com/scanoss/scanoss.py/compare/v1.3.5...v1.3.6
210218
[1.3.7]: https://github.com/scanoss/scanoss.py/compare/v1.3.6...v1.3.7
211219
[1.4.0]: https://github.com/scanoss/scanoss.py/compare/v1.3.7...v1.4.0
220+
[1.4.2]: https://github.com/scanoss/scanoss.py/compare/v1.4.0...v1.4.2

cert_download.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,4 +100,4 @@ if [ $force -eq 0 ] && [ -f "$pemfile" ] ; then
100100
fi
101101
echo "Attempting to get PEM certificate from $host:$port and saving to $pemfile ..."
102102

103-
openssl s_client -showcerts -connect "$host:$port" -servername "$host" </dev/null 2>/dev/null | openssl x509 -outform PEM > "$pemfile"
103+
openssl s_client -showcerts -verify 5 -connect "$host:$port" -servername "$host" < /dev/null 2> /dev/null | awk '/BEGIN/,/END/{ if(/BEGIN/){a++}; print}' > "$pemfile"

requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ progress
55
grpcio>1.42.0
66
protobuf>3.19.1
77
pypac
8-
urllib3
8+
urllib3
9+
pyOpenSSL

setup.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ install_requires =
3232
grpcio>1.42.0
3333
protobuf>3.19.1
3434
pypac
35+
pyOpenSSL
3536

3637
[options.extras_require]
3738
fast_winnowing =

src/scanoss/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@
2222
THE SOFTWARE.
2323
"""
2424

25-
__version__ = '1.4.1'
25+
__version__ = '1.4.2'

src/scanoss/cli.py

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -561,43 +561,40 @@ def utils_cert_download(_, args):
561561
:param _: ignore/unused
562562
:param args: Parsed arguments
563563
"""
564-
import ssl
565564
from urllib.parse import urlparse
566565
import socket
566+
from OpenSSL import SSL, crypto
567567
import traceback
568568

569569
file = sys.stdout
570570
hostname = 'unset'
571571
port = 'unkown'
572+
if args.output:
573+
file = open(args.output, 'w')
574+
parsed_url = urlparse(args.hostname)
575+
hostname = parsed_url.hostname or args.hostname # Use the parse hostname, or it None use the supplied one
576+
port = int(parsed_url.port or args.port) # Use the parsed port, if not use the supplied one (default 443)
577+
certs = []
572578
try:
573-
if args.output:
574-
file = open(args.output, 'w')
575-
parsed_url = urlparse(args.hostname)
576-
hostname = parsed_url.hostname or args.hostname # Use the parse hostname, or it None use the supplied one
577-
port = int(parsed_url.port or args.port) # Use the parsed port, if not use the supplied one (default 443)
578-
conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
579-
context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
580-
sock = context.wrap_socket(conn, server_hostname=hostname)
581-
if not args.quiet or args.debug:
582-
print_stderr(f'Attempting to download PEM certificate from {hostname}:{port} ...')
583579
if args.debug:
584-
print_stderr('Connecting to host...')
585-
sock.connect((hostname, port))
586-
if args.debug:
587-
print_stderr('Getting peer cert...')
588-
peer_cert = sock.getpeercert(True)
589-
if not peer_cert:
590-
print_stderr(f'Error: Failed to download peer certificate data from {hostname}:{port}')
591-
exit(1)
592-
if args.debug:
593-
print_stderr('Converting DER to PEM...')
594-
cert_data = ssl.DER_cert_to_PEM_cert(peer_cert)
595-
if not cert_data or cert_data == '':
596-
print_stderr(f'Error: Failed to convert certificate data to PEM from {hostname}:{port}')
597-
exit(1)
598-
else:
599-
print(cert_data.strip(), file=file) # Print the downloaded PEM certificate
600-
except Exception as e:
580+
print_stderr(f'Connecting to {hostname} on {port}...')
581+
conn = SSL.Connection(SSL.Context(SSL.TLSv1_2_METHOD), socket.socket())
582+
conn.connect((hostname, port))
583+
conn.do_handshake()
584+
certs = conn.get_peer_cert_chain()
585+
for index, cert in enumerate(certs):
586+
cert_components = dict(cert.get_subject().get_components())
587+
if(sys.version_info[0] >= 3):
588+
cn = cert_components.get(b'CN')
589+
else:
590+
cn = cert_components.get('CN')
591+
if not args.quiet:
592+
print_stderr(f'Centificate {index} - CN: {cn}')
593+
if(sys.version_info[0] >= 3):
594+
print((crypto.dump_certificate(crypto.FILETYPE_PEM, cert).decode('utf-8')).strip(), file=file) # Print the downloaded PEM certificate
595+
else:
596+
print((crypto.dump_certificate(crypto.FILETYPE_PEM, cert)).strip(), file=file)
597+
except SSL.Error as e:
601598
print_stderr(f'ERROR: Exception ({e.__class__.__name__}) Downloading certificate from {hostname}:{port} - {e}.')
602599
if args.debug:
603600
traceback.print_exc()

0 commit comments

Comments
 (0)