Bug#1119802: sasl-xoauth2 fails token refresh with code=0 when linked against libcurl 8.17

Martin Pitt <[email protected]>
Newsgroups gmane.linux.debian.devel.bugs.rc
Message-ID <[email protected]>
Control: tag -1 fixed-upstream pending

Hello Etienne and Daniel,

Etienne Dechamps [2025-10-31 14:32 +0000]:
> After upgrading the libcurl4t64 package from 8.16.0-1 to 8.17.0~rc3-1,
> sasl-xoauth2 stopped working.
> [...]
> This is being investigated upstream and I already sent in a patch:
> https://github.com/tarickb/sasl-xoauth2/issues/115

Thanks! I am currently moving my mbsync config from an app password to oauth2,
and this is a really nice tool.

As this package looks unmaintained, I took the liberty to do a DELAYED/7 upload
that updates to the latest upstream version 0.27 and cherry-picks the patch for
this:

  https://github.com/tarickb/sasl-xoauth2/commit/dc77ca4fb9a4e283d738dcbd6710e693454d9fcf

debian/* only debdiff attached.

@ Daniel: If you agree, I'm also happy to re-upload immediately.

Thanks!

Martin
sasl-xoauth2_0.27-0.1.debdiff (text/plain, 6.3 KB)
diff -Nru sasl-xoauth2-0.20/debian/changelog sasl-xoauth2-0.27/debian/changelog
--- sasl-xoauth2-0.20/debian/changelog	2023-05-30 23:30:18.000000000 +0200
+++ sasl-xoauth2-0.27/debian/changelog	2026-08-16 15:57:26.000000000 +0200
@@ -1,3 +1,13 @@
+sasl-xoauth2 (0.27-0.1) experimental; urgency=medium
+
+  * Non-maintainer upload.
+  * New upstream release.
+  * Add new python3-msal build dependency for the new version.
+  * Add 0001-fix-curl_easy_getinfo.patch: Fix refresh token with libcurl 8.17.
+    Patch backported from upstream master. (Closes: #1119802)
+
+ -- Martin Pitt <[email protected]>  Sun, 16 Aug 2026 15:57:26 +0200
+
 sasl-xoauth2 (0.20-1) experimental; urgency=medium
 
   * new upstream version
diff -Nru sasl-xoauth2-0.20/debian/control sasl-xoauth2-0.27/debian/control
--- sasl-xoauth2-0.20/debian/control	2023-05-30 23:30:18.000000000 +0200
+++ sasl-xoauth2-0.27/debian/control	2026-08-16 15:57:26.000000000 +0200
@@ -13,6 +13,7 @@
  pkg-config,
  python3-argcomplete,
  python3-argparse-manpage,
+ python3-msal,
  python3-setuptools,
 Standards-Version: 4.6.2
 Homepage: https://github.com/tarickb/sasl-xoauth2
diff -Nru sasl-xoauth2-0.20/debian/patches/0001-fix-curl_easy_getinfo.patch sasl-xoauth2-0.27/debian/patches/0001-fix-curl_easy_getinfo.patch
--- sasl-xoauth2-0.20/debian/patches/0001-fix-curl_easy_getinfo.patch	1970-01-01 01:00:00.000000000 +0100
+++ sasl-xoauth2-0.27/debian/patches/0001-fix-curl_easy_getinfo.patch	2026-08-16 15:56:40.000000000 +0200
@@ -0,0 +1,120 @@
+From 456c907bbc1a431af2726c1aac61bb6921c2e561 Mon Sep 17 00:00:00 2001
+From: Etienne Dechamps <[email protected]>
+Date: Fri, 31 Oct 2025 14:18:45 +0000
+Subject: [PATCH] Fix curl_easy_getinfo() called after cleanup
+
+Fixes #115.
+
+Also, use RAII to manage the CURL handle so that cleanup occurs
+automatically even in the case of early return.
+---
+ src/http.cc | 49 +++++++++++++++++++++++++++----------------------
+ 1 file changed, 27 insertions(+), 22 deletions(-)
+
+diff --git a/src/http.cc b/src/http.cc
+index 8381d3e..5efaa0e 100644
+--- a/src/http.cc
++++ b/src/http.cc
+@@ -18,12 +18,18 @@
+ #include <sasl/sasl.h>
+ #include <string.h>
+ 
++#include <memory>
+ #include <vector>
+ 
+ namespace sasl_xoauth2 {
+ 
+ namespace {
+ 
++struct CURLDeleter final {
++  void operator()(CURL *curl) const { curl_easy_cleanup(curl); }
++};
++using UniqueCURL = std::unique_ptr<CURL, CURLDeleter>;
++
+ constexpr char kUserAgent[] = "sasl xoauth2 token refresher";
+ 
+ class RequestContext {
+@@ -93,7 +99,7 @@ int HttpPost(HttpPostOptions options) {
+   *options.response_code = 0;
+   options.response->clear();
+ 
+-  CURL *curl = curl_easy_init();
++  UniqueCURL curl(curl_easy_init());
+   if (!curl) {
+     *options.error = "Unable to create CURL handle.";
+     return SASL_BADPROT;
+@@ -104,46 +110,45 @@ int HttpPost(HttpPostOptions options) {
+   char transport_error[CURL_ERROR_SIZE] = {'\0'};
+ 
+   // Behavior.
+-  curl_easy_setopt(curl, CURLOPT_VERBOSE, false);
+-  curl_easy_setopt(curl, CURLOPT_NOPROGRESS, true);
+-  curl_easy_setopt(curl, CURLOPT_NOSIGNAL, true);
++  curl_easy_setopt(curl.get(), CURLOPT_VERBOSE, false);
++  curl_easy_setopt(curl.get(), CURLOPT_NOPROGRESS, true);
++  curl_easy_setopt(curl.get(), CURLOPT_NOSIGNAL, true);
+ 
+   // Errors.
+-  curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, transport_error);
++  curl_easy_setopt(curl.get(), CURLOPT_ERRORBUFFER, transport_error);
+ 
+   // Network.
+-  curl_easy_setopt(curl, CURLOPT_URL, options.url.c_str());
++  curl_easy_setopt(curl.get(), CURLOPT_URL, options.url.c_str());
+ 
+   // Certs.
+   if (options.ca_certs_dir.empty()) {
+     if (options.ca_bundle_file.empty()) {
+       // Use default CA location.
+     } else {
+-      curl_easy_setopt(curl, CURLOPT_CAINFO, options.ca_bundle_file.c_str());
++      curl_easy_setopt(curl.get(), CURLOPT_CAINFO, options.ca_bundle_file.c_str());
+     }
+   } else {
+-    curl_easy_setopt(curl, CURLOPT_CAPATH, options.ca_certs_dir.c_str());
++    curl_easy_setopt(curl.get(), CURLOPT_CAPATH, options.ca_certs_dir.c_str());
+   }
+ 
+   // HTTP.
+-  curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, true);
+-  curl_easy_setopt(curl, CURLOPT_USERAGENT, kUserAgent);
++  curl_easy_setopt(curl.get(), CURLOPT_FOLLOWLOCATION, true);
++  curl_easy_setopt(curl.get(), CURLOPT_USERAGENT, kUserAgent);
+   if (!options.proxy.empty())
+-    curl_easy_setopt(curl, CURLOPT_PROXY, options.proxy.c_str());
+-  curl_easy_setopt(curl, CURLOPT_POST, true);
+-  curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE,
++    curl_easy_setopt(curl.get(), CURLOPT_PROXY, options.proxy.c_str());
++  curl_easy_setopt(curl.get(), CURLOPT_POST, true);
++  curl_easy_setopt(curl.get(), CURLOPT_POSTFIELDSIZE_LARGE,
+                    static_cast<curl_off_t>(context.to_server_size()));
+ 
+   // Callbacks.
+-  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &RequestContext::Write);
+-  curl_easy_setopt(curl, CURLOPT_WRITEDATA, &context);
+-  curl_easy_setopt(curl, CURLOPT_READFUNCTION, &RequestContext::Read);
+-  curl_easy_setopt(curl, CURLOPT_READDATA, &context);
+-  curl_easy_setopt(curl, CURLOPT_SEEKFUNCTION, &RequestContext::Seek);
+-  curl_easy_setopt(curl, CURLOPT_SEEKDATA, &context);
++  curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION, &RequestContext::Write);
++  curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, &context);
++  curl_easy_setopt(curl.get(), CURLOPT_READFUNCTION, &RequestContext::Read);
++  curl_easy_setopt(curl.get(), CURLOPT_READDATA, &context);
++  curl_easy_setopt(curl.get(), CURLOPT_SEEKFUNCTION, &RequestContext::Seek);
++  curl_easy_setopt(curl.get(), CURLOPT_SEEKDATA, &context);
+ 
+-  CURLcode err = curl_easy_perform(curl);
+-  curl_easy_cleanup(curl);
++  CURLcode err = curl_easy_perform(curl.get());
+ 
+   if (err != CURLE_OK) {
+     *options.error = transport_error;
+@@ -154,7 +159,7 @@ int HttpPost(HttpPostOptions options) {
+     return SASL_BADPROT;
+   }
+ 
+-  curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, options.response_code);
++  curl_easy_getinfo(curl.get(), CURLINFO_RESPONSE_CODE, options.response_code);
+   *options.response = context.from_server();
+   return SASL_OK;
+ }
diff -Nru sasl-xoauth2-0.20/debian/patches/series sasl-xoauth2-0.27/debian/patches/series
--- sasl-xoauth2-0.20/debian/patches/series	1970-01-01 01:00:00.000000000 +0100
+++ sasl-xoauth2-0.27/debian/patches/series	2026-08-16 15:57:10.000000000 +0200
@@ -0,0 +1 @@
+0001-fix-curl_easy_getinfo.patch
signature.asc (application/pgp-signature, 833 B)
-----BEGIN PGP SIGNATURE-----

iQIzBAABCgAdFiEEbEuHi35jHxYFV8PN7nvd5LhrVxMFAmqB0/gACgkQ7nvd5Lhr
VxPyGA//WhM7HQwMN8o/I4q+kDk0sxBRDahCeAAjd0qe+4Z5DmC2uCQMfw4X3uzS
EuPEYzY91nXQRI/fRD5NPvMbEW9TsGF1CslCnwT8CVf+TTYKR0uFYZFc/ZaytRVi
b60PqVovwgTfe1danodEHvG+K3LrQg+51V23cInnAjjw8vx2QJ9gG+w8k8e0CFNo
CVQc6YO8VQyc7w7CojXg3AVzkajxnL81I2KjjWeixysqKt0WtTSW6p8ldEa0p1ZF
m0TWTLur+pNQvtytNw7IjOsndkKZ/tD8PUeKJWqDpa2cnjBEuTc+/YJRovXeEJj1
Q29NqdcizICfu17IXa8LuaOheMKEJVTCBJWK/aLssuEC5K4psLe0lZxopVJcpcYn
oyg3sKHZH516yGmB3n7HjJm8dMHQ6UPl52tBrnf2JyD9dDQun4XrRRia5jSuf0Ti
8M16PWF4QAmo0V4GZ20QF89FgCbj5TYaT8sdfOuX/lwdurXBiaU/JFzFy7CznVN3
dTMLj7sF3P9tFAKO2swrszlf5qH72vPdXr+U/j447qtzPaD5ux2lrReRmWiLop0+
kTh6996xHuc3IfiFYVzPSghHMKApJbwM6tIIHPUmTIxeEVUT2X0OTTifuYh3luxP
+ufv8GBNXQcUcw6H1/CV39K2LFBvpL/qvZVVWaceI9dlDB7NEtc=
=IbUn
-----END PGP SIGNATURE-----
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.