pidgin/pidgin

887efbd652d8
certificate: Use public key fingerprint to compare certificates

This fixes an issue with google talk's certificates and gnutls, where the root
certificate in the provided chain is a slightly different version of the one
that is usually present in the certificate stores, but the SubjectPublicKeyInfo
section is the same.

This adds a PurpleCertificateScheme function, compare_pubkeys, and its wrapper
purple_certificate_compare_pubkeys().

This is only implemented for gnutls, since the NSS plugin only uses the NSS
certificate validation code. Even if that path was reachable from a plugin that
doesn't implement this method, it would return FALSE and behave as if this bug
was never fixed.

The gnutls implementation uses the gnutls_x509_crt_get_key_id() function,
which returns a hash of the SubjectPublicKeyInfo section of the certificate.

In gnutls versions older than 3.4.1, this may be a SHA1 hash, but after that
version SHA256 support was added (without much fanfare - the documentation
barely mentions this at all), and we just use the constant for the best known
algo, which for current versions is just SHA256. Older versions ignore that
flag parameter.

The whole comparison is modeled after the private _gnutls_check_if_same_key(),
which checks if both certificates have the same DN ("unique id") and does a
memcmp() of the raw SPKI section. We don't have direct access to the raw SPKI
section but comparing their fingerprints is good enough.
# Makefile.mingw
#
# Author: hermanator12002@yahoo.com
# Date 9/11/02
# Description: Top Makefile for win32 (mingw) port of Pidgin and libpurple
#
PIDGIN_TREE_TOP := .
include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
# Generate a X.X.X.X version for the installer file versioning header
# The last digit will be 99 for a final release, 0 for dev or unknown, or the beta number
PIDGIN_PRODUCT_VERSION = $(shell \
awk 'BEGIN {FS="."} { \
if (int($$3) == $$3) { \
$$4 = "99"; \
} else { \
$$5 = $$3; \
sub(int($$3), "", $$5); \
if ($$5 == "dev") { \
$$4 = "0"; \
} else { \
if (sub("beta", "", $$5) > 0) { \
$$4 = $$5; \
} else { \
$$4 = "0"; \
} \
} \
} \
printf("%s.%s.%s.%s", $$1, $$2, int($$3), $$4); \
exit; \
}' VERSION)
GTK_INSTALL_VERSION = 2.16.6.3
ifdef SIGNTOOL
authenticode_sign = $(SIGNTOOL) sign \
/fd SHA256 \
/f "$(SIGNTOOL_PFX)" /p "$(SIGNTOOL_PASSWORD)" \
/d $(2) /du "https://pidgin.im" \
/tr "http://timestamp.comodoca.com/rfc3161" /td SHA256 \
$(1)
else
authenticode_sign = $(MONO_SIGNCODE) \
-spc "$(SIGNCODE_SPC)" -v "$(SIGNCODE_PVK)" \
-a sha1 -$$ commercial \
-n "$(2)" -i "https://pidgin.im" \
-t "http://timestamp.verisign.com/scripts/timstamp.dll" -tr 10 \
$(1) && rm -f $(1).bak
endif
gpg_sign = $(GPG_SIGN) -ab $(1) && $(GPG_SIGN) --verify $(1).asc
STRIPPED_RELEASE_DIR = $(PIDGIN_TREE_TOP)/pidgin-$(PIDGIN_VERSION)-win32bin
DEBUG_SYMBOLS_DIR = $(PIDGIN_TREE_TOP)/pidgin-$(PIDGIN_VERSION)-dbgsym
PIDGIN_INST_DEP_DIR="$(WIN32_DEV_TOP)/pidgin-inst-deps-20130214"
# Any *.dll or *.exe files included in win32-install-dir that we don't compile
# should be included in this list so they don't get stripped
EXTERNAL_DLLS = \
exchndl.dll \
freebl3.dll \
libenchant.dll \
libenchant_ispell.dll \
libenchant_myspell.dll \
libgtkspell-0.dll \
libmeanwhile-1.dll \
libnspr4.dll \
libplc4.dll \
libplds4.dll \
libssp-0.dll \
nss3.dll \
nssutil3.dll \
smime3.dll \
softokn3.dll \
sqlite3.dll \
ssl3.dll
#build an expression for `find` to use to ignore the above files
EXTERNAL_DLLS_FIND_EXP = $(patsubst %,-o -name %,$(EXTERNAL_DLLS))
include $(PIDGIN_COMMON_RULES)
.PHONY: all docs install installer installer_offline installer_zip debug_symbols_zip installers clean uninstall create_release_install_dir generate_installer_includes $(PIDGIN_REVISION_H) $(PIDGIN_REVISION_RAW_TXT) gtk_runtime_zip
all: $(PIDGIN_CONFIG_H) $(PIDGIN_REVISION_H)
$(MAKE) -C $(PURPLE_TOP) -f $(MINGW_MAKEFILE)
$(MAKE) -C $(PIDGIN_TOP) -f $(MINGW_MAKEFILE)
ifndef DISABLE_NLS
$(MAKE) -C $(PURPLE_PO_TOP) -f $(MINGW_MAKEFILE)
endif
install: all $(PIDGIN_INSTALL_DIR)
$(MAKE) -C $(PURPLE_TOP) -f $(MINGW_MAKEFILE) install
$(MAKE) -C $(PIDGIN_TOP) -f $(MINGW_MAKEFILE) install
ifndef DISABLE_NLS
$(MAKE) -C $(PURPLE_PO_TOP) -f $(MINGW_MAKEFILE) install
endif
$(MAKE) -C share/ca-certs -f $(MINGW_MAKEFILE) install
$(MAKE) -C share/sounds -f $(MINGW_MAKEFILE) install
mkdir -p $(PIDGIN_INSTALL_DIR)/spellcheck/lib/enchant
cp $(GTKSPELL_TOP)/bin/libgtkspell-0.dll $(PIDGIN_INSTALL_DIR)/spellcheck
cp $(ENCHANT_TOP)/bin/libenchant.dll $(PIDGIN_INSTALL_DIR)/spellcheck
cp -R $(ENCHANT_TOP)/lib/enchant/*.dll $(PIDGIN_INSTALL_DIR)/spellcheck/lib/enchant
cp $(PIDGIN_INST_DEP_DIR)/exchndl.dll $(PIDGIN_INSTALL_DIR)
cp $(GCC_SSP_TOP)/libssp-0.dll $(PIDGIN_INSTALL_DIR)
gtk_runtime_zip:
pidgin/win32/nsis/generate_gtk_zip.sh "`pwd`" "$(GPG_SIGN)"
generate_installer_includes: create_release_install_dir gtk_runtime_zip debug_symbols_zip $(PIDGIN_TREE_TOP)/pidgin/win32/nsis/nsis_translations.desktop
rm -f pidgin/win32/nsis/pidgin-translations.nsh pidgin/win32/nsis/pidgin-spellcheck.nsh pidgin/win32/nsis/pidgin-spellcheck-preselect.nsh
find $(STRIPPED_RELEASE_DIR)/locale -maxdepth 1 -mindepth 1 \
-exec basename {} ';' \
| LC_ALL=C sort | sed -e s/^/\!insertmacro\ LANG_SECTION\ \"/ -e s/$$/\"/ \
> pidgin/win32/nsis/pidgin-translations.nsh
#Convert the available.lst lines to "!insertmacro SPELLCHECK_SECTION lang lang_name lang_file"
sed -e "/^#/d" -e "s/^[^,]\{1,\},[^,]\{1,\},/\"/" \
-e "s/,/\"\ \"/" -e "s/,/\"\ \"/" -e "s/[\ \t]*$$/\"/" \
-e "s/^/\!insertmacro\ SPELLCHECK_SECTION\ /" \
pidgin/win32/nsis/available.lst \
> pidgin/win32/nsis/pidgin-spellcheck.nsh
#Convert the lines to "!insertmacro CHECK_SPELLCHECK_SECTION lang"
iconv -f latin1 -t utf-8 pidgin/win32/nsis/pidgin-spellcheck.nsh | \
sed -e "s/SPELLCHECK_SECTION/CHECK_SPELLCHECK_SECTION/" \
-e "s/ \"[^\"]*\"\ \"[^\"]*\"[\t\ ]*$$//" | \
iconv -f utf-8 -t latin1 \
> pidgin/win32/nsis/pidgin-spellcheck-preselect.nsh
#Generate the Installer translations
echo "!define GCOMPRIS_NSIS_INCLUDE_PATH \".\"" > $(PIDGIN_TREE_TOP)/pidgin/win32/nsis/langmacros.nsh
echo "@INSERT_TRANSLATIONS@" >> $(PIDGIN_TREE_TOP)/pidgin/win32/nsis/langmacros.nsh
$(PERL) $(PIDGIN_TREE_TOP)/pidgin/win32/nsis/create_nsis_translations.pl \
$(PIDGIN_TREE_TOP)/pidgin/win32/nsis/nsis_translations.desktop \
$(PIDGIN_TREE_TOP)/pidgin/win32/nsis/langmacros.nsh \
$(PIDGIN_TREE_TOP)/pidgin/win32/nsis/translations
create_release_install_dir: install
rm -rf $(STRIPPED_RELEASE_DIR)
mkdir $(STRIPPED_RELEASE_DIR)
tar -cf - $(PIDGIN_INSTALL_DIR) --exclude=Gtk --exclude=spellcheck/share \
| tar --strip 2 -xC $(STRIPPED_RELEASE_DIR) -f -
find $(STRIPPED_RELEASE_DIR) \( -name '*.dll' -o -name '*.exe' \) \
-not \( -false $(EXTERNAL_DLLS_FIND_EXP) \) \
-exec $(STRIP) --strip-unneeded {} ';'
$(call authenticode_sign, $(STRIPPED_RELEASE_DIR)/pidgin.exe, "Pidgin $(PIDGIN_VERSION)")
installer: generate_installer_includes
$(eval $@_DEBUG_SYMBOLS_SHA1SUM := $(shell sha1sum $(DEBUG_SYMBOLS_DIR).zip | sed -e "s/\ .*$$//"))
$(eval $@_GTK_SHA1SUM := $(shell sha1sum pidgin/win32/nsis/gtk-runtime-$(GTK_INSTALL_VERSION).zip | sed -e "s/\ .*$$//"))
$(MAKENSIS) -V3 -DPIDGIN_VERSION="$(PIDGIN_VERSION)" -DPIDGIN_PRODUCT_VERSION="$(PIDGIN_PRODUCT_VERSION)" \
-DPIDGIN_INSTALL_DIR="$(STRIPPED_RELEASE_DIR)" -DGTK_INSTALL_VERSION="$(GTK_INSTALL_VERSION)" \
-DDEBUG_SYMBOLS_SHA1SUM="$($@_DEBUG_SYMBOLS_SHA1SUM)" -DGTK_SHA1SUM="$($@_GTK_SHA1SUM)"\
pidgin/win32/nsis/pidgin-installer.nsi
$(call authenticode_sign, pidgin/win32/nsis/pidgin-$(PIDGIN_VERSION).exe, "Pidgin Installer")
mv pidgin/win32/nsis/pidgin-$(PIDGIN_VERSION).exe ./
$(call gpg_sign, pidgin-$(PIDGIN_VERSION).exe)
installer_offline: generate_installer_includes
$(MAKENSIS) -V3 -DPIDGIN_VERSION="$(PIDGIN_VERSION)" -DPIDGIN_PRODUCT_VERSION="$(PIDGIN_PRODUCT_VERSION)" \
-DPIDGIN_INSTALL_DIR="$(STRIPPED_RELEASE_DIR)" -DGTK_INSTALL_VERSION="$(GTK_INSTALL_VERSION)" \
-DOFFLINE_INSTALLER \
pidgin/win32/nsis/pidgin-installer.nsi
$(call authenticode_sign, pidgin/win32/nsis/pidgin-$(PIDGIN_VERSION)-offline.exe, "Pidgin Installer")
mv pidgin/win32/nsis/pidgin-$(PIDGIN_VERSION)-offline.exe ./
$(call gpg_sign, pidgin-$(PIDGIN_VERSION)-offline.exe)
installer_zip: create_release_install_dir
rm -f pidgin-$(PIDGIN_VERSION)-win32-bin.zip
zip -9 -r pidgin-$(PIDGIN_VERSION)-win32-bin.zip $(STRIPPED_RELEASE_DIR)
$(call gpg_sign, pidgin-$(PIDGIN_VERSION)-win32-bin.zip)
debug_symbols_zip: install
rm -rf $(DEBUG_SYMBOLS_DIR) $(DEBUG_SYMBOLS_DIR).zip
mkdir $(DEBUG_SYMBOLS_DIR)
tar -cf - `find $(PIDGIN_INSTALL_DIR) \( -name '*.dll' -o -name '*.exe' \) \
-not \( -false $(EXTERNAL_DLLS_FIND_EXP) \) -print` \
| tar --strip 2 --xform s/$$/.dbgsym/ -xC $(DEBUG_SYMBOLS_DIR) -f -
cp $(MEANWHILE_TOP)/bin/libmeanwhile-1.dll.unstripped $(DEBUG_SYMBOLS_DIR)/libmeanwhile-1.dll.dbgsym
zip -9 -r $(DEBUG_SYMBOLS_DIR).zip $(DEBUG_SYMBOLS_DIR)
$(call gpg_sign, $(DEBUG_SYMBOLS_DIR).zip)
installers: installer installer_offline debug_symbols_zip installer_zip
Doxyfile.mingw: Doxyfile.in
sed -e "s/@PACKAGE@/pidgin/" -e "s/@VERSION@/$(PIDGIN_VERSION)/" -e "s/@top_srcdir@/$(PIDGIN_TREE_TOP)/g" -e "s/@enable_dot@/NO/" $< > $@
docs: Doxyfile.mingw
@echo "Running doxygen..."
@doxygen Doxyfile.mingw
clean:
$(MAKE) -C $(PURPLE_PO_TOP) -f $(MINGW_MAKEFILE) clean
$(MAKE) -C $(PIDGIN_TOP) -f $(MINGW_MAKEFILE) clean
$(MAKE) -C $(PURPLE_TOP) -f $(MINGW_MAKEFILE) clean
$(MAKE) -C share/ca-certs -f $(MINGW_MAKEFILE) clean
rm -f $(PIDGIN_CONFIG_H) $(PIDGIN_REVISION_H) $(PIDGIN_REVISION_RAW_TXT) ./VERSION pidgin-$(PIDGIN_VERSION)*.exe pidgin-$(PIDGIN_VERSION)-win32-bin.zip $(DEBUG_SYMBOLS_DIR).zip
rm -rf doc/html Doxyfile.mingw
uninstall:
rm -rf $(PURPLE_INSTALL_PERL_DIR) $(PIDGIN_INSTALL_PLUGINS_DIR) $(PURPLE_INSTALL_PO_DIR) $(PIDGIN_INSTALL_DIR) $(STRIPPED_RELEASE_DIR) $(DEBUG_SYMBOLS_DIR)
rm -f ./VERSION
include $(PIDGIN_COMMON_TARGETS)