#!/usr/bin/env bash
# fix_dnf_gpg_aix.sh
# Purpose: Fix "GPGME: Invalid crypto engine" during `dnf` operations on AIX Toolbox and update httpd.
# Author: Unix Team (Roshan)
# Tested scope: AIX with /opt/freeware (AIX Toolbox for Linux Applications)
set -u
# Colors for readability
GREEN="\033[0;32m"
YELLOW="\033[1;33m"
RED="\033[0;31m"
NC="\033[0m"
ALLOW_TEMP_DISABLE=0
HTTPD_PKG="${HTTPD_PKG:-httpd}"
log() { printf "${GREEN}[INFO]${NC} %s\n" "$*"; }
warn() { printf "${YELLOW}[WARN]${NC} %s\n" "$*"; }
error() { printf "${RED}[ERROR]${NC} %s\n" "$*"; }
usage() {
cat <<USAGE
Usage: $0 [--allow-temporary-disable]
--allow-temporary-disable If the proper fix fails, temporarily disable GPG checks to proceed with update.
USAGE
}
# Parse args
while [ "${1-}" != "" ]; do
case "$1" in
--allow-temporary-disable) ALLOW_TEMP_DISABLE=1 ;;
-h|--help) usage; exit 0 ;;
*) warn "Unknown option: $1"; usage; exit 2 ;;
esac
shift
done
# Ensure we have required tools in PATH
FREEWARE_BIN="/opt/freeware/bin"
FREEWARE_ETC="/opt/freeware/etc"
DNF_BIN="${FREEWARE_BIN}/dnf"
GPG_BIN="${FREEWARE_BIN}/gpg"
REPO_DIR="${FREEWARE_ETC}/yum/repos.d"
DNF_CONF="${FREEWARE_ETC}/dnf/dnf.conf"
require_root() {
if [ "$(id -u)" -ne 0 ]; then
error "Please run as root."
exit 1
fi
}
check_cmd() {
if ! command -v "$1" >/dev/null 2>&1; then
return 1
fi
return 0
}
# Safely run commands and echo them
run() {
log "Running: $*"
eval "$@"
local rc=$?
if [ $rc -ne 0 ]; then
error "Command failed (rc=$rc): $*"
return $rc
fi
return 0
}
# Audit installed packages
audit_packages() {
log "Auditing required packages..."
local pkgs="gnupg gnupg2 gpgme libassuan libgpg-error python3-gpg"
rpm -qa >/dev/null 2>&1 || { error "rpm not available. Ensure AIX Toolbox is installed."; return 1; }
for p in $pkgs; do
if rpm -qa | grep -qi "^${p}-"; then
log "Package present: $p"
else
warn "Package missing: $p"
fi
done
}
install_packages() {
log "Installing/repairing required packages using dnf..."
if [ ! -x "$DNF_BIN" ]; then
error "dnf not found at $DNF_BIN. Ensure AIX Toolbox dnf is installed."
return 1
fi
local pkgs_to_install="gnupg gnupg2 gpgme libassuan libgpg-error python3-gpg"
# Some systems may not have both gnupg and gnupg2; proceed without failing the whole batch.
run "$DNF_BIN install -y $pkgs_to_install" || {
warn "Primary install attempt failed. Retrying with available subsets..."
for p in $pkgs_to_install; do
if rpm -qa | grep -qi "^${p}-"; then
log "Already installed: $p"
else
run "$DNF_BIN install -y $p" || warn "Could not install $p. Continuing."
fi
done
}
}
verify_gpg_engine() {
log "Verifying GPG engine and libraries..."
if [ -x "$GPG_BIN" ]; then
"$GPG_BIN" --version || {
error "gpg failed to run. Check library paths."
return 1
}
else
error "gpg binary not found at $GPG_BIN"
return 1
fi
# Ensure python3-gpg can be imported
if command -v python3 >/dev/null 2>&1; then
python3 - <<'PY'
import sys
try:
import gpg
print("python3-gpg import OK.")
except Exception as e:
print("python3-gpg import FAILED:", e)
sys.exit(1)
PY
local rc=$?
if [ $rc -ne 0 ]; then
error "Python gpg bindings not working."
return 1
fi
else
warn "python3 not found in PATH; skipping python gpg binding test."
fi
# Sometimes AIX needs /opt/freeware/lib in LD_LIBRARY_PATH
if ! "$GPG_BIN" --version >/dev/null 2>&1; then
warn "Setting LD_LIBRARY_PATH to include /opt/freeware/lib and retrying..."
export LD_LIBRARY_PATH="/opt/freeware/lib:${LD_LIBRARY_PATH-}"
"$GPG_BIN" --version || {
error "gpg still failing after adjusting LD_LIBRARY_PATH."
return 1
}
fi
log "GPG engine looks healthy."
return 0
}
import_repo_keys() {
log "Importing AIX Toolbox repository GPG keys..."
local keys=(
"${FREEWARE_ETC}/RPM-GPG-KEY-AIX"
"${FREEWARE_ETC}/RPM-GPG-KEY-AIXToolbox"
)
# Also parse any explicit gpgkey entries in repo files
if [ -d "$REPO_DIR" ]; then
log "Scanning repo files for gpgkey entries..."
grep -R "gpgkey" "$REPO_DIR" | awk -F'=' '{print $2}' | tr ' ' '\n' | while read -r keypath; do
[ -n "$keypath" ] && keys+=("$keypath")
done
fi
local imported_any=0
for key in "${keys[@]}"; do
if [ -f "$key" ]; then
run "rpm --import '$key'" && { log "Imported key: $key"; imported_any=1; }
else
warn "Key file not found: $key"
fi
done
if [ $imported_any -eq 0 ]; then
warn "No keys were imported. Ensure your repo files specify valid gpgkey paths."
fi
}
dnf_housekeeping() {
log "Cleaning caches and rebuilding metadata..."
run "$DNF_BIN clean all" || true
run "$DNF_BIN makecache" || true
}
update_httpd() {
log "Attempting to update package: $HTTPD_PKG"
run "$DNF_BIN update -y $HTTPD_PKG"
local rc=$?
if [ $rc -eq 0 ]; then
log "Update succeeded for $HTTPD_PKG."
return 0
fi
error "Update failed for $HTTPD_PKG (rc=$rc)."
return $rc
}
disable_gpg_checks_temporarily() {
warn "Temporarily disabling GPG checks (you requested --allow-temporary-disable)."
warn "Use only if you trust your local repositories, and re-enable GPG afterwards."
# Disable per-repo
if [ -d "$REPO_DIR" ]; then
for f in "$REPO_DIR"/*.repo; do
[ -f "$f" ] || continue
log "Disabling GPG in $f"
# Replace or add gpgcheck and repo_gpgcheck
if grep -q '^gpgcheck=' "$f"; then
sed -i 's/^gpgcheck=.*/gpgcheck=0/' "$f"
else
echo "gpgcheck=0" >> "$f"
fi
if grep -q '^repo_gpgcheck=' "$f"; then
sed -i 's/^repo_gpgcheck=.*/repo_gpgcheck=0/' "$f"
else
echo "repo_gpgcheck=0" >> "$f"
fi
done
else
warn "Repo dir not found: $REPO_DIR"
fi
# Disable global (optional)
if [ -f "$DNF_CONF" ]; then
log "Disabling GPG in $DNF_CONF"
if grep -q '^gpgcheck=' "$DNF_CONF"; then
sed -i 's/^gpgcheck=.*/gpgcheck=0/' "$DNF_CONF"
else
echo "gpgcheck=0" >> "$DNF_CONF"
fi
fi
dnf_housekeeping
log "Retrying update without GPG checks..."
run "$DNF_BIN update -y $HTTPD_PKG"
}
main() {
require_root
log "Starting fix for 'GPGME: Invalid crypto engine' on AIX (AIX Toolbox)."
# Sanity: show repos
if [ -x "$DNF_BIN" ]; then
log "Current repos:"
"$DNF_BIN" repolist || warn "Could not list repos."
else
error "dnf not found at $DNF_BIN"
exit 1
fi
audit_packages
install_packages
if ! verify_gpg_engine; then
error "GPG engine verification failed after installation."
if [ $ALLOW_TEMP_DISABLE -eq 1 ]; then
disable_gpg_checks_temporarily
exit $?
else
error "Aborting without disabling GPG. Re-run with --allow-temporary-disable to proceed urgently."
exit 1
fi
fi
import_repo_keys
dnf_housekeeping
if update_httpd; then
log "All done ✅"
exit 0
else
if [ $ALLOW_TEMP_DISABLE -eq 1 ]; then
disable_gpg_checks_temporarily
exit $?
else
error "Update failed. You may re-run with --allow-temporary-disable to bypass GPG temporarily."
exit 1
fi
fi
}
------------------------------
Roshan Kumar Sa
------------------------------
Original Message:
Sent: Wed December 03, 2025 03:30 AM
From: Unix Team
Subject: issue while updating httpd version from httpd-2.4.54-3.ppc to httpd-2.4.65-1 using dnf
Hello Lakshmi,
Same error even now.
gdisprnimal1d(root):/# export PATH=/opt/freeware/bin/:$PATH
gdisprnimal1d(root):/# env | grep -i bin
_=/usr/bin/env
PATH=/opt/freeware/bin/:/usr/bin:/etc:/usr/sbin:/usr/ucb:/usr/bin/X11:/sbin:/usr/java8_64/jre/bin:/usr/java8_64/bin:/opt/freeware/bin:/usr/symcli/bin
SHELL=/usr/bin/ksh
gdisprnimal1d(root):/# $PATH
ksh: /opt/freeware/bin/:/usr/bin:/etc:/usr/sbin:/usr/ucb:/usr/bin/X11:/sbin:/usr/java8_64/jre/bin:/usr/java8_64/bin:/opt/freeware/bin:/usr/symcli/bin: not found.
gdisprnimal1d(root):/# cd /mnt
gdisprnimal1d(root):/mnt# ls -ld httpd*
-rw-r----- 1 324 staff 4075854 Dec 02 12:11 httpd-2.4.65-1.aix7.1.ppc.rpm
gdisprnimal1d(root):/mnt# dnf update httpd
Last metadata expiration check: 20:17:52 ago on Tue Dec 2 13:06:57 CET 2025.
Dependencies resolved.
=============================================================================================================================================================
Package Architecture Version Repository Size
=============================================================================================================================================================
Upgrading:
apr ppc 1.7.4-1 Local_AIX_Toolbox 369 k
apr-util ppc 1.6.3-2 Local_AIX_Toolbox 278 k
expat ppc 2.6.3-1 Local_AIX_Toolbox 855 k
httpd ppc 2.4.63-1 Local_AIX_Toolbox 3.9 M
openldap ppc 2.5.16-3 Local_AIX_Toolbox 4.0 M
zlib ppc 1.2.13-1 Local_AIX_Toolbox 345 k
Transaction Summary
=============================================================================================================================================================
Upgrade 6 Packages
Total size: 9.7 M
Is this ok [y/N]: y
Downloading Packages:
warning: [fd 19]: Header V4 RSA/SHA256 Signature, key ID 41eea8e0: NOKEY
Local AIX generic repository 3.0 MB/s | 3.1 kB 00:00
Traceback (most recent call last):
File "/opt/freeware/bin/dnf", line 58, in <module>
main.user_main(sys.argv[1:], exit_code=True)
File "/opt/freeware/lib/python3.9/site-packages/dnf/cli/main.py", line 191, in user_main
errcode = main(args)
File "/opt/freeware/lib/python3.9/site-packages/dnf/cli/main.py", line 65, in main
return _main(base, args, cli_class, option_parser_class)
File "/opt/freeware/lib/python3.9/site-packages/dnf/cli/main.py", line 98, in _main
return cli_run(cli, base)
File "/opt/freeware/lib/python3.9/site-packages/dnf/cli/main.py", line 122, in cli_run
ret = resolving(cli, base)
File "/opt/freeware/lib/python3.9/site-packages/dnf/cli/main.py", line 166, in resolving
base.do_transaction(display=displays)
File "/opt/freeware/lib/python3.9/site-packages/dnf/cli/cli.py", line 235, in do_transaction
self.gpgsigcheck(install_pkgs)
File "/opt/freeware/lib/python3.9/site-packages/dnf/cli/cli.py", line 287, in gpgsigcheck
self._get_key_for_package(po, fn)
File "/opt/freeware/lib/python3.9/site-packages/dnf/base.py", line 2313, in _get_key_for_package
keys = dnf.crypto.retrieve(keyurl, repo)
File "/opt/freeware/lib/python3.9/site-packages/dnf/crypto.py", line 177, in retrieve
keyinfos = rawkey2infos(handle)
File "/opt/freeware/lib/python3.9/site-packages/dnf/crypto.py", line 158, in rawkey2infos
with pubring_dir(pb_dir), Context() as ctx:
File "/opt/freeware/lib/python3.9/site-packages/gpg/core.py", line 220, in __init__
self.protocol = protocol
File "/opt/freeware/lib/python3.9/site-packages/gpg/core.py", line 169, in __setattr__
super(GpgmeWrapper, self).__setattr__(key, value)
File "/opt/freeware/lib/python3.9/site-packages/gpg/core.py", line 1123, in protocol
errorcheck(gpgme.gpgme_engine_check_version(value))
File "/opt/freeware/lib/python3.9/site-packages/gpg/errors.py", line 129, in errorcheck
raise GPGMEError(retval, extradata)
gpg.errors.GPGMEError: GPGME: Invalid crypto engine
gdisprnimal1d(root):/mnt#
------------------------------
Unix Team
Original Message:
Sent: Tue December 02, 2025 08:50 AM
From: Lakshmi Surekha Kovvuri
Subject: issue while updating httpd version from httpd-2.4.54-3.ppc to httpd-2.4.65-1 using dnf
Hi,
You are currently using DNF 3.9, and the fix for this issue is available in the latest DNF 3.12.
As a workaround, you can do:
export PATH=/opt/freeware/bin/:$PATH
------------------------------
Lakshmi Surekha Kovvuri
Original Message:
Sent: Tue December 02, 2025 07:15 AM
From: Unix Team
Subject: issue while updating httpd version from httpd-2.4.54-3.ppc to httpd-2.4.65-1 using dnf
Hello Team,
I'm getting below error while updating httpd version using dnf. Please help me on this.
gdisprnimal1d(root):/mnt# dnf update httpd
Last metadata expiration check: 0:02:40 ago on Tue Dec 2 13:06:57 CET 2025.
Dependencies resolved.
=============================================================================================================================================================
Package Architecture Version Repository Size
=============================================================================================================================================================
Upgrading:
apr ppc 1.7.4-1 Local_AIX_Toolbox 369 k
apr-util ppc 1.6.3-2 Local_AIX_Toolbox 278 k
expat ppc 2.6.3-1 Local_AIX_Toolbox 855 k
httpd ppc 2.4.63-1 Local_AIX_Toolbox 3.9 M
openldap ppc 2.5.16-3 Local_AIX_Toolbox 4.0 M
zlib ppc 1.2.13-1 Local_AIX_Toolbox 345 k
Transaction Summary
=============================================================================================================================================================
Upgrade 6 Packages
Total size: 9.7 M
Is this ok [y/N]: y
Downloading Packages:
warning: [fd 19]: Header V4 RSA/SHA256 Signature, key ID 41eea8e0: NOKEY
Local AIX generic repository 3.0 MB/s | 3.1 kB 00:00
Traceback (most recent call last):
File "/opt/freeware/bin/dnf", line 58, in <module>
main.user_main(sys.argv[1:], exit_code=True)
File "/opt/freeware/lib/python3.9/site-packages/dnf/cli/main.py", line 191, in user_main
errcode = main(args)
File "/opt/freeware/lib/python3.9/site-packages/dnf/cli/main.py", line 65, in main
return _main(base, args, cli_class, option_parser_class)
File "/opt/freeware/lib/python3.9/site-packages/dnf/cli/main.py", line 98, in _main
return cli_run(cli, base)
File "/opt/freeware/lib/python3.9/site-packages/dnf/cli/main.py", line 122, in cli_run
ret = resolving(cli, base)
File "/opt/freeware/lib/python3.9/site-packages/dnf/cli/main.py", line 166, in resolving
base.do_transaction(display=displays)
File "/opt/freeware/lib/python3.9/site-packages/dnf/cli/cli.py", line 235, in do_transaction
self.gpgsigcheck(install_pkgs)
File "/opt/freeware/lib/python3.9/site-packages/dnf/cli/cli.py", line 287, in gpgsigcheck
self._get_key_for_package(po, fn)
File "/opt/freeware/lib/python3.9/site-packages/dnf/base.py", line 2313, in _get_key_for_package
keys = dnf.crypto.retrieve(keyurl, repo)
File "/opt/freeware/lib/python3.9/site-packages/dnf/crypto.py", line 177, in retrieve
keyinfos = rawkey2infos(handle)
File "/opt/freeware/lib/python3.9/site-packages/dnf/crypto.py", line 158, in rawkey2infos
with pubring_dir(pb_dir), Context() as ctx:
File "/opt/freeware/lib/python3.9/site-packages/gpg/core.py", line 220, in __init__
self.protocol = protocol
File "/opt/freeware/lib/python3.9/site-packages/gpg/core.py", line 169, in __setattr__
super(GpgmeWrapper, self).__setattr__(key, value)
File "/opt/freeware/lib/python3.9/site-packages/gpg/core.py", line 1123, in protocol
errorcheck(gpgme.gpgme_engine_check_version(value))
File "/opt/freeware/lib/python3.9/site-packages/gpg/errors.py", line 129, in errorcheck
raise GPGMEError(retval, extradata)
gpg.errors.GPGMEError: GPGME: Invalid crypto engine
gdisprnimal1d(root):/mnt#
gdisprnimal1d(root):/mnt# dnf repolist
repo id repo name
Local_AIX_Toolbox Local AIX generic repository
Local_AIX_Toolbox_72 Local AIX 7.2 specific repository
Local_AIX_Toolbox_noarch Local AIX noarch repository
gdisprnimal1d(root):/mnt#
gdisprnimal1d(root):/mnt# rpm -qa | egrep -i 'httpd|dnf'
libdnf-0.39.1-32_3.ppc
python3.9-dnf-4.2.17-32_4.noarch
dnf-4.2.17-32_4.noarch
python3.9-libdnf-0.39.1-32_3.ppc
dnf-data-4.2.17-32_4.noarch
python3-dnf-4.2.17-32_4.noarch
dnf-automatic-4.2.17-32_4.noarch
python3-libdnf-0.39.1-32_3.ppc
httpd-2.4.54-3.ppc
gdisprnimal1d(root):/mnt#
------------------------------
Unix Team
------------------------------