diff --git a/app-crypt/cprocsp/cprocsp-5.0.13000.ebuild b/app-crypt/cprocsp/cprocsp-5.0.13000.ebuild new file mode 100644 index 000000000..be727acb5 --- /dev/null +++ b/app-crypt/cprocsp/cprocsp-5.0.13000.ebuild @@ -0,0 +1,262 @@ +# Copyright 1999-2024 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +inherit rpm systemd xdg udev + +DESCRIPTION="CryptoPro Crypto Provider" +HOMEPAGE="https://cryptopro.ru/products/csp/downloads" + +SRC_URI=" + x86? ( ${P}_x86.tgz ) + amd64? ( ${P}_amd64.tgz ) + arm? ( ${P}_arm.tgz ) + arm64? ( ${P}_arm64.tgz ) +" + +LICENSE="Crypto-Pro" +SLOT="0/${PV}" +# KEYWORDS="~amd64 ~arm ~arm64 ~x86" + +CRYPTOPRO_PATCHED_SOFTWARE=( + curl + nginx + apache-modssl +) +CRYPTOPRO_READERS_DEFAULT=( # cprocsp-rdr- + # NOTE: check in install_gui.sh + pcsc + emv + inpaspot + kst + mskey + novacard + edoc + rutoken + jacarta + cloud + cpfkc + infocrypt + rosan + cryptoki + rustoken +) +CRYPTOPRO_READERS_ADDITIONAL=( + cloud + esmart + relay + gui # TODO: move to searate use flag +) + +IUSE="kc2" +for p in ${CRYPTOPRO_PATCHED_SOFTWARE[@]}; do + IUSE+=(cryptopro_patched_${p}) +done +for p in ${CRYPTOPRO_PATCHED_SOFTWARE[@]}; do + IUSE+=(cryptopro_readers_${p}) +done + +RESTRICT="bindist fetch mirror strip" + +DEPEND=" + app-accessibility/at-spi2-core + dev-libs/glib + dev-libs/libusb-compat + media-libs/fontconfig + media-libs/freetype + sys-libs/pam + sys-libs/zlib + x11-libs/cairo + x11-libs/gdk-pixbuf + x11-libs/gtk+:2 + x11-libs/libSM + x11-libs/libX11 + x11-libs/libXxf86vm + x11-libs/pango +" +RDEPEND=" + app-crypt/ccid + >=dev-libs/libp11-0.4.0 + dev-libs/libxml2 + x86? ( dev-libs/opensc ) + amd64? ( dev-libs/opensc ) + media-libs/libpng:0 + media-libs/fontconfig + sys-apps/dbus + sys-apps/lsb-release + >=sys-apps/pcsc-lite-1.4.99 + sys-apps/pcsc-tools + virtual/libcrypt:= + virtual/libusb:0 + ${DEPEND} +" +BDEPEND=" + app-arch/rpm2targz + app-alternatives/bzip2 +" + +QA_PREBUILT="opt/cprocsp/*" + +_get_arch() { + if [[ -n "${_got_arch}" ]]; then + echo ${_got_arch}; + return + fi + local _got_arch + case $(uname -m) in + x86_64) + _got_arch="amd64" + ;; + i*86) + _got_arch="ia32" + ;; + armv7*) + _got_arch="armhf" + ;; + aarch64) + _got_arch="arm64" + ;; + esac + export _got_arch + echo "${_got_arch}" +} + +pkg_pretend() { + die "Not yet ready" +} + +pkg_nofetch() { + local BASE_URL="https://cryptopro.ru/sites/default/files/private/csp" + local v=$(ver_cut 1-2) + local arch=$(_get_arch) + einfo "Please, open this link in the browser: ${BASE_URL}/${v//.}/$(ver_cut 3)/linux-${arch}.tgz" + einfo "(registration/login needed)" + einfo "Then download it, and place at ${PORTAGE_ACTUAL_DISTDIR}/${A}" + ewarn "Please, post an issue on GitHub in case of checksums mismatch" +} + +src_unpack() { + local uname_m=$(uname -m) + local arch=$(_get_arch); + local libdir=$(get_libdir) + + default + + mkdir -p "${S}" + cd "${S}" + + PKGS=( # Packages that usually installed by CryptoPro installer + lsb-cprocsp-{base,ca-certs,capilite,kc1,pkcs11,rdr} + cprocsp-{curl,rdr} + apache-modssl + ) + ADD_PKGS=( # Additional packages that should be useful (token drivers, patched stunnel, cert viewer) + lsb-cprocsp-rcrypt + cprocsp-{stunnel,xer2print,cptools} + cprocsp-ipsec-{genpsk,ike} + ifd-rutokens + cprocsp-pki{,-{plugin,cades}} # ,phpcades}} + ) + + # TODO: USE-flags for readers, browser plugin, curl, stunnel and so on + + for f in ${PKGS[@]} ${ADD_PKGS[@]}; do + find "../linux-${arch}" -name "${f}*.rpm" | while read r; do rpm_unpack "./${r}"; done + done + + mkdir -p usr/lib || die + mv etc/udev usr/lib/udev || die + + mkdir -p usr/${libdir}/readers/usb || die + mv usr/${libdir}/pcsc/drivers/* usr/${libdir}/readers/usb/ || die + + cp -rl opt/cprocsp/share usr/share || die + # ^ TODO: investigave about pottential collisions on certmgr (mono?) and stunnel mans + + mkdir -p usr/lib/mozilla/plugins || die + cp -lL opt/cprocsp/lib/${arch}/libnpcades.so usr/lib/mozilla/plugins/ || die + + # cp etc/opt/cprocsp/config64.ini{,.backup} || die + # ^ TODO: What about non-64bit installs? (need someone with 32bit setup) + bzip2 -d -c < "${FILESDIR}"/cprocsp_postinstal_all_scripts.sh.bz2 > "${T}"/postinst.bash || die +} + +src_install() { + return + local arch=$(_get_arch) + + insinto / + doins -r opt etc usr var + + exeinto /opt/cprocsp/bin/"${arch}" + doexe opt/cprocsp/bin/"${arch}"/* + exeinto /opt/cprocsp/sbin/"${arch}" + doexe opt/cprocsp/sbin/"${arch}"/* + exeinto /opt/cprocsp/lib/"${arch}" + doexe opt/cprocsp/lib/${arch}/* + + keepdir /var/opt/cprocsp/dsrf + keepdir /var/opt/cprocsp/dsrf/db1 + keepdir /var/opt/cprocsp/dsrf/db2 + keepdir /var/opt/cprocsp/keys + keepdir /var/opt/cprocsp/tmp + keepdir /var/opt/cprocsp/users + keepdir /var/opt/cprocsp/users/stores + keepdir /var/opt/cprocsp/mnt + + # insinto /etc/opt/cprocsp + + # alt-compat + # rm "${arch}"/ld-lsb-x86-64.so.3 + # rm etc/init.d/cprocsp + mv etc/init.d/cprocsp opt/cprocsp/cprocsp.init || die # FIXME: + + newinitd "${FILESDIR}/${P}" cprocsp + # TODO: ^ make it just script, and make normal openrc init-file + systemd_dounit "${FILESDIR}/${PN}.service" + + newenvd - "99${PN}" <<-_EOF_ + PATH=/opt/cprocsp/bin/${arch}:/opt/cprocsp/sbin/${arch} + _EOF_ + # TODO: ^^^ adding it to the end of PATH leads to shadowing + # CryptoPro's `certmgr` by same-named utility from dev-lang/mono + # And adding it to the beginning leads to shadowning `curl` from + # net-misc/curl by proprietary-patched `curl` from this package. + # TODO: maybe make symliks to bindir instead of adding to PATH? + # Or wrapper(s)? +} + +pkg_postinst() { + return + local arch=$(_get_arch) + local pi_st + + /etc/init.d/cprocsp repair_var + + ebegin "Running postinstall script (pre-configuring)" + bash "${T}"/postinst.bash &>"${T}/postinst.log" + pi_st=$? + eend "${pi_st}" + if [[ "${pi_st}" -gt 0 ]]; then + eerror "Something gone wrong during postinstall. It is not necessarily bad, but check the log just in case:" + eerror "==================" + cat "${T}/postinst.log" + eerror "==================" + fi + + xdg_desktop_database_update + udev_reload + + einfo "You may want to run following command as user (not root):" + einfo " /opt/cprocsp/bin/"${arch}"/csptestf -absorb -certs -autoprov" + einfo "to import cryptocontainers and certificates from USB-smartcard (aka token)" + + ewarn "!!!!!! WARNING !!!!!!" + ewarn "In case of breakages (for example, it stopped to work with your smartcard)" + ewarn "try to:" + ewarn "1) uninstall this package" + ewarn "2) remove (or move to another place) /etc/opt/cprocsp/config64.ini if it wasn't removed by portage" + ewarn "3) install this package again" + ewarn "4) if you did any modifications on config64.ini - repeat them now" +} diff --git a/app-crypt/cprocsp/files/rpm_hooks_extractor.pl b/app-crypt/cprocsp/files/rpm_hooks_extractor.pl new file mode 100644 index 000000000..18324ee55 --- /dev/null +++ b/app-crypt/cprocsp/files/rpm_hooks_extractor.pl @@ -0,0 +1,72 @@ +#!/usr/bin/perl +use strict; +use warnings; + +package RPM; +use vars qw(%hdr_tags); +%hdr_tags = ( + 1023 => { 'TAGNAME' => 'PREIN', 'GROUP' => 'TRIGGER', 'NAME' => '', 'TYPE' => 1 }, + 1024 => { 'TAGNAME' => 'POSTIN', 'GROUP' => 'TRIGGER', 'NAME' => '', 'TYPE' => 1 }, + 1025 => { 'TAGNAME' => 'PREUN', 'GROUP' => 'TRIGGER', 'NAME' => '', 'TYPE' => 1 }, + 1026 => { 'TAGNAME' => 'POSTUN', 'GROUP' => 'TRIGGER', 'NAME' => '', 'TYPE' => 1 }, + 1085 => { 'TAGNAME' => 'PREINPROG', 'GROUP' => 'TRIGGER', 'NAME' => '', 'TYPE' => 1 }, + 1086 => { 'TAGNAME' => 'POSTINPROG', 'GROUP' => 'TRIGGER', 'NAME' => '', 'TYPE' => 1 }, + 1087 => { 'TAGNAME' => 'PREUNPROG', 'GROUP' => 'TRIGGER', 'NAME' => '', 'TYPE' => 1 }, + 1088 => { 'TAGNAME' => 'POSTUNPROG', 'GROUP' => 'TRIGGER', 'NAME' => '', 'TYPE' => 1 }, +); +sub TIEHASH { + my $RPM_HEADER_MAGIC = chr(0x8e).chr(0xad).chr(0xe8); + my $RPM_FILE_MAGIC = chr(0xed).chr(0xab).chr(0xee).chr(0xdb); + my $buff; + my ($class_name, $filename, $readtype) = @_; + my $self = bless { hash => {}, }, $class_name; + if (!defined($filename) or !open(RPMFILE, "<$filename")) { return undef; } + binmode(RPMFILE); read(RPMFILE, $buff, 96); + ( $self->{'hash'}->{'LEAD_MAGIC'}, $self->{'hash'}->{'LEAD_MAJOR'}, $self->{'hash'}->{'LEAD_MINOR'}, $self->{'hash'}->{'LEAD_TYPE'}, $self->{'hash'}->{'LEAD_ARCHNUM'}, $self->{'hash'}->{'LEAD_NAME'}, $self->{'hash'}->{'LEAD_OSNUM'}, $self->{'hash'}->{'LEAD_SIGNATURETYPE'}, $self->{'hash'}->{'LEAD_RESERVED'} ) = unpack("a4CCssA66ssA16", $buff); + if (!$self->{'hash'}->{'LEAD_MAGIC'} eq $RPM_FILE_MAGIC) { return 0; } + for (my $header_num=1; $header_num < 3; $header_num++) { + read(RPMFILE, $buff, 16); + my ($header_magic, $header_version, $header_reserved, $header_entries, $header_size) = unpack("a3CNNN", $buff); + if ($header_magic eq $RPM_HEADER_MAGIC) { + my $record; + read(RPMFILE, $record, 16*$header_entries); + if ($header_num == 1) { + if (($header_size % 8) == 0) { read(RPMFILE, $buff, $header_size); } + else { read(RPMFILE, $buff, $header_size+(8-($header_size % 8))); } + } else { read(RPMFILE, $buff, $header_size); } + for (my $record_num=0; $record_num < $header_entries; $record_num++) { + my ($tag, $type, $offset, $count) = unpack("NNNN", substr($record, $record_num*16, 16)); + my @value; + if ($header_num == 1) { $tag = $tag*10; } + if (!defined($hdr_tags{$tag})) { next; } + elsif ($type == 0) { @value = (''); } + elsif ($type == 1) { print "$hdr_tags{$tag}{'TAGNAME'}\n"; } + elsif ($type == 2) { @value = unpack("C*", substr($buff, $offset, 1*$count)); $offset = 1*$count; } + elsif ($type == 3) { @value = unpack("n*", substr($buff, $offset, 2*$count)); $offset = 2*$count; } + elsif ($type == 4) { @value = unpack("N*", substr($buff, $offset, 4*$count)); $offset = 4*$count; } + elsif ($type == 5) { print "$hdr_tags{$tag}{'TAGNAME'}\n"; } + if ($type == 6 or $type == 8 or $type == 9) { + for(my $i=0;$i<$count;$i++) { + my $length = index($buff, "\0", $offset)-$offset; + push(@value, substr($buff, $offset, $length)); + $offset += $length+1; + } + } + elsif ($type == 7) { $value[0] = substr($buff, $offset, $count); } + if (defined($hdr_tags{$tag}{'TYPE'}) and $hdr_tags{$tag}{'TYPE'} == 1) { + @{$self->{'hash'}->{$hdr_tags{$tag}{'TAGNAME'}}} = @value; + } else { $self->{'hash'}->{$hdr_tags{$tag}{'TAGNAME'}} = $value[0]; } + } + } + } + return $self; +} +sub FETCH { my ($self, $key) = @_; return $self->{hash}->{$key}; } +1; + +package main; +die "Usage: $0 \n" until @ARGV == 2; +my ($phase, $file) = ($ARGV[0], $ARGV[1]); +my %phases = (preinst => "PREIN", postinst => "POSTIN", prerm => "PREUN", postrm => "POSTUN"); +tie my %rpm, 'RPM', $file or die "Could not open RPM file: $!"; +print @{$rpm{$phases{$phase}}};