GNU bug report logs - #72441
31.0.50; Auth-source-pass doesn't match password attributes or hosts without user when extra-query-keywords is true

Please note: This is a static page, with minimal formatting, updated once a day.
Click here to see this page with the latest information and nicer formatting.

Package: emacs; Reported by: Björn Bidar <bjorn.bidar@HIDDEN>; dated Sat, 3 Aug 2024 11:14:01 UTC; Maintainer for emacs is bug-gnu-emacs@HIDDEN.

Message received at 72441 <at> debbugs.gnu.org:


Received: (at 72441) by debbugs.gnu.org; 6 Sep 2024 23:16:48 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Fri Sep 06 19:16:48 2024
Received: from localhost ([127.0.0.1]:54382 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1smiC7-00074W-Rx
	for submit <at> debbugs.gnu.org; Fri, 06 Sep 2024 19:16:48 -0400
Received: from mail-108-mta162.mxroute.com ([136.175.108.162]:44125)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <jp@HIDDEN>) id 1smiC5-00074C-RK
 for 72441 <at> debbugs.gnu.org; Fri, 06 Sep 2024 19:16:46 -0400
Received: from filter006.mxroute.com ([136.175.111.3] filter006.mxroute.com)
 (Authenticated sender: mN4UYu2MZsgR)
 by mail-108-mta162.mxroute.com (ZoneMTA) with ESMTPSA id
 191c9a0308f0003e01.001 for <72441 <at> debbugs.gnu.org>
 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384);
 Fri, 06 Sep 2024 23:16:44 +0000
X-Zone-Loop: 04f81c8496d038500cebcd59d07baf91b724a1286753
X-Originating-IP: [136.175.111.3]
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me
 ; s=x;
 h=Content-Type:MIME-Version:Message-ID:Date:References:In-Reply-To:
 Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID:
 Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc
 :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe:
 List-Post:List-Owner:List-Archive;
 bh=OZFgeSVHgF6e0aoLUy2nXencfzpL5tZuVpxRL4ObzlY=; b=Nf1jds9eHbh5w5P6pOGk7VsWvC
 Vyn906F0bCatC2PJtesUTTT2HhoGcR9xiB8yQ3GcJHsMKrxdiXJGmA8yYrFzrVMpIZDQPCjKznGJS
 WZ6iA4jSdlxaFDHvAh03J/ERNH8HgTAfLV2kzGt7RG3T2VVGEcVoeRQde2k67dD2a+QQTfCLCs8qR
 2Yo064+rsYAfkpnpqZ538Gwz3FzbJXxMQ2SG1wQ/Y+LY78uxrVhzTXINxEWP3A3a8zzzcFPT8Vh0B
 ftyH420Be2LeXIEEsgJYl+E996oDoxdxel78ByTs9IXWWW1d10vcIYa8BNSwDID6dO+tmmPYwyB3m
 7ok/dHdw==;
From: "J.P." <jp@HIDDEN>
To: 72441 <at> debbugs.gnu.org
Subject: Re: bug#72441: 31.0.50; Auth-source-pass doesn't match password
 attributes or hosts without user when extra-query-keywords is true
In-Reply-To: <874j7pedsz.fsf@HIDDEN> (J. P.'s message of "Mon, 12 Aug
 2024 12:33:48 -0700")
References: <17083.4807607875$1722683645@HIDDEN>
 <87frrdvaku.fsf@HIDDEN> <877ccoo4x8.fsf@HIDDEN>
 <874j7pedsz.fsf@HIDDEN>
Date: Fri, 06 Sep 2024 16:16:41 -0700
Message-ID: <875xr82x0m.fsf@HIDDEN>
User-Agent: Gnus/5.13 (Gnus v5.13)
MIME-Version: 1.0
Content-Type: text/plain
X-Authenticated-Id: masked@HIDDEN
X-Spam-Score: -0.0 (/)
X-Debbugs-Envelope-To: 72441
Cc: =?utf-8?Q?Bj=C3=B6rn?= Bidar <bjorn.bidar@HIDDEN>
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

"J.P." <jp@HIDDEN> writes:

> While exploring ways to tackle this feature, I stumbled on a couple
> minor bugs related to `auth-source-pass-extra-query-keywords'.
>
> Because there's no telling when we'll end up with something installable
> for this feature, I've gone ahead and isolated the fixes into a separate
> patch (0001 in the attached). It's probably safe enough for Emacs 30,
> but since the option was introduced back in 29, I'll just install it on
> master (unless I hear otherwise in the coming days). Thanks.

Installed on master as

  https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=80228d1f

As previously mentioned, the above commit only addresses an ancillary
issue, so the bug should remain open.




Information forwarded to bug-gnu-emacs@HIDDEN:
bug#72441; Package emacs. Full text available.

Message received at 72441 <at> debbugs.gnu.org:


Received: (at 72441) by debbugs.gnu.org; 12 Aug 2024 19:34:33 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Mon Aug 12 15:34:33 2024
Received: from localhost ([127.0.0.1]:43848 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1sdaoH-0000ju-NW
	for submit <at> debbugs.gnu.org; Mon, 12 Aug 2024 15:34:33 -0400
Received: from mail-108-mta165.mxroute.com ([136.175.108.165]:44963)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <jp@HIDDEN>) id 1sdaoD-0000ji-C3
 for 72441 <at> debbugs.gnu.org; Mon, 12 Aug 2024 15:34:27 -0400
Received: from filter006.mxroute.com ([136.175.111.3] filter006.mxroute.com)
 (Authenticated sender: mN4UYu2MZsgR)
 by mail-108-mta165.mxroute.com (ZoneMTA) with ESMTPSA id
 191481528200000a78.001 for <72441 <at> debbugs.gnu.org>
 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384);
 Mon, 12 Aug 2024 19:33:51 +0000
X-Zone-Loop: 147a1a39328cccf6e60875e7f1d3b521c83eab0ba0f0
X-Originating-IP: [136.175.111.3]
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me
 ; s=x;
 h=Content-Type:MIME-Version:Message-ID:Date:References:In-Reply-To:
 Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID:
 Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc
 :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe:
 List-Post:List-Owner:List-Archive;
 bh=Ed9Sry5fb7GnaO7k1sC52UBxaIDOMW4IyilFaEC0VgY=; b=EMTb1fNRx5+LP3JHTn0WkF4kFw
 g6Cx9xsKl01HLHH/jdm8WCpl9sxzkjRMXdDEdwNdZiogUqFccc/bWEZxnswFVe8OvfWam/swYpISO
 FeuUq7cph3hypT8Cd9KkhcHRo6p6ULhnPAG+OvWu2Q3hVTz0D7gbIu0l7K37Yw7zui1ofAgxm06j6
 EA00KDfgw4UfliGTxcxT8YEov0DUkSUe6s29/ksjg/QiHv1Zz7EtJEoXPHwNivPn7Dek9r5Nkll39
 4lQPXYQ29FyJFgJneaIz+HVDhq/NX1Q/PuGMFKr3cGrLiFkbf7TVb90t9mHusXuy2abUWnCZyYNeZ
 /VvbUhQw==;
From: "J.P." <jp@HIDDEN>
To: 72441 <at> debbugs.gnu.org
Subject: Re: bug#72441: 31.0.50; Auth-source-pass doesn't match password
 attributes or hosts without user when extra-query-keywords is true
In-Reply-To: <877ccoo4x8.fsf@HIDDEN> (J. P.'s message of "Sat, 10 Aug
 2024 06:58:43 -0700")
References: <17083.4807607875$1722683645@HIDDEN>
 <87frrdvaku.fsf@HIDDEN> <877ccoo4x8.fsf@HIDDEN>
Date: Mon, 12 Aug 2024 12:33:48 -0700
Message-ID: <874j7pedsz.fsf@HIDDEN>
User-Agent: Gnus/5.13 (Gnus v5.13)
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="=-=-="
X-Authenticated-Id: masked@HIDDEN
X-Spam-Score: 0.0 (/)
X-Debbugs-Envelope-To: 72441
Cc: =?utf-8?Q?Bj=C3=B6rn?= Bidar <bjorn.bidar@HIDDEN>
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

--=-=-=
Content-Type: text/plain

While exploring ways to tackle this feature, I stumbled on a couple
minor bugs related to `auth-source-pass-extra-query-keywords'.

Because there's no telling when we'll end up with something installable
for this feature, I've gone ahead and isolated the fixes into a separate
patch (0001 in the attached). It's probably safe enough for Emacs 30,
but since the option was introduced back in 29, I'll just install it on
master (unless I hear otherwise in the coming days). Thanks.


--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment; filename=0000-v2-v3.diff

From d9bd10debf6c3930669aedb896026f9f19b54466 Mon Sep 17 00:00:00 2001
From: "F. Jason Park" <jp@HIDDEN>
Date: Mon, 12 Aug 2024 07:00:23 -0700
Subject: [PATCH 0/2] *** NOT A PATCH ***

*** BLURB HERE ***

F. Jason Park (2):
  Fix deviations in auth-source-pass behavior WRT netrc
  [POC] Match attrs with auth-source-pass-extra-query-keywords

 lisp/auth-source-pass.el            | 146 ++++++++++++++++++++--------
 test/lisp/auth-source-pass-tests.el | 138 +++++++++++++++++++++++++-
 2 files changed, 237 insertions(+), 47 deletions(-)

Interdiff:
diff --git a/lisp/auth-source-pass.el b/lisp/auth-source-pass.el
index 0df7817f501..a52dafc5ab2 100644
--- a/lisp/auth-source-pass.el
+++ b/lisp/auth-source-pass.el
@@ -266,9 +266,10 @@ auth-source-pass--cast-port
 
 (defun auth-source-pass--match-parts (cache key reference require)
   (let ((value (plist-get cache key)))
-    (if (memq key require)
-        (if reference (equal value reference) value)
-      (or (null reference) (null value) (equal value reference)))))
+    (cond ((memq key require)
+           (if reference (equal value reference) value))
+          ((and value reference) (equal value reference))
+          (t))))
 
 (defvar auth-source-pass-check-attrs-with-extra-query-keywords t
   "When non-nil, decrypt files to find attributes matching parameters.
diff --git a/test/lisp/auth-source-pass-tests.el b/test/lisp/auth-source-pass-tests.el
index c6662cd8b42..695635299f9 100644
--- a/test/lisp/auth-source-pass-tests.el
+++ b/test/lisp/auth-source-pass-tests.el
@@ -548,6 +548,44 @@ auth-source-pass-extra-query-keywords--wild-port-hit
                      '((:host "x.com" :secret "a")
                        (:host "x.com" :port 42 :secret "b")))))))
 
+;; The query requires a user and doesn't specify a user to match against.
+;; The only entry matching the host lacks a user, so the search fails.
+
+(ert-deftest auth-source-pass-extra-query-keywords--req-noparam-miss-netrc ()
+  (ert-with-temp-file netrc-file
+    :text "machine foo password a\n"
+    (let ((auth-sources (list netrc-file))
+          (auth-source-do-cache nil))
+      (should-not (auth-source-search :host "foo" :require '(:user) :max 2)))))
+
+(ert-deftest auth-source-pass-extra-query-keywords--req-noparam-miss ()
+  (let ((auth-source-pass-extra-query-keywords t))
+    (auth-source-pass--with-store '(("foo" (secret . "a")))
+      (auth-source-pass-enable)
+      (should-not (auth-source-search :host "foo" :require '(:user) :max 2)))))
+
+;; The query requires a user but does not provide a reference value to
+;; match against.  An entry matching the host that specifies a user is
+;; selected because any user will do.
+(ert-deftest auth-source-pass-extra-query-keywords--req-param-netrc ()
+  (ert-with-temp-file netrc-file
+    :text "machine foo login bob password a\n"
+    (let* ((auth-sources (list netrc-file))
+           (auth-source-do-cache nil)
+           (results (auth-source-search :host "foo" :require '(:user))))
+      (dolist (result results)
+        (setf (plist-get result :secret) (auth-info-password result)))
+      (should (equal results '((:host "foo" :user "bob" :secret "a")))))))
+
+(ert-deftest auth-source-pass-extra-query-keywords--req-param ()
+  (let ((auth-source-pass-extra-query-keywords t))
+    (auth-source-pass--with-store '(("foo/bob" (secret . "a")))
+      (auth-source-pass-enable)
+      (let ((results (auth-source-search :host "foo" :require '(:user))))
+        (dolist (result results)
+          (setf (plist-get result :secret) (auth-info-password result)))
+        (should (equal results '((:host "foo" :user "bob" :secret "a"))))))))
+
 ;; No entry has the requested port, but :port is required, so search fails.
 
 (ert-deftest auth-source-pass-extra-query-keywords--wild-port-req-miss-netrc ()
@@ -601,7 +639,7 @@ auth-source-pass-extra-query-keywords--akib
       (should (equal results
                      '((:host "disroot.org" :user "akib" :secret "b")))))))
 
-(ert-deftest auth-source-pass-extra-query-keywords--akib/attr ()
+(ert-deftest auth-source-pass-extra-query-keywords--akib-attr ()
   (auth-source-pass--with-store '(("x.com" (secret . "a"))
                                   ("disroot.org" (secret . "b")
                                    ("user" . "akib") ("port" . "42"))
@@ -638,23 +676,7 @@ auth-source-pass-extra-query-keywords--akib/attr
                      '(( :host "disroot.org" :user "akib"
                          :port 42 :secret "b")))))))
 
-(ert-deftest auth-source-pass-extra-query-keywords--netrc-akib/require ()
-  (ert-with-temp-file netrc-file
-    :text "\
-machine x.com password a
-machine disroot.org user akib password b
-machine z.com password c
-"
-    (let* ((auth-sources (list netrc-file))
-           (auth-source-do-cache nil)
-           (results (auth-source-search :host "disroot.org"
-                                        :require '(:user) :max 2)))
-      (dolist (result results)
-        (setf (plist-get result :secret) (auth-info-password result)))
-      (should (equal results
-                     '((:host "disroot.org" :user "akib" :secret "b")))))))
-
-(ert-deftest auth-source-pass-extra-query-keywords--akib/attr/require ()
+(ert-deftest auth-source-pass-extra-query-keywords--akib-attr-req ()
   (auth-source-pass--with-store '(("x.com" (secret . "a"))
                                   ("disroot.org" (secret . "b")
                                    ("user" . "akib"))
@@ -668,7 +690,23 @@ auth-source-pass-extra-query-keywords--akib/attr/require
       (should (equal results
                      '((:host "disroot.org" :user "akib" :secret "b")))))))
 
-(ert-deftest auth-source-pass-extra-query-keywords--akib/attr/extras ()
+(ert-deftest auth-source-pass-extra-query-keywords--akib-attr-extras-netrc ()
+  (ert-with-temp-file netrc-file
+    :text "\
+machine x.com password a
+machine disroot.org user akib port 42 password b foo 1 bar 2
+machine z.com password c
+"
+    (let* ((auth-sources (list netrc-file))
+           (auth-source-do-cache nil)
+           (results (auth-source-search :host "disroot.org" :max 2)))
+      (dolist (result results)
+        (setf (plist-get result :secret) (auth-info-password result)))
+      (should (equal results
+                     '((:host "disroot.org" :user "akib" :port "42"
+                              :secret "b" :foo "1" :bar "2")))))))
+
+(ert-deftest auth-source-pass-extra-query-keywords--akib-attr-extras ()
   (auth-source-pass--with-store '(("x.com" (secret . "a"))
                                   ("disroot.org" (secret . "b")
                                    ("user" . "akib")
@@ -713,8 +751,8 @@ auth-source-pass-extra-query-keywords--host
                      '((:host "Libera.Chat" :secret "b")))))))
 
 
-;; A retrieved store entry mustn't be nil regardless of whether its
-;; path contains port or user components.
+;; An effectively empty entry in the store returns nothing but the
+;; :host field matching the given host parameter.
 
 (ert-deftest auth-source-pass-extra-query-keywords--netrc-baseline ()
   (ert-with-temp-file netrc-file
-- 
2.46.0


--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment;
 filename=0001-Fix-deviations-in-auth-source-pass-behavior-WRT-netr.patch

From 1aa0f941d79b77de4a87a8043f13607c0719f5d0 Mon Sep 17 00:00:00 2001
From: "F. Jason Park" <jp@HIDDEN>
Date: Sun, 11 Aug 2024 21:55:32 -0700
Subject: [PATCH 1/2] Fix deviations in auth-source-pass behavior WRT netrc

The option `auth-source-pass-extra-query-keywords' aims to make this
back end hew as close to the other built-in ones as possible, except
WRT features not yet implemented, such as arbitrary "attribute"
retrieval and new entry creation.  This change only concerns behavior
exhibited when the option is enabled.

* lisp/auth-source-pass.el (auth-source-pass--match-parts): Account
for the case in which a query lacks a reference parameter for a
`:port' or `:user' but still requires one or both via the `:require'
keyword.  Previously, such a query would fail even when an entry met
this requirement by simply specifying a field with any non-null value
corresponding to the required parameter.
(auth-source-pass--find-match-many): Account for the baseline case
where a matching entry lacks a secret and the user doesn't require
one.  Although this function doesn't currently return so-called
"attributes" from the contents of a matching decrypted file, were it
to eventually, this case would no longer be academic.
* test/lisp/auth-source-pass-tests.el
(auth-source-pass-extra-query-keywords--req-noparam-miss-netrc)
(auth-source-pass-extra-query-keywords--req-noparam-miss)
(auth-source-pass-extra-query-keywords--req-param-netrc)
(auth-source-pass-extra-query-keywords--req-param): New tests.
(auth-source-pass-extra-query-keywords--netrc-baseline): New test
asserting behavior of netrc backend when passed a lone `:host' as a
query parameter.
(auth-source-pass-extra-query-keywords--baseline): Reverse expected
outcome to match that of the netrc reference
implementation.  (bug#72441)
---
 lisp/auth-source-pass.el            | 19 +++++-----
 test/lisp/auth-source-pass-tests.el | 54 ++++++++++++++++++++++++++---
 2 files changed, 60 insertions(+), 13 deletions(-)

diff --git a/lisp/auth-source-pass.el b/lisp/auth-source-pass.el
index 03fd1f35811..dd93d414d5e 100644
--- a/lisp/auth-source-pass.el
+++ b/lisp/auth-source-pass.el
@@ -271,11 +271,12 @@ auth-source-pass--retrieve-parsed
                            n)))
              seen)))
 
-(defun auth-source-pass--match-parts (parts key value require)
-  (let ((mv (plist-get parts key)))
-    (if (memq key require)
-        (and value (equal mv value))
-      (or (not value) (not mv) (equal mv value)))))
+(defun auth-source-pass--match-parts (cache key reference require)
+  (let ((value (plist-get cache key)))
+    (cond ((memq key require)
+           (if reference (equal value reference) value))
+          ((and value reference) (equal value reference))
+          (t))))
 
 (defun auth-source-pass--find-match-many (hosts users ports require max)
   "Return plists for valid combinations of HOSTS, USERS, PORTS."
@@ -290,17 +291,17 @@ auth-source-pass--find-match-many
           (dolist (user (or users (list u)))
             (dolist (port (or ports (list p)))
               (dolist (e entries)
-                (when-let*
+                (when-let
                     ((m (or (gethash e seen) (auth-source-pass--retrieve-parsed
                                               seen e (integerp port))))
                      ((equal host (plist-get m :host)))
                      ((auth-source-pass--match-parts m :port port require))
                      ((auth-source-pass--match-parts m :user user require))
-                     (parsed (auth-source-pass-parse-entry e))
                      ;; For now, ignore body-content pairs, if any,
                      ;; from `auth-source-pass--parse-data'.
-                     (secret (or (auth-source-pass--get-attr 'secret parsed)
-                                 (not (memq :secret require)))))
+                     (secret (let ((parsed (auth-source-pass-parse-entry e)))
+                               (or (auth-source-pass--get-attr 'secret parsed)
+                                   (not (memq :secret require))))))
                   (push
                    `( :host ,host ; prefer user-provided :host over h
                       ,@(and-let* ((u (plist-get m :user))) (list :user u))
diff --git a/test/lisp/auth-source-pass-tests.el b/test/lisp/auth-source-pass-tests.el
index 6455c3393d5..c54936c3f92 100644
--- a/test/lisp/auth-source-pass-tests.el
+++ b/test/lisp/auth-source-pass-tests.el
@@ -548,6 +548,44 @@ auth-source-pass-extra-query-keywords--wild-port-hit
                      '((:host "x.com" :secret "a")
                        (:host "x.com" :port 42 :secret "b")))))))
 
+;; The query requires a user and doesn't specify a user to match against.
+;; The only entry matching the host lacks a user, so the search fails.
+
+(ert-deftest auth-source-pass-extra-query-keywords--req-noparam-miss-netrc ()
+  (ert-with-temp-file netrc-file
+    :text "machine foo password a\n"
+    (let ((auth-sources (list netrc-file))
+          (auth-source-do-cache nil))
+      (should-not (auth-source-search :host "foo" :require '(:user) :max 2)))))
+
+(ert-deftest auth-source-pass-extra-query-keywords--req-noparam-miss ()
+  (let ((auth-source-pass-extra-query-keywords t))
+    (auth-source-pass--with-store '(("foo" (secret . "a")))
+      (auth-source-pass-enable)
+      (should-not (auth-source-search :host "foo" :require '(:user) :max 2)))))
+
+;; The query requires a user but does not provide a reference value to
+;; match against.  An entry matching the host that specifies a user is
+;; selected because any user will do.
+(ert-deftest auth-source-pass-extra-query-keywords--req-param-netrc ()
+  (ert-with-temp-file netrc-file
+    :text "machine foo login bob password a\n"
+    (let* ((auth-sources (list netrc-file))
+           (auth-source-do-cache nil)
+           (results (auth-source-search :host "foo" :require '(:user))))
+      (dolist (result results)
+        (setf (plist-get result :secret) (auth-info-password result)))
+      (should (equal results '((:host "foo" :user "bob" :secret "a")))))))
+
+(ert-deftest auth-source-pass-extra-query-keywords--req-param ()
+  (let ((auth-source-pass-extra-query-keywords t))
+    (auth-source-pass--with-store '(("foo/bob" (secret . "a")))
+      (auth-source-pass-enable)
+      (let ((results (auth-source-search :host "foo" :require '(:user))))
+        (dolist (result results)
+          (setf (plist-get result :secret) (auth-info-password result)))
+        (should (equal results '((:host "foo" :user "bob" :secret "a"))))))))
+
 ;; No entry has the requested port, but :port is required, so search fails.
 
 (ert-deftest auth-source-pass-extra-query-keywords--wild-port-req-miss-netrc ()
@@ -629,14 +667,22 @@ auth-source-pass-extra-query-keywords--host
                      '((:host "Libera.Chat" :secret "b")))))))
 
 
-;; A retrieved store entry mustn't be nil regardless of whether its
-;; path contains port or user components.
+;; An effectively empty entry in the store returns nothing but the
+;; :host field matching the given host parameter.
+
+(ert-deftest auth-source-pass-extra-query-keywords--netrc-baseline ()
+  (ert-with-temp-file netrc-file
+    :text "machine foo\n"
+    (let* ((auth-sources (list netrc-file))
+           (auth-source-do-cache nil)
+           (results (auth-source-search :host "foo")))
+      (should (equal results '((:host "foo")))))))
 
 (ert-deftest auth-source-pass-extra-query-keywords--baseline ()
   (let ((auth-source-pass-extra-query-keywords t))
-    (auth-source-pass--with-store '(("x.com"))
+    (auth-source-pass--with-store '(("foo"))
       (auth-source-pass-enable)
-      (should-not (auth-source-search :host "x.com")))))
+      (should (equal (auth-source-search :host "foo") '((:host "foo")))))))
 
 ;; Output port type (int or string) matches that of input parameter.
 
-- 
2.46.0


--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment;
 filename=0002-POC-Match-attrs-with-auth-source-pass-extra-query-ke.patch

From d9bd10debf6c3930669aedb896026f9f19b54466 Mon Sep 17 00:00:00 2001
From: "F. Jason Park" <jp@HIDDEN>
Date: Wed, 7 Aug 2024 22:23:09 -0700
Subject: [PATCH 2/2] [POC] Match attrs with
 auth-source-pass-extra-query-keywords

* lisp/auth-source-pass.el (auth-source-pass--retrieve-parsed):
Remove unused function.
(auth-source-pass--cast-port): New function, a helper to match an
entry's port to the given query param's type.
(auth-source-pass--match-parts): Return non-nil when a key is required
but the value is null.  Not doing so produced behavior that deviated
from the reference netrc implementation and was thus a bug.
(auth-source-pass-check-attrs-with-extra-query-keywords): New
variable, a flag to opt out of arguably expensive attribute lookups.
(auth-source-pass--find-matched-entry): New function to isolate
processing logic for a single entry.
(auth-source-pass--find-match-many): Move single-entry processing
logic to separate helper, mainly for readability.
* test/lisp/auth-source-pass-tests.el
(auth-source-pass-extra-query-keywords--akib-attr)
(auth-source-pass-extra-query-keywords--akib-attr-req)
(auth-source-pass-extra-query-keywords--akib-attr-netrc)
(auth-source-pass-extra-query-keywords--akib-attr-extras)
(auth-source-pass-extra-query-keywords--netrc-baseline): New tests.
(auth-source-pass-extra-query-keywords--baseline): Reverse expected
outcome to match reference implementation.  That it didn't before was
a bug.  (Bug#72441)
---
 lisp/auth-source-pass.el            | 133 ++++++++++++++++++++--------
 test/lisp/auth-source-pass-tests.el |  84 ++++++++++++++++++
 2 files changed, 180 insertions(+), 37 deletions(-)

diff --git a/lisp/auth-source-pass.el b/lisp/auth-source-pass.el
index dd93d414d5e..a52dafc5ab2 100644
--- a/lisp/auth-source-pass.el
+++ b/lisp/auth-source-pass.el
@@ -256,20 +256,13 @@ auth-source-pass--find-match
                 hosts
               (list hosts))))
 
-(defun auth-source-pass--retrieve-parsed (seen path port-number-p)
-  (when (string-match auth-source-pass--match-regexp path)
-    (puthash path
-             `( :host ,(or (match-string 10 path) (match-string 11 path))
-                ,@(if-let* ((tr (match-string 21 path)))
-                      (list :user tr :suffix t)
-                    (list :user (match-string 20 path)))
-                :port ,(and-let* ((p (or (match-string 30 path)
-                                         (match-string 31 path)))
-                                  (n (string-to-number p)))
-                         (if (or (zerop n) (not port-number-p))
-                             (format "%s" p)
-                           n)))
-             seen)))
+(defun auth-source-pass--cast-port (val ref)
+  (cond ((integerp val) val)
+        ((and-let* (((integerp ref))
+                    (n (string-to-number val))
+                    ((not (zerop n))))
+           n))
+        (t (format "%s" val))))
 
 (defun auth-source-pass--match-parts (cache key reference require)
   (let ((value (plist-get cache key)))
@@ -278,11 +271,87 @@ auth-source-pass--match-parts
           ((and value reference) (equal value reference))
           (t))))
 
+(defvar auth-source-pass-check-attrs-with-extra-query-keywords t
+  "When non-nil, decrypt files to find attributes matching parameters.
+However, give precedence to fields encoded in file names.  Only applies
+when `auth-source-pass-extra-query-keywords' is non-nil.")
+
+;; This function tries to defer decryption as long as possible.  For
+;; that reason, an entry's file-path-derived :port or :user field
+;; always takes precedence over their counterparts from a decrypted
+;; file's attribute list.
+(defun auth-source-pass--find-matched-entry (host user port require seen entry)
+  "Match ENTRY against query params HOST USER PORT REQUIRE with cache SEEN."
+  (when (string-match auth-source-pass--match-regexp entry)
+    (let* ((cached (gethash entry seen))
+           (optp auth-source-pass-check-attrs-with-extra-query-keywords)
+           (suffixedp nil)
+           (h (or (and cached (plist-get cached :host))
+                  (match-string 10 entry)
+                  (match-string 11 entry)))
+           (attrs (and cached (plist-get :attrs cached)))
+           (getat (lambda (k)
+                    (save-match-data
+                      (unless attrs
+                        (setq attrs (auth-source-pass-parse-entry entry)))
+                      (auth-source-pass--get-attr k attrs))))
+           (u (cond (cached (plist-get cached :user))
+                    ((and-let* ((u (match-string 21 entry)))
+                       (setq suffixedp t)
+                       u))
+                    ((match-string 20 entry))
+                    ((and optp (or user (memq :user require)))
+                     (funcall getat "user"))))
+           (p (cond (cached (plist-get cached :port))
+                    ((match-string 30 entry))
+                    ((match-string 31 entry))
+                    ((and optp (or port (memq :port require)))
+                     (funcall getat "port"))))
+           ;;
+           s extras)
+      (when p
+        (setq p (auth-source-pass--cast-port p port)))
+      (unless cached
+        (setq cached `( :host ,h
+                        ,@(and u (list :user u))
+                        ,@(and p (list :port p))
+                        ,@(and suffixedp (list :suffix t))
+                        ,@(and attrs (list :attrs attrs))))
+        (puthash entry cached seen))
+      (when (and (equal host h)
+                 (auth-source-pass--match-parts cached :port port require)
+                 (auth-source-pass--match-parts cached :user user require)
+                 (setq s (or (funcall getat 'secret)
+                             (not (memq :secret require)))))
+        (let (tmp)
+          (while-let ((v (pop attrs))
+                      (k (pop v)))
+            (pcase k
+              ((or "user" "username")
+               (unless (or user u)
+                 (setq u v
+                       cached (plist-put cached :user u))))
+              ("port"
+               (unless (or port p)
+                 (setq p (auth-source-pass--cast-port v port)
+                       cached (plist-put cached :port p))))
+              ((pred stringp)
+               (push (intern (concat ":" k)) extras)
+               (push v extras)
+               (push (cons k v) tmp))))
+          (setq attrs (nreverse tmp)))
+        (puthash entry (plist-put cached :attrs attrs) seen)
+        `( :host ,host
+           ,@(and u (list :user u))
+           ,@(and p (list :port p))
+           ,@(and s (not (eq s t)) (list :secret s))
+           ,@(nreverse extras))))))
+
 (defun auth-source-pass--find-match-many (hosts users ports require max)
   "Return plists for valid combinations of HOSTS, USERS, PORTS."
   (let ((seen (make-hash-table :test #'equal))
         (entries (auth-source-pass-entries))
-        out suffixed suffixedp)
+        out suffixed)
     (catch 'done
       (dolist (host hosts out)
         (pcase-let ((`(,_ ,u ,p) (auth-source-pass--disambiguate host)))
@@ -290,28 +359,18 @@ auth-source-pass--find-match-many
             (setq p nil))
           (dolist (user (or users (list u)))
             (dolist (port (or ports (list p)))
-              (dolist (e entries)
-                (when-let
-                    ((m (or (gethash e seen) (auth-source-pass--retrieve-parsed
-                                              seen e (integerp port))))
-                     ((equal host (plist-get m :host)))
-                     ((auth-source-pass--match-parts m :port port require))
-                     ((auth-source-pass--match-parts m :user user require))
-                     ;; For now, ignore body-content pairs, if any,
-                     ;; from `auth-source-pass--parse-data'.
-                     (secret (let ((parsed (auth-source-pass-parse-entry e)))
-                               (or (auth-source-pass--get-attr 'secret parsed)
-                                   (not (memq :secret require))))))
-                  (push
-                   `( :host ,host ; prefer user-provided :host over h
-                      ,@(and-let* ((u (plist-get m :user))) (list :user u))
-                      ,@(and-let* ((p (plist-get m :port))) (list :port p))
-                      ,@(and secret (not (eq secret t)) (list :secret secret)))
-                   (if (setq suffixedp (plist-get m :suffix)) suffixed out))
-                  (unless suffixedp
-                    (when (or (zerop (cl-decf max))
-                              (null (setq entries (delete e entries))))
-                      (throw 'done out)))))
+              (dolist (entry entries)
+                (let* ((result (auth-source-pass--find-matched-entry
+                                host user port require seen entry))
+                       ;;
+                       suffixedp)
+                  (when result
+                    (setq suffixedp (plist-get (gethash entry seen) :suffix))
+                    (push result (if suffixedp suffixed out))
+                    (unless suffixedp
+                      (when (or (zerop (cl-decf max))
+                                (null (setq entries (delete entry entries))))
+                        (throw 'done out))))))
               (setq suffixed (nreverse suffixed))
               (while suffixed
                 (push (pop suffixed) out)
diff --git a/test/lisp/auth-source-pass-tests.el b/test/lisp/auth-source-pass-tests.el
index c54936c3f92..695635299f9 100644
--- a/test/lisp/auth-source-pass-tests.el
+++ b/test/lisp/auth-source-pass-tests.el
@@ -639,6 +639,90 @@ auth-source-pass-extra-query-keywords--akib
       (should (equal results
                      '((:host "disroot.org" :user "akib" :secret "b")))))))
 
+(ert-deftest auth-source-pass-extra-query-keywords--akib-attr ()
+  (auth-source-pass--with-store '(("x.com" (secret . "a"))
+                                  ("disroot.org" (secret . "b")
+                                   ("user" . "akib") ("port" . "42"))
+                                  ("z.com" (secret . "c")))
+    (auth-source-pass-enable)
+    (let* ((auth-source-pass-extra-query-keywords t)
+           results)
+
+      ;; Non-matching query param.
+      (setq results (auth-source-search :host "disroot.org" :user "?" :max 2))
+      (should-not results)
+
+      ;; No query params matching attrs.
+      (setq results (auth-source-search :host "disroot.org" :max 2))
+      (dolist (result results)
+        (setf (plist-get result :secret) (auth-info-password result)))
+      (should (equal results
+                     '(( :host "disroot.org" :user "akib"
+                         :port "42" :secret "b"))))
+
+      ;; Matching user query param.
+      (setq results (auth-source-search :host "disroot.org" :user "akib"))
+      (dolist (result results)
+        (setf (plist-get result :secret) (auth-info-password result)))
+      (should (equal results
+                     '(( :host "disroot.org" :user "akib"
+                         :port "42" :secret "b"))))
+
+      ;; Matching port typed query param.
+      (setq results (auth-source-search :host "disroot.org" :port 42))
+      (dolist (result results)
+        (setf (plist-get result :secret) (auth-info-password result)))
+      (should (equal results
+                     '(( :host "disroot.org" :user "akib"
+                         :port 42 :secret "b")))))))
+
+(ert-deftest auth-source-pass-extra-query-keywords--akib-attr-req ()
+  (auth-source-pass--with-store '(("x.com" (secret . "a"))
+                                  ("disroot.org" (secret . "b")
+                                   ("user" . "akib"))
+                                  ("z.com" (secret . "c")))
+    (auth-source-pass-enable)
+    (let* ((auth-source-pass-extra-query-keywords t)
+           (results (auth-source-search :host "disroot.org"
+                                        :require '(:user) :max 2)))
+      (dolist (result results)
+        (setf (plist-get result :secret) (auth-info-password result)))
+      (should (equal results
+                     '((:host "disroot.org" :user "akib" :secret "b")))))))
+
+(ert-deftest auth-source-pass-extra-query-keywords--akib-attr-extras-netrc ()
+  (ert-with-temp-file netrc-file
+    :text "\
+machine x.com password a
+machine disroot.org user akib port 42 password b foo 1 bar 2
+machine z.com password c
+"
+    (let* ((auth-sources (list netrc-file))
+           (auth-source-do-cache nil)
+           (results (auth-source-search :host "disroot.org" :max 2)))
+      (dolist (result results)
+        (setf (plist-get result :secret) (auth-info-password result)))
+      (should (equal results
+                     '((:host "disroot.org" :user "akib" :port "42"
+                              :secret "b" :foo "1" :bar "2")))))))
+
+(ert-deftest auth-source-pass-extra-query-keywords--akib-attr-extras ()
+  (auth-source-pass--with-store '(("x.com" (secret . "a"))
+                                  ("disroot.org" (secret . "b")
+                                   ("user" . "akib")
+                                   ("port" . "42")
+                                   ("foo" . "1")
+                                   ("bar" . "2"))
+                                  ("z.com" (secret . "c")))
+    (auth-source-pass-enable)
+    (let* ((auth-source-pass-extra-query-keywords t)
+           (results (auth-source-search :host "disroot.org" :max 2)))
+      (dolist (result results)
+        (setf (plist-get result :secret) (auth-info-password result)))
+      (should (equal results
+                     '((:host "disroot.org" :user "akib" :port "42"
+                              :secret "b" :foo "1" :bar "2")))))))
+
 ;; Searches for :host are case-sensitive, and a returned host isn't
 ;; normalized.
 
-- 
2.46.0


--=-=-=--




Information forwarded to bug-gnu-emacs@HIDDEN:
bug#72441; Package emacs. Full text available.

Message received at 72441 <at> debbugs.gnu.org:


Received: (at 72441) by debbugs.gnu.org; 10 Aug 2024 13:59:26 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Sat Aug 10 09:59:26 2024
Received: from localhost ([127.0.0.1]:40241 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1scmcv-0007ei-4R
	for submit <at> debbugs.gnu.org; Sat, 10 Aug 2024 09:59:26 -0400
Received: from mail-108-mta104.mxroute.com ([136.175.108.104]:42421)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <jp@HIDDEN>) id 1scmcr-0007eW-7U
 for 72441 <at> debbugs.gnu.org; Sat, 10 Aug 2024 09:59:23 -0400
Received: from filter006.mxroute.com ([136.175.111.3] filter006.mxroute.com)
 (Authenticated sender: mN4UYu2MZsgR)
 by mail-108-mta104.mxroute.com (ZoneMTA) with ESMTPSA id
 1913c95a6f30000a78.001 for <72441 <at> debbugs.gnu.org>
 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384);
 Sat, 10 Aug 2024 13:58:46 +0000
X-Zone-Loop: 3499b44ae4f6e9d32dcf8185c1b8e545ef938dbc7245
X-Originating-IP: [136.175.111.3]
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me
 ; s=x;
 h=Content-Type:MIME-Version:Message-ID:Date:References:In-Reply-To:
 Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID:
 Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc
 :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe:
 List-Post:List-Owner:List-Archive;
 bh=JFknXVgOTf77YUJVIrD/NtPFbD+h4JkO4OCHBJ1ecw0=; b=Cy6XNrnbYpJj+lhO0OsL/cnoRh
 hfzKi/4OCsbRE89+lhi5FB33ur1OOcTLFotx+1cwyrCKU7bP36p95qp7IRbIMbyWdv4OK0/7WMYr8
 HfWblaQ9caX3v8+QZLHP7OKWvJhy9FyXCiDXN47luuRoP6A+sSHYhe6s51UKc04lODjU0KZH+PZu0
 8zuaKi4Wpr8l6vuD+K+YBrsm503qY3JmHs7vX7UpodJUUJ6pGGcg1StmhG0wf+K4JGxoak+axQP5E
 7G8bKI0zmMxV+VRw30lea/dogu5ksAT9ZGWpeaZMHdrdkFTLY6wNXM5BrbyegcUE2nB1UwY8hc7zM
 DzErFsJg==;
From: "J.P." <jp@HIDDEN>
To: =?utf-8?Q?Bj=C3=B6rn?= Bidar <bjorn.bidar@HIDDEN>
Subject: Re: bug#72441: 31.0.50; Auth-source-pass doesn't match password
 attributes or hosts without user when extra-query-keywords is true
In-Reply-To: <87ed6xy03r.fsf@> (=?utf-8?Q?=22Bj=C3=B6rn?= Bidar"'s message
 of "Fri, 09 Aug 2024 22:20:24 +0300")
References: <17083.4807607875$1722683645@HIDDEN>
 <87frrdvaku.fsf@HIDDEN>
Date: Sat, 10 Aug 2024 06:58:43 -0700
Message-ID: <877ccoo4x8.fsf@HIDDEN>
User-Agent: Gnus/5.13 (Gnus v5.13)
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="=-=-="
X-Authenticated-Id: masked@HIDDEN
X-Spam-Score: 0.0 (/)
X-Debbugs-Envelope-To: 72441
Cc: 72441 <at> debbugs.gnu.org
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

--=-=-=
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable

Bj=C3=B6rn Bidar <bjorn.bidar@HIDDEN> writes:

> "J.P." <jp@HIDDEN> writes:
>
>> However, I do realize that the auth-source-pass back end without the
>> extra-keywords option already dips into a file's contents looking for an
>> attributes list like the one shown on the web page. (Whether that's wise
>> is pretty much moot after all these years.) Anyway, for that reason, I
>> suppose we _should_ attempt to at least explore doing the same when the
>> extra-keywords option is enabled. For me, the most important thing
>> remains mimicking the behavior of the other built-in back ends, which at
>> times is admittedly unintuitive but nevertheless consistent and thus
>> predictable from a mechanical POV.
>
> I agree fully with the comment. Other's that use pass as source for
> passwords also use file contents to match or retrieve variables from.
> E.g. most browser plugins derive the parameter for the login or user
> name from either of these names.

Hm, actually, I was not initially thinking of including all the
attributes, only :user and :port. But it seems I'd forgotten that the
netrc reference implementation does indeed include arbitrary key/value
pairs in the results from a successful match:

  # ~/.authinfo
  machine example.org login me password 123 foo bar

  M-: (auth-source-search :host "example.org")
  =3D> (... :foo "bar")

I've updated my previous patch to do this.

>> If we do end up going with something like the attached patch, we'll need
>> to profile it. I can create a bunch of fake trees of varying shapes and
>> sizes, but I'd rather someone with real data and a sizable store assess
>> how much slower it is to visit (and thus decrypt) potentially every file
>> in the tree, which is what any attr-reading implementation must do. On
>> my machine, it takes roughly 0.18 seconds to decrypt a single two-line
>> file via `auth-source-pass--read-entry'. (This seems prohibitively
>> expensive to do en masse, no?) FWIW, most of this time is spent in
>> `epg-wait-for-status', which blocks until the subprocess exits.
>
> That is why I was arguing that we should attempt to not try decrypt the
> password file unless a previous attribute such as :host or :user matched
> before.
> If we could do the search in parallel or at least without blocking Emacs
> that would be a different story of course.

With what I'm proposing, we would actually decrypt to inspect the parsed
attrs if :port or :user isn't found in the filename and a port or user
query parameter is given (or :port or :user appears in a :require
parameter). This behavior is currently gated by a new variable called
`auth-source-pass-check-attrs-with-extra-query-keywords', but it's t by
default. Perhaps it's better to have it be nil? If we do that, then, by
default, :port and :user attributes won't be considered, but they will
still be included in successful matches along with all other attributes.

>>> Same it should maybe also match against :host
>>> if no user was provided, I don't know how other sources do this thou.
>>
>> While the reference implementation indeed succeeds with a plain :host
>> input (see test `auth-source-pass-extra-query-keywords--netrc-host'), I
>> believe the actual problem you perceive has more to do with the content
>> of the file paths, specifically, leading directory components. Still,
>> I'm inclined to agree that this would be nice to have. However, I do
>> seem to recall this being discussed on at least one occasion, with the
>> conclusion being that it's too complicated, if not impossible, to
>> disambiguate between a trailing "hostname/user" and "folder/hostname".
>>
>> Nevertheless, we could add an option to do it anyway based on one or
>> more heuristics-based strategy (resolving hosts for real is surely a no
>> go). For example, one such strategy could ignore a penultimate file-path
>> component that's not an FQDN, even if it's, say, LDH-only and resolvable
>> as a hostname, so long as the leaf component _is_ an FQDN. However, such
>> an option would have to be disabled by default to prevent existing
>> entries like "localhost/test.user" from being parsed as (:host
>> "test.user").
>>
>
> What do you mean by resolving hosts for real?

I just meant it'd be unrealistic to query the system resolver via
`network-lookup-address-info' or similar whenever we need to
disambiguate.

> I think another option would be for the user to specific the hierarchy
> of their password store to auth-source-pass e.g. word/%host%/%user or
> word/(or %host word)/%user where word is any word that isn't used for
> matching but just for the user to organize the hierarchy.

That could work, although it seems rather complex with pattern
substitutions and expressions (?). Perhaps it could be precomputed
somehow into a regexp before every query.

Another idea would be to just have the option be an integer indicating
the number of leading path components to mask off before matching. Given
a tree like

  ~/.password-store/
  - foo/
    - example.com
  - irc.bar.org/
    - example.net/
      - me
  - baz/
    - myvps/
      - my.user.name

if the option (which is 0 by default) were set to 1, then possible
results might be

 (:host "example.com" :user "some-attr")
 (:host "example.net" :user "me")
 (:host "myvps"       :user "my.user.name")

Although this won't work if a user wants different mask depths for
different sub-directories.

>> In any case, I'm happy to review patches, but I think someone who
>> actually uses this back end should implement the feature.
>
> I'm not a good lisp programmar but I could give it a go with some help
> such as your patch as a start point.

I should be able to handle the attribute feature, unless you want to
improve upon it. It's mainly the disambiguation feature that I'd want an
actual pass user, like yourself, to implement or at least help design.
(Although feel free to offer patches of any nature, including based on
anything I've proposed.)


--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment; filename=0000-v1-v2.diff

From a0381a48cb4ff960ef2dd55dd511f5c18e535f6e Mon Sep 17 00:00:00 2001
From: "F. Jason Park" <jp@HIDDEN>
Date: Sat, 10 Aug 2024 07:15:36 -0700
Subject: [PATCH 0/1] *** NOT A PATCH ***

*** BLURB HERE ***

F. Jason Park (1):
  [POC] Match attrs with auth-source-pass-extra-query-keywords

 lisp/auth-source-pass.el            | 143 ++++++++++++++++++++--------
 test/lisp/auth-source-pass-tests.el |  96 ++++++++++++++++++-
 2 files changed, 195 insertions(+), 44 deletions(-)

Interdiff:
diff --git a/lisp/auth-source-pass.el b/lisp/auth-source-pass.el
index 8982e07a6be..0df7817f501 100644
--- a/lisp/auth-source-pass.el
+++ b/lisp/auth-source-pass.el
@@ -264,10 +264,10 @@ auth-source-pass--cast-port
            n))
         (t (format "%s" val))))
 
-(defun auth-source-pass--match-parts (parts key reference require)
-  (let ((value (plist-get parts key)))
+(defun auth-source-pass--match-parts (cache key reference require)
+  (let ((value (plist-get cache key)))
     (if (memq key require)
-        (or (null reference) (equal value reference))
+        (if reference (equal value reference) value)
       (or (null reference) (null value) (equal value reference)))))
 
 (defvar auth-source-pass-check-attrs-with-extra-query-keywords t
@@ -299,13 +299,15 @@ auth-source-pass--find-matched-entry
                        (setq suffixedp t)
                        u))
                     ((match-string 20 entry))
-                    ((and user optp) (funcall getat "user"))))
+                    ((and optp (or user (memq :user require)))
+                     (funcall getat "user"))))
            (p (cond (cached (plist-get cached :port))
                     ((match-string 30 entry))
                     ((match-string 31 entry))
-                    ((and port optp) (funcall getat "port"))))
+                    ((and optp (or port (memq :port require)))
+                     (funcall getat "port"))))
            ;;
-           s)
+           s extras)
       (when p
         (setq p (auth-source-pass--cast-port p port)))
       (unless cached
@@ -320,18 +322,29 @@ auth-source-pass--find-matched-entry
                  (auth-source-pass--match-parts cached :user user require)
                  (setq s (or (funcall getat 'secret)
                              (not (memq :secret require)))))
-        (unless (or user u)
-          (when (setq u (funcall getat "user"))
-            (setq cached (plist-put cached :user u))))
-        (unless (or port p)
-          (when (setq p (funcall getat "port"))
-            (setq p (auth-source-pass--cast-port p port)
-                  cached (plist-put cached :port p))))
+        (let (tmp)
+          (while-let ((v (pop attrs))
+                      (k (pop v)))
+            (pcase k
+              ((or "user" "username")
+               (unless (or user u)
+                 (setq u v
+                       cached (plist-put cached :user u))))
+              ("port"
+               (unless (or port p)
+                 (setq p (auth-source-pass--cast-port v port)
+                       cached (plist-put cached :port p))))
+              ((pred stringp)
+               (push (intern (concat ":" k)) extras)
+               (push v extras)
+               (push (cons k v) tmp))))
+          (setq attrs (nreverse tmp)))
         (puthash entry (plist-put cached :attrs attrs) seen)
         `( :host ,host
            ,@(and u (list :user u))
            ,@(and p (list :port p))
-           ,@(and s (not (eq s t)) (list :secret s)))))))
+           ,@(and s (not (eq s t)) (list :secret s))
+           ,@(nreverse extras))))))
 
 (defun auth-source-pass--find-match-many (hosts users ports require max)
   "Return plists for valid combinations of HOSTS, USERS, PORTS."
diff --git a/test/lisp/auth-source-pass-tests.el b/test/lisp/auth-source-pass-tests.el
index 2ce5d12a6bc..c6662cd8b42 100644
--- a/test/lisp/auth-source-pass-tests.el
+++ b/test/lisp/auth-source-pass-tests.el
@@ -668,6 +668,23 @@ auth-source-pass-extra-query-keywords--akib/attr/require
       (should (equal results
                      '((:host "disroot.org" :user "akib" :secret "b")))))))
 
+(ert-deftest auth-source-pass-extra-query-keywords--akib/attr/extras ()
+  (auth-source-pass--with-store '(("x.com" (secret . "a"))
+                                  ("disroot.org" (secret . "b")
+                                   ("user" . "akib")
+                                   ("port" . "42")
+                                   ("foo" . "1")
+                                   ("bar" . "2"))
+                                  ("z.com" (secret . "c")))
+    (auth-source-pass-enable)
+    (let* ((auth-source-pass-extra-query-keywords t)
+           (results (auth-source-search :host "disroot.org" :max 2)))
+      (dolist (result results)
+        (setf (plist-get result :secret) (auth-info-password result)))
+      (should (equal results
+                     '((:host "disroot.org" :user "akib" :port "42"
+                              :secret "b" :foo "1" :bar "2")))))))
+
 ;; Searches for :host are case-sensitive, and a returned host isn't
 ;; normalized.
 
-- 
2.46.0


--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment;
 filename=0001-POC-Match-attrs-with-auth-source-pass-extra-query-ke.patch

From a0381a48cb4ff960ef2dd55dd511f5c18e535f6e Mon Sep 17 00:00:00 2001
From: "F. Jason Park" <jp@HIDDEN>
Date: Wed, 7 Aug 2024 22:23:09 -0700
Subject: [PATCH 1/1] [POC] Match attrs with
 auth-source-pass-extra-query-keywords

* lisp/auth-source-pass.el (auth-source-pass--retrieve-parsed):
Remove unused function.
(auth-source-pass--cast-port): New function, a helper to match an
entry's port to the given query param's type.
(auth-source-pass--match-parts): Return non-nil when a key is required
but the value is null.  Not doing produced behavior that deviated from
the reference netrc implementation and was thus a bug.
(auth-source-pass-check-attrs-with-extra-query-keywords): New
variable, a flag to opt out of arguably expensive attribute lookups.
(auth-source-pass--find-matched-entry): New function to isolate
processing logic for a single entry.
(auth-source-pass--find-match-many): Move single-entry processing
logic to separate helper, mainly for readability.
* test/lisp/auth-source-pass-tests.el
(auth-source-pass-extra-query-keywords--akib/attr)
(auth-source-pass-extra-query-keywords--netrc-akib/require)
(auth-source-pass-extra-query-keywords--akib/attr/require)
(auth-source-pass-extra-query-keywords--akib/attr/extras)
(auth-source-pass-extra-query-keywords--netrc-baseline): New tests.
(auth-source-pass-extra-query-keywords--baseline): Reverse expected
outcome to match reference implementation.  That it didn't before was
a bug.  (Bug#72441)
---
 lisp/auth-source-pass.el            | 143 ++++++++++++++++++++--------
 test/lisp/auth-source-pass-tests.el |  96 ++++++++++++++++++-
 2 files changed, 195 insertions(+), 44 deletions(-)

diff --git a/lisp/auth-source-pass.el b/lisp/auth-source-pass.el
index 03fd1f35811..0df7817f501 100644
--- a/lisp/auth-source-pass.el
+++ b/lisp/auth-source-pass.el
@@ -256,32 +256,101 @@ auth-source-pass--find-match
                 hosts
               (list hosts))))
 
-(defun auth-source-pass--retrieve-parsed (seen path port-number-p)
-  (when (string-match auth-source-pass--match-regexp path)
-    (puthash path
-             `( :host ,(or (match-string 10 path) (match-string 11 path))
-                ,@(if-let* ((tr (match-string 21 path)))
-                      (list :user tr :suffix t)
-                    (list :user (match-string 20 path)))
-                :port ,(and-let* ((p (or (match-string 30 path)
-                                         (match-string 31 path)))
-                                  (n (string-to-number p)))
-                         (if (or (zerop n) (not port-number-p))
-                             (format "%s" p)
-                           n)))
-             seen)))
-
-(defun auth-source-pass--match-parts (parts key value require)
-  (let ((mv (plist-get parts key)))
+(defun auth-source-pass--cast-port (val ref)
+  (cond ((integerp val) val)
+        ((and-let* (((integerp ref))
+                    (n (string-to-number val))
+                    ((not (zerop n))))
+           n))
+        (t (format "%s" val))))
+
+(defun auth-source-pass--match-parts (cache key reference require)
+  (let ((value (plist-get cache key)))
     (if (memq key require)
-        (and value (equal mv value))
-      (or (not value) (not mv) (equal mv value)))))
+        (if reference (equal value reference) value)
+      (or (null reference) (null value) (equal value reference)))))
+
+(defvar auth-source-pass-check-attrs-with-extra-query-keywords t
+  "When non-nil, decrypt files to find attributes matching parameters.
+However, give precedence to fields encoded in file names.  Only applies
+when `auth-source-pass-extra-query-keywords' is non-nil.")
+
+;; This function tries to defer decryption as long as possible.  For
+;; that reason, an entry's file-path-derived :port or :user field
+;; always takes precedence over their counterparts from a decrypted
+;; file's attribute list.
+(defun auth-source-pass--find-matched-entry (host user port require seen entry)
+  "Match ENTRY against query params HOST USER PORT REQUIRE with cache SEEN."
+  (when (string-match auth-source-pass--match-regexp entry)
+    (let* ((cached (gethash entry seen))
+           (optp auth-source-pass-check-attrs-with-extra-query-keywords)
+           (suffixedp nil)
+           (h (or (and cached (plist-get cached :host))
+                  (match-string 10 entry)
+                  (match-string 11 entry)))
+           (attrs (and cached (plist-get :attrs cached)))
+           (getat (lambda (k)
+                    (save-match-data
+                      (unless attrs
+                        (setq attrs (auth-source-pass-parse-entry entry)))
+                      (auth-source-pass--get-attr k attrs))))
+           (u (cond (cached (plist-get cached :user))
+                    ((and-let* ((u (match-string 21 entry)))
+                       (setq suffixedp t)
+                       u))
+                    ((match-string 20 entry))
+                    ((and optp (or user (memq :user require)))
+                     (funcall getat "user"))))
+           (p (cond (cached (plist-get cached :port))
+                    ((match-string 30 entry))
+                    ((match-string 31 entry))
+                    ((and optp (or port (memq :port require)))
+                     (funcall getat "port"))))
+           ;;
+           s extras)
+      (when p
+        (setq p (auth-source-pass--cast-port p port)))
+      (unless cached
+        (setq cached `( :host ,h
+                        ,@(and u (list :user u))
+                        ,@(and p (list :port p))
+                        ,@(and suffixedp (list :suffix t))
+                        ,@(and attrs (list :attrs attrs))))
+        (puthash entry cached seen))
+      (when (and (equal host h)
+                 (auth-source-pass--match-parts cached :port port require)
+                 (auth-source-pass--match-parts cached :user user require)
+                 (setq s (or (funcall getat 'secret)
+                             (not (memq :secret require)))))
+        (let (tmp)
+          (while-let ((v (pop attrs))
+                      (k (pop v)))
+            (pcase k
+              ((or "user" "username")
+               (unless (or user u)
+                 (setq u v
+                       cached (plist-put cached :user u))))
+              ("port"
+               (unless (or port p)
+                 (setq p (auth-source-pass--cast-port v port)
+                       cached (plist-put cached :port p))))
+              ((pred stringp)
+               (push (intern (concat ":" k)) extras)
+               (push v extras)
+               (push (cons k v) tmp))))
+          (setq attrs (nreverse tmp)))
+        (puthash entry (plist-put cached :attrs attrs) seen)
+        `( :host ,host
+           ,@(and u (list :user u))
+           ,@(and p (list :port p))
+           ,@(and s (not (eq s t)) (list :secret s))
+           ,@(nreverse extras))))))
 
 (defun auth-source-pass--find-match-many (hosts users ports require max)
   "Return plists for valid combinations of HOSTS, USERS, PORTS."
   (let ((seen (make-hash-table :test #'equal))
         (entries (auth-source-pass-entries))
-        out suffixed suffixedp)
+        out suffixed)
     (catch 'done
       (dolist (host hosts out)
         (pcase-let ((`(,_ ,u ,p) (auth-source-pass--disambiguate host)))
@@ -289,28 +358,18 @@ auth-source-pass--find-match-many
             (setq p nil))
           (dolist (user (or users (list u)))
             (dolist (port (or ports (list p)))
-              (dolist (e entries)
-                (when-let*
-                    ((m (or (gethash e seen) (auth-source-pass--retrieve-parsed
-                                              seen e (integerp port))))
-                     ((equal host (plist-get m :host)))
-                     ((auth-source-pass--match-parts m :port port require))
-                     ((auth-source-pass--match-parts m :user user require))
-                     (parsed (auth-source-pass-parse-entry e))
-                     ;; For now, ignore body-content pairs, if any,
-                     ;; from `auth-source-pass--parse-data'.
-                     (secret (or (auth-source-pass--get-attr 'secret parsed)
-                                 (not (memq :secret require)))))
-                  (push
-                   `( :host ,host ; prefer user-provided :host over h
-                      ,@(and-let* ((u (plist-get m :user))) (list :user u))
-                      ,@(and-let* ((p (plist-get m :port))) (list :port p))
-                      ,@(and secret (not (eq secret t)) (list :secret secret)))
-                   (if (setq suffixedp (plist-get m :suffix)) suffixed out))
-                  (unless suffixedp
-                    (when (or (zerop (cl-decf max))
-                              (null (setq entries (delete e entries))))
-                      (throw 'done out)))))
+              (dolist (entry entries)
+                (let* ((result (auth-source-pass--find-matched-entry
+                                host user port require seen entry))
+                       ;;
+                       suffixedp)
+                  (when result
+                    (setq suffixedp (plist-get (gethash entry seen) :suffix))
+                    (push result (if suffixedp suffixed out))
+                    (unless suffixedp
+                      (when (or (zerop (cl-decf max))
+                                (null (setq entries (delete entry entries))))
+                        (throw 'done out))))))
               (setq suffixed (nreverse suffixed))
               (while suffixed
                 (push (pop suffixed) out)
diff --git a/test/lisp/auth-source-pass-tests.el b/test/lisp/auth-source-pass-tests.el
index 6455c3393d5..c6662cd8b42 100644
--- a/test/lisp/auth-source-pass-tests.el
+++ b/test/lisp/auth-source-pass-tests.el
@@ -601,6 +601,90 @@ auth-source-pass-extra-query-keywords--akib
       (should (equal results
                      '((:host "disroot.org" :user "akib" :secret "b")))))))
 
+(ert-deftest auth-source-pass-extra-query-keywords--akib/attr ()
+  (auth-source-pass--with-store '(("x.com" (secret . "a"))
+                                  ("disroot.org" (secret . "b")
+                                   ("user" . "akib") ("port" . "42"))
+                                  ("z.com" (secret . "c")))
+    (auth-source-pass-enable)
+    (let* ((auth-source-pass-extra-query-keywords t)
+           results)
+
+      ;; Non-matching query param.
+      (setq results (auth-source-search :host "disroot.org" :user "?" :max 2))
+      (should-not results)
+
+      ;; No query params matching attrs.
+      (setq results (auth-source-search :host "disroot.org" :max 2))
+      (dolist (result results)
+        (setf (plist-get result :secret) (auth-info-password result)))
+      (should (equal results
+                     '(( :host "disroot.org" :user "akib"
+                         :port "42" :secret "b"))))
+
+      ;; Matching user query param.
+      (setq results (auth-source-search :host "disroot.org" :user "akib"))
+      (dolist (result results)
+        (setf (plist-get result :secret) (auth-info-password result)))
+      (should (equal results
+                     '(( :host "disroot.org" :user "akib"
+                         :port "42" :secret "b"))))
+
+      ;; Matching port typed query param.
+      (setq results (auth-source-search :host "disroot.org" :port 42))
+      (dolist (result results)
+        (setf (plist-get result :secret) (auth-info-password result)))
+      (should (equal results
+                     '(( :host "disroot.org" :user "akib"
+                         :port 42 :secret "b")))))))
+
+(ert-deftest auth-source-pass-extra-query-keywords--netrc-akib/require ()
+  (ert-with-temp-file netrc-file
+    :text "\
+machine x.com password a
+machine disroot.org user akib password b
+machine z.com password c
+"
+    (let* ((auth-sources (list netrc-file))
+           (auth-source-do-cache nil)
+           (results (auth-source-search :host "disroot.org"
+                                        :require '(:user) :max 2)))
+      (dolist (result results)
+        (setf (plist-get result :secret) (auth-info-password result)))
+      (should (equal results
+                     '((:host "disroot.org" :user "akib" :secret "b")))))))
+
+(ert-deftest auth-source-pass-extra-query-keywords--akib/attr/require ()
+  (auth-source-pass--with-store '(("x.com" (secret . "a"))
+                                  ("disroot.org" (secret . "b")
+                                   ("user" . "akib"))
+                                  ("z.com" (secret . "c")))
+    (auth-source-pass-enable)
+    (let* ((auth-source-pass-extra-query-keywords t)
+           (results (auth-source-search :host "disroot.org"
+                                        :require '(:user) :max 2)))
+      (dolist (result results)
+        (setf (plist-get result :secret) (auth-info-password result)))
+      (should (equal results
+                     '((:host "disroot.org" :user "akib" :secret "b")))))))
+
+(ert-deftest auth-source-pass-extra-query-keywords--akib/attr/extras ()
+  (auth-source-pass--with-store '(("x.com" (secret . "a"))
+                                  ("disroot.org" (secret . "b")
+                                   ("user" . "akib")
+                                   ("port" . "42")
+                                   ("foo" . "1")
+                                   ("bar" . "2"))
+                                  ("z.com" (secret . "c")))
+    (auth-source-pass-enable)
+    (let* ((auth-source-pass-extra-query-keywords t)
+           (results (auth-source-search :host "disroot.org" :max 2)))
+      (dolist (result results)
+        (setf (plist-get result :secret) (auth-info-password result)))
+      (should (equal results
+                     '((:host "disroot.org" :user "akib" :port "42"
+                              :secret "b" :foo "1" :bar "2")))))))
+
 ;; Searches for :host are case-sensitive, and a returned host isn't
 ;; normalized.
 
@@ -632,11 +716,19 @@ auth-source-pass-extra-query-keywords--host
 ;; A retrieved store entry mustn't be nil regardless of whether its
 ;; path contains port or user components.
 
+(ert-deftest auth-source-pass-extra-query-keywords--netrc-baseline ()
+  (ert-with-temp-file netrc-file
+    :text "machine foo\n"
+    (let* ((auth-sources (list netrc-file))
+           (auth-source-do-cache nil)
+           (results (auth-source-search :host "foo")))
+      (should (equal results '((:host "foo")))))))
+
 (ert-deftest auth-source-pass-extra-query-keywords--baseline ()
   (let ((auth-source-pass-extra-query-keywords t))
-    (auth-source-pass--with-store '(("x.com"))
+    (auth-source-pass--with-store '(("foo"))
       (auth-source-pass-enable)
-      (should-not (auth-source-search :host "x.com")))))
+      (should (equal (auth-source-search :host "foo") '((:host "foo")))))))
 
 ;; Output port type (int or string) matches that of input parameter.
 
-- 
2.46.0


--=-=-=--




Information forwarded to bug-gnu-emacs@HIDDEN:
bug#72441; Package emacs. Full text available.

Message received at 72441 <at> debbugs.gnu.org:


Received: (at 72441) by debbugs.gnu.org; 9 Aug 2024 19:21:06 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Fri Aug 09 15:21:06 2024
Received: from localhost ([127.0.0.1]:38614 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1scVAf-0002i9-GP
	for submit <at> debbugs.gnu.org; Fri, 09 Aug 2024 15:21:06 -0400
Received: from thaodan.de ([185.216.177.71]:51010)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <bjorn.bidar@HIDDEN>) id 1scVAb-0002hV-H8
 for 72441 <at> debbugs.gnu.org; Fri, 09 Aug 2024 15:21:04 -0400
Received: from odin (dsl-trebng12-50dc75-154.dhcp.inet.fi [80.220.117.154])
 by thaodan.de (Postfix) with ESMTPSA id BF59CD00056;
 Fri,  9 Aug 2024 22:20:26 +0300 (EEST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=thaodan.de; s=mail;
 t=1723231226; bh=VS6VjaMCeg7c3lWsTnOeEkSXoFWKGvoGJLNXae4SpbM=;
 h=From:To:Cc:Subject:In-Reply-To:References:Date;
 b=m9Maj2PKiQO5OqG++6+DQjpaf2jMSQtK/EfpqHFc2pYRcKV/BdyEZxcPzyOVfxKMh
 z+IPek9bhCXO8PIx4vGXv8NTZL5b+QbIoBp/nWkDE4GW6E2rK7MVNtZ0AaqV2BzCmn
 ZP6uybnLqxChgCl5FbELYrWOpPSJMfBd569sEg/d/9p3FluLv64WRNYiWvqTL3/V6K
 8dvGfLVG9gKLT+ARYyKT7oy1FVxmKARIIoF/bETi/SPryP2imFlfZN1fZMaUdkhjD8
 J6QVkgThtqAoOeHrSoJd8ZACHDFbSIvuO6rsDVpq6IDz78KETXSRETvCmAPstwBa2T
 xDX9kf8Rmo/FwmE3xYyjLGTTUhPzzKDVLQKO2FyqFectTiQ1YDJy9LkcqYkZnbtXfZ
 dvUBvxdiA0mB0rFSn7idTnw/pwJBsOcrfRwBFqqSCJs2eGVc47OdsbF6QtId8+8Jwd
 ssRH9E5O6SPiRcuokj0CbB07HtHhRWY7wojeiU8lTfe8q0ev3W9kYGgwaumVGVMOLq
 gd46gAzfGQwMa7uB71UqDQOrUZcfEBYSP3gwt4iW8VJXozofs0/Zjjl5iQIaXtdJ5Q
 0aXxhqEbCu+D1uiWJRJG3kNB3h2Bmj/b1vxK9Sg5qBWSl6mGL7JLtmlbWJibKljy+Z
 vM9SAMeH+98etQ6UuwC0Eidg=
From: =?utf-8?Q?Bj=C3=B6rn?= Bidar <bjorn.bidar@HIDDEN>
To: "J.P." <jp@HIDDEN>
Subject: Re: bug#72441: 31.0.50; Auth-source-pass doesn't match password
 attributes or hosts without user when extra-query-keywords is true
In-Reply-To: <87frrdvaku.fsf@HIDDEN> (J. P.'s message of "Fri, 09 Aug
 2024 11:02:25 -0700")
References: <17083.4807607875$1722683645@HIDDEN>
 <87frrdvaku.fsf@HIDDEN>
Autocrypt: addr=bjorn.bidar@HIDDEN; prefer-encrypt=nopreference; keydata=
 mDMEZNfpPhYJKwYBBAHaRw8BAQdACBEmr+0xwIIHZfIDlZmm7sa+lHHSb0g9FZrN6qE6ru60JUJq
 w7ZybiBCaWRhciA8Ympvcm4uYmlkYXJAdGhhb2Rhbi5kZT6IlgQTFgoAPgIbAwULCQgHAgIiAgYV
 CgkICwIEFgIDAQIeBwIXgBYhBFHxdut1RzAepymoq1wbdKFlHF9oBQJk1/YmAhkBAAoJEFwbdKFl
 HF9oB9cBAJoIIGQKXm4cpap+Flxc/EGnYl0123lcEyzuduqvlDT0AQC3OlFKm/OiqJ8IMTrzJRZ8
 phFssTkSrrFXnM2jm5PYDoiTBBMWCgA7FiEEUfF263VHMB6nKairXBt0oWUcX2gFAmTX6T4CGwMF
 CwkIBwICIgIGFQoJCAsCBBYCAwECHgcCF4AACgkQXBt0oWUcX2hbCQEAtru7kvM8hi8zo6z9ux2h
 K+B5xViKuo7Z8K3IXuK5ugwA+wUfKzomzdBPhfxDsqLcEziGRxoyx0Q3ld9aermBUccHtBxCasO2
 cm4gQmlkYXIgPG1lQHRoYW9kYW4uZGU+iJMEExYKADsCGwMFCwkIBwICIgIGFQoJCAsCBBYCAwEC
 HgcCF4AWIQRR8XbrdUcwHqcpqKtcG3ShZRxfaAUCZNf2FQAKCRBcG3ShZRxfaCzSAP4hZ7cSp0YN
 XYpcjHdsySh2MuBhhoPeLGXs+2kSiqBiOwD/TP8AgPEg/R+SI9GI9on7fBJJ0mp2IT8kZ2rhDOjg
 gA6IkwQTFgoAOxYhBFHxdut1RzAepymoq1wbdKFlHF9oBQJk1+ntAhsDBQsJCAcCAiICBhUKCQgL
 AgQWAgMBAh4HAheAAAoJEFwbdKFlHF9oBgwA/iQHwe0VL4Df4GGTYlNjMSHFlIkBmN4UfYGLYj3E
 TrOUAQC51M+M3cjsL8WHdpBz6VAo6df9d+rVwhQ9vQuFHqevArg4BGTX6T4SCisGAQQBl1UBBQEB
 B0Cbohc3JEfn005/cm0AOGjSsW1ZxAkgaoVNjbpqk4MgNAMBCAeIeAQYFgoAIBYhBFHxdut1RzAe
 pymoq1wbdKFlHF9oBQJk1+k+AhsMAAoJEFwbdKFlHF9ooHABAKGmrGBic/Vys3BBrOQiRB3Z7izO
 HwhqTRpAqFZtXS2nAQDZhp/5aYw1TZjTzkm1KVt9QiYnjd/MvxRE9iaY6x4mDbgzBGTX6T4WCSsG
 AQQB2kcPAQEHQAgRJq/tMcCCB2XyA5WZpu7GvpRx0m9IPRWazeqhOq7uiO8EGBYKACAWIQRR8Xbr
 dUcwHqcpqKtcG3ShZRxfaAUCZNf71AIbIgCBCRBcG3ShZRxfaHYgBBkWCgAdFiEEUfF263VHMB6n
 KairXBt0oWUcX2gFAmTX+9QACgkQXBt0oWUcX2jeSwD6AtWn0cuo8IF35YRo4o3cDRJnUfJnbvJy
 GxyCDThR+zYBAKG6/jdwmZkBQZKslnDAbMMd2WfiZZT5JW3IWC4EaKMO7HkBAKYPGZ3UbfkRvfFK
 S+pQ9CgtNfkSJQBtT1Ob7Y6nsacgAQCpyXN7yppmhW/oBgivITPy9Lkg+V4NK9WZYZCU9Q7LBA==
Date: Fri, 09 Aug 2024 22:20:24 +0300
Message-ID: <87ed6xy03r.fsf@>
User-Agent: Gnus/5.13 (Gnus v5.13)
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable
X-Spam-Score: 1.2 (+)
X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org",
 has NOT identified this incoming email as spam.  The original
 message has been attached to this so you can view it or label
 similar future email.  If you have any questions, see
 the administrator of that system for details.
 
 Content preview:  "J.P." <jp@HIDDEN> writes: > Björn Bidar via "Bug reports
    for GNU Emacs, the Swiss army knife of text > editors" <bug-gnu-emacs@HIDDEN>
    writes: > >> I noticed that auth-source-pass doesn't match agains password
    file >> attrib [...] 
 
 Content analysis details:   (1.2 points, 10.0 required)
 
  pts rule name              description
 ---- ---------------------- --------------------------------------------------
 -0.0 SPF_PASS               SPF: sender matches SPF record
 -0.0 SPF_HELO_PASS          SPF: HELO matches SPF record
  1.2 INVALID_MSGID          Message-Id is not valid, according to RFC 2822
X-Debbugs-Envelope-To: 72441
Cc: 72441 <at> debbugs.gnu.org
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: 0.2 (/)

"J.P." <jp@HIDDEN> writes:

> Bj=C3=B6rn Bidar via "Bug reports for GNU Emacs, the Swiss army knife of =
text
> editors" <bug-gnu-emacs@HIDDEN> writes:
>
>> I noticed that auth-source-pass doesn't match agains password file
>> attributes such as those containing :user and only matches password
>> files which contain a host and a user when
>> auth-source-pass-extra-query-keywords is true.
>
> I don't use pass myself, nor have I ever, but I suppose I did add the
> `auth-source-pass-extra-query-keywords' option (though mainly in a bid
> to make auth-source-pass behave more like other back ends so it's usable
> with ERC). Anyway, I do actually recall being somewhat aware of the
> existence of the file attributes you mention. It seems I even left a
> comment about the current lack of support [1].

I started using the option since my girlfriends password store is
organized for many passwords as hostname.tld/user@HIDDEN, when she
created a password that is <Topic e.g. SSO>/example.com/user where
without the option the wrong password files were used.
Her mail address is user@HIDDEN and the login server is also
example.com with her name as the username (we selfhost).

> Looking into this a bit, it seems the password store's web page
> considers everything after the initial (password) line to be an opaque
> text blob:
>
>   The password store does not impose any particular schema or type of
>   organization of your data, as it is simply a flat text file, which can
>   contain arbitrary data. Though the most common case is storing a
>   single password per entry, some power users find they would like to
>   store more than just their password inside the password store, and
>   additionally store answers to secret questions, website URLs, and
>   other sensitive information or metadata. Since the password store does
>   not impose a scheme of it's own, you can choose your own organization.
>   There are many possibilities.
>
> However, I do realize that the auth-source-pass back end without the
> extra-keywords option already dips into a file's contents looking for an
> attributes list like the one shown on the web page. (Whether that's wise
> is pretty much moot after all these years.) Anyway, for that reason, I
> suppose we _should_ attempt to at least explore doing the same when the
> extra-keywords option is enabled. For me, the most important thing
> remains mimicking the behavior of the other built-in back ends, which at
> times is admittedly unintuitive but nevertheless consistent and thus
> predictable from a mechanical POV.

I agree fully with the comment. Other's that use pass as source for
passwords also use file contents to match or retrieve variables from.
E.g. most browser plugins derive the parameter for the login or user
name from either of these names.

>> Steps to reproduce:
>> 1. Setup pass with the following structure
>>    WorkingTest/example.com/foo
>>    FailingTest/example2.com
>>    FailingTest/example3.com with user: foo in the password file
>> 2. (auth-source-pass-enable)
>> 3. (setq auth-source-pass-extra-query-keywords t)
>> 4. (auth-source-search :host "example" :user "foo") -> works
>> 5. (auth-source-search :host "example2.com") -> fails
>> 6. (auth-source-search :host "example3.com" :user "foo")
>>
>> Auth-source-pass should be able to query the password file for
>> additional attributes if one of the previous attributes such as :host
>> match to it. Quering the file attributes is quite important in use
>> cases where it doesn't make sense to the user to have a
>> host-folder/user-file structure in cases where there's only one
>> password for said host.
>
> Currently, if you have a file in the root of your ~/.password-store
> named something like "top-level-host.com", and it's contents feature a
> "user: foo" attribute, both
>
>   (auth-source-search :host "top-level-host.com")
>
> and
>
>   (auth-source-search :host "top-level-host.com" :user "foo")
>
> return
>
>   ((:host "top-level-host.com" :secret ...)).
>
> If you're saying you want to see (:user "foo") in the results as well, I
> guess we can do that (see attached patch as well as [2], below).
> However, this still won't work on any of your examples, which all have
> intervening path components between the root directory and the .gpg
> files. The reason for this restriction is explained below.
>
> If we do end up going with something like the attached patch, we'll need
> to profile it. I can create a bunch of fake trees of varying shapes and
> sizes, but I'd rather someone with real data and a sizable store assess
> how much slower it is to visit (and thus decrypt) potentially every file
> in the tree, which is what any attr-reading implementation must do. On
> my machine, it takes roughly 0.18 seconds to decrypt a single two-line
> file via `auth-source-pass--read-entry'. (This seems prohibitively
> expensive to do en masse, no?) FWIW, most of this time is spent in
> `epg-wait-for-status', which blocks until the subprocess exits.

That is why I was arguing that we should attempt to not try decrypt the
password file unless a previous attribute such as :host or :user matched
before.
If we could do the search in parallel or at least without blocking Emacs
that would be a different story of course.

>> Same it should maybe also match against :host
>> if no user was provided, I don't know how other sources do this thou.
>
> While the reference implementation indeed succeeds with a plain :host
> input (see test `auth-source-pass-extra-query-keywords--netrc-host'), I
> believe the actual problem you perceive has more to do with the content
> of the file paths, specifically, leading directory components. Still,
> I'm inclined to agree that this would be nice to have. However, I do
> seem to recall this being discussed on at least one occasion, with the
> conclusion being that it's too complicated, if not impossible, to
> disambiguate between a trailing "hostname/user" and "folder/hostname".
>
> Nevertheless, we could add an option to do it anyway based on one or
> more heuristics-based strategy (resolving hosts for real is surely a no
> go). For example, one such strategy could ignore a penultimate file-path
> component that's not an FQDN, even if it's, say, LDH-only and resolvable
> as a hostname, so long as the leaf component _is_ an FQDN. However, such
> an option would have to be disabled by default to prevent existing
> entries like "localhost/test.user" from being parsed as (:host
> "test.user").
>

What do you mean by resolving hosts for real? I think another option
would be for the user to specific the hierarchy of their password store
to auth-source-pass e.g. word/%host%/%user or word/(or %host word)/%user
where word is any word that isn't used for matching but just for the
user to organize the hierarchy.

> In any case, I'm happy to review patches, but I think someone who
> actually uses this back end should implement the feature.

I'm not a good lisp programmar but I could give it a go with some help
such as your patch as a start point.

>
> [1] https://git.savannah.gnu.org/cgit/emacs.git/tree/lisp/auth-source-pas=
s.el?id=3D423c86cb#n300
>
> [2] The following describes details of the attached patch's logic for
>     the inner (dolist (e entries) ...) loop of the primary matching
>     function `auth-source-pass--find-match-many'. Hopefully it's
>     somewhat sound with regard to deferring decryption for as long as
>     possible.
>
>     1. Parse the file path of each entry first and cache its results in
>        a plist, the "cached entry metadata," which is filed under the
>        entry's file-path in the `seen' hash table. If it doesn't match
>        the basic filename format, it must not be a passwordstore file,
>        so reject the entry.
>     2. Check the :host field before reading the file. Unless it matches,
>        reject the entry.
>     3. Engage in a series of probing conditional checks for a :port
>        field to match against a provided "port" query parameter, all
>        while attempting to defer decryption until absolutely necessary.
>        (A path-encoded :port always takes precedence over a :port in the
>        file.)
>        - If a `port' query parameter is not given for matching against,
>          continue to the next steps for the current entry.
>        - Otherwise, if a :port parsed from the file path is present and
>          it doesn't match, reject the entry, meaning go to the beginning
>          of the current loop, considering the next entry.
>        - If a path-derived :port is absent, ensure the cached entry
>          metadata contains an additional :attrs field (an alist). If the
>          metadata lacks an :attrs field, the file has not yet been
>          decrypted. Decrypt it now using `auth-source-pass-parse-entry',
>          then add its secret and its attrs alist to the cached metadata,
>          under :attrs.
>        - Look in the cached entry metadata's :attrs alist for a "port"
>          attr. If a "port" attr is indeed present and doesn't match the
>          port query parameter, reject the entry.
>        - If no such "port" attr exists and is required (meaning :port
>          appears in the `require' query parameter), reject the entry.
>     4. Repeat step 3 for :user. The same precedence rules apply, meaning
>        any non-null path-derived :user field is immediately accepted,
>        and the file is not decrypted.
>     5. If we haven't yet decrypted the file, do so now and populate the
>        :attrs item in the cached entry metadata. If it's already been
>        decrypted at some point, :attrs will present (though possibly
>        empty). In any case, add the items we care about if non-null
>        (:user, :port, and :secret) to the matched results for this entry.
>        However, only do so if a secret was either not required or is
>        present; otherwise, reject the entry.




Information forwarded to bug-gnu-emacs@HIDDEN:
bug#72441; Package emacs. Full text available.

Message received at 72441 <at> debbugs.gnu.org:


Received: (at 72441) by debbugs.gnu.org; 9 Aug 2024 18:03:04 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Fri Aug 09 14:03:03 2024
Received: from localhost ([127.0.0.1]:38589 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1scTx8-0000Zn-Ld
	for submit <at> debbugs.gnu.org; Fri, 09 Aug 2024 14:03:03 -0400
Received: from mail-108-mta253.mxroute.com ([136.175.108.253]:39551)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <jp@HIDDEN>) id 1scTx5-0000ZH-1b
 for 72441 <at> debbugs.gnu.org; Fri, 09 Aug 2024 14:03:01 -0400
Received: from filter006.mxroute.com ([136.175.111.3] filter006.mxroute.com)
 (Authenticated sender: mN4UYu2MZsgR)
 by mail-108-mta253.mxroute.com (ZoneMTA) with ESMTPSA id
 191384e6b8b0000a78.001 for <72441 <at> debbugs.gnu.org>
 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384);
 Fri, 09 Aug 2024 18:02:29 +0000
X-Zone-Loop: 50eeddaa4a3a454c696fcfdafb8e616b15f3dfef9c19
X-Originating-IP: [136.175.111.3]
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me
 ; s=x;
 h=Content-Type:MIME-Version:Message-ID:Date:References:In-Reply-To:
 Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID:
 Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc
 :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe:
 List-Post:List-Owner:List-Archive;
 bh=/aFVtJVGdnn7/rpC8frIZlREd3udNNjiBhHLkM3LDs4=; b=Glnay1elkMklUdWg2xMtYBBGdY
 1FaRPm2XcVLG2gPoi+6XwKnDagRaZEoxcsQFHt+OYc/oTh876NARQ97gz9Edw8cOYdMA7BbTT1cW6
 qAwlq9fF5WRWAXX1/gtOPbnfXafYWQKbw4AueicMZD4FW7jEluMV+YlS8pL4bxnd2T8oj3CWbB/vy
 m23fNIAY16dpJU+QdYHJin78gjE0XDjnz/x8/t3MmzMq2xVJPJ9HEAqbdyishHuxKfwg48PWxMhLz
 rNyYxHyKJxvfJFGKXe72k/sJqkRrJVI6/cqj07Cfx9Idltq82uh/csEHIHYmMaMLVu38ORnEmcPBs
 0kQpA/Kw==;
From: "J.P." <jp@HIDDEN>
To: 72441 <at> debbugs.gnu.org
Subject: Re: bug#72441: 31.0.50; Auth-source-pass doesn't match password
 attributes or hosts without user when extra-query-keywords is true
In-Reply-To: <17083.4807607875$1722683645@HIDDEN> (=?utf-8?Q?=22Bj?=
 =?utf-8?Q?=C3=B6rn?= Bidar via
 \"Bug reports for GNU Emacs, the Swiss army knife of text editors\""'s
 message of "Sat, 03 Aug 2024 14:12:33 +0300")
References: <17083.4807607875$1722683645@HIDDEN>
Date: Fri, 09 Aug 2024 11:02:25 -0700
Message-ID: <87frrdvaku.fsf@HIDDEN>
User-Agent: Gnus/5.13 (Gnus v5.13)
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="=-=-="
X-Authenticated-Id: masked@HIDDEN
X-Spam-Score: 0.0 (/)
X-Debbugs-Envelope-To: 72441
Cc: =?utf-8?Q?Bj=C3=B6rn?= Bidar <bjorn.bidar@HIDDEN>
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

--=-=-=
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable

Bj=C3=B6rn Bidar via "Bug reports for GNU Emacs, the Swiss army knife of te=
xt
editors" <bug-gnu-emacs@HIDDEN> writes:

> I noticed that auth-source-pass doesn't match agains password file
> attributes such as those containing :user and only matches password
> files which contain a host and a user when
> auth-source-pass-extra-query-keywords is true.

I don't use pass myself, nor have I ever, but I suppose I did add the
`auth-source-pass-extra-query-keywords' option (though mainly in a bid
to make auth-source-pass behave more like other back ends so it's usable
with ERC). Anyway, I do actually recall being somewhat aware of the
existence of the file attributes you mention. It seems I even left a
comment about the current lack of support [1].

Looking into this a bit, it seems the password store's web page
considers everything after the initial (password) line to be an opaque
text blob:

  The password store does not impose any particular schema or type of
  organization of your data, as it is simply a flat text file, which can
  contain arbitrary data. Though the most common case is storing a
  single password per entry, some power users find they would like to
  store more than just their password inside the password store, and
  additionally store answers to secret questions, website URLs, and
  other sensitive information or metadata. Since the password store does
  not impose a scheme of it's own, you can choose your own organization.
  There are many possibilities.

However, I do realize that the auth-source-pass back end without the
extra-keywords option already dips into a file's contents looking for an
attributes list like the one shown on the web page. (Whether that's wise
is pretty much moot after all these years.) Anyway, for that reason, I
suppose we _should_ attempt to at least explore doing the same when the
extra-keywords option is enabled. For me, the most important thing
remains mimicking the behavior of the other built-in back ends, which at
times is admittedly unintuitive but nevertheless consistent and thus
predictable from a mechanical POV.

> Steps to reproduce:
> 1. Setup pass with the following structure
>    WorkingTest/example.com/foo
>    FailingTest/example2.com
>    FailingTest/example3.com with user: foo in the password file
> 2. (auth-source-pass-enable)
> 3. (setq auth-source-pass-extra-query-keywords t)
> 4. (auth-source-search :host "example" :user "foo") -> works
> 5. (auth-source-search :host "example2.com") -> fails
> 6. (auth-source-search :host "example3.com" :user "foo")
>
> Auth-source-pass should be able to query the password file for
> additional attributes if one of the previous attributes such as :host
> match to it. Quering the file attributes is quite important in use
> cases where it doesn't make sense to the user to have a
> host-folder/user-file structure in cases where there's only one
> password for said host.

Currently, if you have a file in the root of your ~/.password-store
named something like "top-level-host.com", and it's contents feature a
"user: foo" attribute, both

  (auth-source-search :host "top-level-host.com")

and

  (auth-source-search :host "top-level-host.com" :user "foo")

return

  ((:host "top-level-host.com" :secret ...)).

If you're saying you want to see (:user "foo") in the results as well, I
guess we can do that (see attached patch as well as [2], below).
However, this still won't work on any of your examples, which all have
intervening path components between the root directory and the .gpg
files. The reason for this restriction is explained below.

If we do end up going with something like the attached patch, we'll need
to profile it. I can create a bunch of fake trees of varying shapes and
sizes, but I'd rather someone with real data and a sizable store assess
how much slower it is to visit (and thus decrypt) potentially every file
in the tree, which is what any attr-reading implementation must do. On
my machine, it takes roughly 0.18 seconds to decrypt a single two-line
file via `auth-source-pass--read-entry'. (This seems prohibitively
expensive to do en masse, no?) FWIW, most of this time is spent in
`epg-wait-for-status', which blocks until the subprocess exits.

> Same it should maybe also match against :host
> if no user was provided, I don't know how other sources do this thou.

While the reference implementation indeed succeeds with a plain :host
input (see test `auth-source-pass-extra-query-keywords--netrc-host'), I
believe the actual problem you perceive has more to do with the content
of the file paths, specifically, leading directory components. Still,
I'm inclined to agree that this would be nice to have. However, I do
seem to recall this being discussed on at least one occasion, with the
conclusion being that it's too complicated, if not impossible, to
disambiguate between a trailing "hostname/user" and "folder/hostname".

Nevertheless, we could add an option to do it anyway based on one or
more heuristics-based strategy (resolving hosts for real is surely a no
go). For example, one such strategy could ignore a penultimate file-path
component that's not an FQDN, even if it's, say, LDH-only and resolvable
as a hostname, so long as the leaf component _is_ an FQDN. However, such
an option would have to be disabled by default to prevent existing
entries like "localhost/test.user" from being parsed as (:host
"test.user").

In any case, I'm happy to review patches, but I think someone who
actually uses this back end should implement the feature.


[1] https://git.savannah.gnu.org/cgit/emacs.git/tree/lisp/auth-source-pass.=
el?id=3D423c86cb#n300

[2] The following describes details of the attached patch's logic for
    the inner (dolist (e entries) ...) loop of the primary matching
    function `auth-source-pass--find-match-many'. Hopefully it's
    somewhat sound with regard to deferring decryption for as long as
    possible.

    1. Parse the file path of each entry first and cache its results in
       a plist, the "cached entry metadata," which is filed under the
       entry's file-path in the `seen' hash table. If it doesn't match
       the basic filename format, it must not be a passwordstore file,
       so reject the entry.
    2. Check the :host field before reading the file. Unless it matches,
       reject the entry.
    3. Engage in a series of probing conditional checks for a :port
       field to match against a provided "port" query parameter, all
       while attempting to defer decryption until absolutely necessary.
       (A path-encoded :port always takes precedence over a :port in the
       file.)
       - If a `port' query parameter is not given for matching against,
         continue to the next steps for the current entry.
       - Otherwise, if a :port parsed from the file path is present and
         it doesn't match, reject the entry, meaning go to the beginning
         of the current loop, considering the next entry.
       - If a path-derived :port is absent, ensure the cached entry
         metadata contains an additional :attrs field (an alist). If the
         metadata lacks an :attrs field, the file has not yet been
         decrypted. Decrypt it now using `auth-source-pass-parse-entry',
         then add its secret and its attrs alist to the cached metadata,
         under :attrs.
       - Look in the cached entry metadata's :attrs alist for a "port"
         attr. If a "port" attr is indeed present and doesn't match the
         port query parameter, reject the entry.
       - If no such "port" attr exists and is required (meaning :port
         appears in the `require' query parameter), reject the entry.
    4. Repeat step 3 for :user. The same precedence rules apply, meaning
       any non-null path-derived :user field is immediately accepted,
       and the file is not decrypted.
    5. If we haven't yet decrypted the file, do so now and populate the
       :attrs item in the cached entry metadata. If it's already been
       decrypted at some point, :attrs will present (though possibly
       empty). In any case, add the items we care about if non-null
       (:user, :port, and :secret) to the matched results for this entry.
       However, only do so if a secret was either not required or is
       present; otherwise, reject the entry.

--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment;
 filename=0001-POC-Match-attrs-with-auth-source-pass-extra-query-ke.patch

From a36ef10d81e2c5afb0cf2515887084b6331d38d1 Mon Sep 17 00:00:00 2001
From: "F. Jason Park" <jp@HIDDEN>
Date: Wed, 7 Aug 2024 22:23:09 -0700
Subject: [PATCH] [POC] Match attrs with auth-source-pass-extra-query-keywords

* lisp/auth-source-pass.el (auth-source-pass--retrieve-parsed):
Remove unused function.
(auth-source-pass--cast-port): New function, a helper to match an
entry's port to the given query param's type.
(auth-source-pass--match-parts): Return non-nil when a key is required
but the value is null.  Not doing produced behavior that deviated from
the reference netrc implementation and was thus a bug.
(auth-source-pass-check-attrs-with-extra-query-keywords): New
variable, a flag to opt out of arguably expensive attribute lookups.
(auth-source-pass--find-matched-entry): New function to isolate
processing logic for a single entry.
(auth-source-pass--find-match-many): Move single-entry processing
logic to separate helper, mainly for readability.
* test/lisp/auth-source-pass-tests.el
(auth-source-pass-extra-query-keywords--akib/attr)
(auth-source-pass-extra-query-keywords--netrc-akib/require)
(auth-source-pass-extra-query-keywords--akib/attr/require)
(auth-source-pass-extra-query-keywords--netrc-baseline): New tests.
(auth-source-pass-extra-query-keywords--baseline): Reverse expected
outcome to match reference implementation.  That it didn't before was
a bug.  (Bug#72441)
---
 lisp/auth-source-pass.el            | 130 +++++++++++++++++++---------
 test/lisp/auth-source-pass-tests.el |  79 ++++++++++++++++-
 2 files changed, 165 insertions(+), 44 deletions(-)

diff --git a/lisp/auth-source-pass.el b/lisp/auth-source-pass.el
index 03fd1f35811..8982e07a6be 100644
--- a/lisp/auth-source-pass.el
+++ b/lisp/auth-source-pass.el
@@ -256,32 +256,88 @@ auth-source-pass--find-match
                 hosts
               (list hosts))))
 
-(defun auth-source-pass--retrieve-parsed (seen path port-number-p)
-  (when (string-match auth-source-pass--match-regexp path)
-    (puthash path
-             `( :host ,(or (match-string 10 path) (match-string 11 path))
-                ,@(if-let* ((tr (match-string 21 path)))
-                      (list :user tr :suffix t)
-                    (list :user (match-string 20 path)))
-                :port ,(and-let* ((p (or (match-string 30 path)
-                                         (match-string 31 path)))
-                                  (n (string-to-number p)))
-                         (if (or (zerop n) (not port-number-p))
-                             (format "%s" p)
-                           n)))
-             seen)))
-
-(defun auth-source-pass--match-parts (parts key value require)
-  (let ((mv (plist-get parts key)))
+(defun auth-source-pass--cast-port (val ref)
+  (cond ((integerp val) val)
+        ((and-let* (((integerp ref))
+                    (n (string-to-number val))
+                    ((not (zerop n))))
+           n))
+        (t (format "%s" val))))
+
+(defun auth-source-pass--match-parts (parts key reference require)
+  (let ((value (plist-get parts key)))
     (if (memq key require)
-        (and value (equal mv value))
-      (or (not value) (not mv) (equal mv value)))))
+        (or (null reference) (equal value reference))
+      (or (null reference) (null value) (equal value reference)))))
+
+(defvar auth-source-pass-check-attrs-with-extra-query-keywords t
+  "When non-nil, decrypt files to find attributes matching parameters.
+However, give precedence to fields encoded in file names.  Only applies
+when `auth-source-pass-extra-query-keywords' is non-nil.")
+
+;; This function tries to defer decryption as long as possible.  For
+;; that reason, an entry's file-path-derived :port or :user field
+;; always takes precedence over their counterparts from a decrypted
+;; file's attribute list.
+(defun auth-source-pass--find-matched-entry (host user port require seen entry)
+  "Match ENTRY against query params HOST USER PORT REQUIRE with cache SEEN."
+  (when (string-match auth-source-pass--match-regexp entry)
+    (let* ((cached (gethash entry seen))
+           (optp auth-source-pass-check-attrs-with-extra-query-keywords)
+           (suffixedp nil)
+           (h (or (and cached (plist-get cached :host))
+                  (match-string 10 entry)
+                  (match-string 11 entry)))
+           (attrs (and cached (plist-get :attrs cached)))
+           (getat (lambda (k)
+                    (save-match-data
+                      (unless attrs
+                        (setq attrs (auth-source-pass-parse-entry entry)))
+                      (auth-source-pass--get-attr k attrs))))
+           (u (cond (cached (plist-get cached :user))
+                    ((and-let* ((u (match-string 21 entry)))
+                       (setq suffixedp t)
+                       u))
+                    ((match-string 20 entry))
+                    ((and user optp) (funcall getat "user"))))
+           (p (cond (cached (plist-get cached :port))
+                    ((match-string 30 entry))
+                    ((match-string 31 entry))
+                    ((and port optp) (funcall getat "port"))))
+           ;;
+           s)
+      (when p
+        (setq p (auth-source-pass--cast-port p port)))
+      (unless cached
+        (setq cached `( :host ,h
+                        ,@(and u (list :user u))
+                        ,@(and p (list :port p))
+                        ,@(and suffixedp (list :suffix t))
+                        ,@(and attrs (list :attrs attrs))))
+        (puthash entry cached seen))
+      (when (and (equal host h)
+                 (auth-source-pass--match-parts cached :port port require)
+                 (auth-source-pass--match-parts cached :user user require)
+                 (setq s (or (funcall getat 'secret)
+                             (not (memq :secret require)))))
+        (unless (or user u)
+          (when (setq u (funcall getat "user"))
+            (setq cached (plist-put cached :user u))))
+        (unless (or port p)
+          (when (setq p (funcall getat "port"))
+            (setq p (auth-source-pass--cast-port p port)
+                  cached (plist-put cached :port p))))
+        (puthash entry (plist-put cached :attrs attrs) seen)
+        `( :host ,host
+           ,@(and u (list :user u))
+           ,@(and p (list :port p))
+           ,@(and s (not (eq s t)) (list :secret s)))))))
 
 (defun auth-source-pass--find-match-many (hosts users ports require max)
   "Return plists for valid combinations of HOSTS, USERS, PORTS."
   (let ((seen (make-hash-table :test #'equal))
         (entries (auth-source-pass-entries))
-        out suffixed suffixedp)
+        out suffixed)
     (catch 'done
       (dolist (host hosts out)
         (pcase-let ((`(,_ ,u ,p) (auth-source-pass--disambiguate host)))
@@ -289,28 +345,18 @@ auth-source-pass--find-match-many
             (setq p nil))
           (dolist (user (or users (list u)))
             (dolist (port (or ports (list p)))
-              (dolist (e entries)
-                (when-let*
-                    ((m (or (gethash e seen) (auth-source-pass--retrieve-parsed
-                                              seen e (integerp port))))
-                     ((equal host (plist-get m :host)))
-                     ((auth-source-pass--match-parts m :port port require))
-                     ((auth-source-pass--match-parts m :user user require))
-                     (parsed (auth-source-pass-parse-entry e))
-                     ;; For now, ignore body-content pairs, if any,
-                     ;; from `auth-source-pass--parse-data'.
-                     (secret (or (auth-source-pass--get-attr 'secret parsed)
-                                 (not (memq :secret require)))))
-                  (push
-                   `( :host ,host ; prefer user-provided :host over h
-                      ,@(and-let* ((u (plist-get m :user))) (list :user u))
-                      ,@(and-let* ((p (plist-get m :port))) (list :port p))
-                      ,@(and secret (not (eq secret t)) (list :secret secret)))
-                   (if (setq suffixedp (plist-get m :suffix)) suffixed out))
-                  (unless suffixedp
-                    (when (or (zerop (cl-decf max))
-                              (null (setq entries (delete e entries))))
-                      (throw 'done out)))))
+              (dolist (entry entries)
+                (let* ((result (auth-source-pass--find-matched-entry
+                                host user port require seen entry))
+                       ;;
+                       suffixedp)
+                  (when result
+                    (setq suffixedp (plist-get (gethash entry seen) :suffix))
+                    (push result (if suffixedp suffixed out))
+                    (unless suffixedp
+                      (when (or (zerop (cl-decf max))
+                                (null (setq entries (delete entry entries))))
+                        (throw 'done out))))))
               (setq suffixed (nreverse suffixed))
               (while suffixed
                 (push (pop suffixed) out)
diff --git a/test/lisp/auth-source-pass-tests.el b/test/lisp/auth-source-pass-tests.el
index 6455c3393d5..2ce5d12a6bc 100644
--- a/test/lisp/auth-source-pass-tests.el
+++ b/test/lisp/auth-source-pass-tests.el
@@ -601,6 +601,73 @@ auth-source-pass-extra-query-keywords--akib
       (should (equal results
                      '((:host "disroot.org" :user "akib" :secret "b")))))))
 
+(ert-deftest auth-source-pass-extra-query-keywords--akib/attr ()
+  (auth-source-pass--with-store '(("x.com" (secret . "a"))
+                                  ("disroot.org" (secret . "b")
+                                   ("user" . "akib") ("port" . "42"))
+                                  ("z.com" (secret . "c")))
+    (auth-source-pass-enable)
+    (let* ((auth-source-pass-extra-query-keywords t)
+           results)
+
+      ;; Non-matching query param.
+      (setq results (auth-source-search :host "disroot.org" :user "?" :max 2))
+      (should-not results)
+
+      ;; No query params matching attrs.
+      (setq results (auth-source-search :host "disroot.org" :max 2))
+      (dolist (result results)
+        (setf (plist-get result :secret) (auth-info-password result)))
+      (should (equal results
+                     '(( :host "disroot.org" :user "akib"
+                         :port "42" :secret "b"))))
+
+      ;; Matching user query param.
+      (setq results (auth-source-search :host "disroot.org" :user "akib"))
+      (dolist (result results)
+        (setf (plist-get result :secret) (auth-info-password result)))
+      (should (equal results
+                     '(( :host "disroot.org" :user "akib"
+                         :port "42" :secret "b"))))
+
+      ;; Matching port typed query param.
+      (setq results (auth-source-search :host "disroot.org" :port 42))
+      (dolist (result results)
+        (setf (plist-get result :secret) (auth-info-password result)))
+      (should (equal results
+                     '(( :host "disroot.org" :user "akib"
+                         :port 42 :secret "b")))))))
+
+(ert-deftest auth-source-pass-extra-query-keywords--netrc-akib/require ()
+  (ert-with-temp-file netrc-file
+    :text "\
+machine x.com password a
+machine disroot.org user akib password b
+machine z.com password c
+"
+    (let* ((auth-sources (list netrc-file))
+           (auth-source-do-cache nil)
+           (results (auth-source-search :host "disroot.org"
+                                        :require '(:user) :max 2)))
+      (dolist (result results)
+        (setf (plist-get result :secret) (auth-info-password result)))
+      (should (equal results
+                     '((:host "disroot.org" :user "akib" :secret "b")))))))
+
+(ert-deftest auth-source-pass-extra-query-keywords--akib/attr/require ()
+  (auth-source-pass--with-store '(("x.com" (secret . "a"))
+                                  ("disroot.org" (secret . "b")
+                                   ("user" . "akib"))
+                                  ("z.com" (secret . "c")))
+    (auth-source-pass-enable)
+    (let* ((auth-source-pass-extra-query-keywords t)
+           (results (auth-source-search :host "disroot.org"
+                                        :require '(:user) :max 2)))
+      (dolist (result results)
+        (setf (plist-get result :secret) (auth-info-password result)))
+      (should (equal results
+                     '((:host "disroot.org" :user "akib" :secret "b")))))))
+
 ;; Searches for :host are case-sensitive, and a returned host isn't
 ;; normalized.
 
@@ -632,11 +699,19 @@ auth-source-pass-extra-query-keywords--host
 ;; A retrieved store entry mustn't be nil regardless of whether its
 ;; path contains port or user components.
 
+(ert-deftest auth-source-pass-extra-query-keywords--netrc-baseline ()
+  (ert-with-temp-file netrc-file
+    :text "machine foo\n"
+    (let* ((auth-sources (list netrc-file))
+           (auth-source-do-cache nil)
+           (results (auth-source-search :host "foo")))
+      (should (equal results '((:host "foo")))))))
+
 (ert-deftest auth-source-pass-extra-query-keywords--baseline ()
   (let ((auth-source-pass-extra-query-keywords t))
-    (auth-source-pass--with-store '(("x.com"))
+    (auth-source-pass--with-store '(("foo"))
       (auth-source-pass-enable)
-      (should-not (auth-source-search :host "x.com")))))
+      (should (equal (auth-source-search :host "foo") '((:host "foo")))))))
 
 ;; Output port type (int or string) matches that of input parameter.
 
-- 
2.45.2


--=-=-=--




Information forwarded to bug-gnu-emacs@HIDDEN:
bug#72441; Package emacs. Full text available.

Message received at submit <at> debbugs.gnu.org:


Received: (at submit) by debbugs.gnu.org; 3 Aug 2024 11:13:07 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Sat Aug 03 07:13:07 2024
Received: from localhost ([127.0.0.1]:54139 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1saCh7-0001VM-4W
	for submit <at> debbugs.gnu.org; Sat, 03 Aug 2024 07:13:07 -0400
Received: from lists.gnu.org ([209.51.188.17]:49506)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <bjorn.bidar@HIDDEN>) id 1saCh3-0001Uw-CF
 for submit <at> debbugs.gnu.org; Sat, 03 Aug 2024 07:13:03 -0400
Received: from eggs.gnu.org ([2001:470:142:3::10])
 by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.90_1) (envelope-from <bjorn.bidar@HIDDEN>)
 id 1saCgj-0000fG-Jw
 for bug-gnu-emacs@HIDDEN; Sat, 03 Aug 2024 07:12:41 -0400
Received: from thaodan.de ([185.216.177.71])
 by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.90_1) (envelope-from <bjorn.bidar@HIDDEN>)
 id 1saCge-0007uG-Oy
 for bug-gnu-emacs@HIDDEN; Sat, 03 Aug 2024 07:12:41 -0400
Received: from odin (dsl-trebng12-50dc75-154.dhcp.inet.fi [80.220.117.154])
 by thaodan.de (Postfix) with ESMTPSA id 8CC02D00080
 for <bug-gnu-emacs@HIDDEN>; Sat,  3 Aug 2024 14:12:34 +0300 (EEST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=thaodan.de; s=mail;
 t=1722683554; bh=avRJuQuAL3ai1NnFeVShZkdx+wKv2rjIJvz97+wqX40=;
 h=From:To:Subject:Date;
 b=uuv7m7yQ46lt8wcIrqPPHmFt86q6lk+4RbETUDQVeW2h/DGqRcWAatbiJXvbBbUPM
 VcEpRJ75rHdWyZbhOb9dKfEHiPCtGVZyaUClmexRrTz5GVpDMU/Uh/IeNYsJ04VOKY
 2z8XM01M0F3cgAtdz6smZS/gbDDPvzLrk51+7NUKuXU8hawYLAD1MEVLFPKOsMaEmE
 AMWdpN8K3K0/LUUD0BvToPUCBCvCa5LiuETwl7Z8cNQufGcXM88LY8rT3X8gZgAQ13
 Aj0WKx/4RPIUmaSRv9/GuCmGlcgSWeFii+eF6MncXAT8vsPuZl/2yjZFZwr1pgbd3x
 OnUzruxyCcCT5NwYXSc0lkgmvfd3O+qb7ChxPpLsAMM1ntvGCVU1HvSdKebsY3ajYK
 O95tznZWpJtQ5/agYHJFRsVzG6Ngc5r78kkS4qBHVD0Qfz3dvTqoqk7++paLzjIfKj
 32pxXMgnjc8vSNXP1IhSLLxG7lBb/OOkOz9gYRpIO7ubShOHWF9BYTFU0JoNduzO6h
 +9taGwjEHEipC9Cct5vMSUDNqc5LNK/1rZjYoq/CVjKVTVTJABVxT095vNbaJGw7N8
 Elwxpja1FHHcmYQ1UvJXLOp4r8yXDeTyuGsqQXY4dYb9q1Eys0Zt7meI6UK0r4KGot
 uoZsJNYNFYx142zrETip80UQ=
From: =?utf-8?Q?Bj=C3=B6rn?= Bidar <bjorn.bidar@HIDDEN>
To: bug-gnu-emacs@HIDDEN
Subject: 31.0.50; Auth-source-pass doesn't match password attributes or
 hosts without user when extra-query-keywords is true
X-Debbugs-Cc: 
Autocrypt: addr=bjorn.bidar@HIDDEN; prefer-encrypt=nopreference; keydata=
 mDMEZNfpPhYJKwYBBAHaRw8BAQdACBEmr+0xwIIHZfIDlZmm7sa+lHHSb0g9FZrN6qE6ru60JUJq
 w7ZybiBCaWRhciA8Ympvcm4uYmlkYXJAdGhhb2Rhbi5kZT6IlgQTFgoAPgIbAwULCQgHAgIiAgYV
 CgkICwIEFgIDAQIeBwIXgBYhBFHxdut1RzAepymoq1wbdKFlHF9oBQJk1/YmAhkBAAoJEFwbdKFl
 HF9oB9cBAJoIIGQKXm4cpap+Flxc/EGnYl0123lcEyzuduqvlDT0AQC3OlFKm/OiqJ8IMTrzJRZ8
 phFssTkSrrFXnM2jm5PYDoiTBBMWCgA7FiEEUfF263VHMB6nKairXBt0oWUcX2gFAmTX6T4CGwMF
 CwkIBwICIgIGFQoJCAsCBBYCAwECHgcCF4AACgkQXBt0oWUcX2hbCQEAtru7kvM8hi8zo6z9ux2h
 K+B5xViKuo7Z8K3IXuK5ugwA+wUfKzomzdBPhfxDsqLcEziGRxoyx0Q3ld9aermBUccHtBxCasO2
 cm4gQmlkYXIgPG1lQHRoYW9kYW4uZGU+iJMEExYKADsCGwMFCwkIBwICIgIGFQoJCAsCBBYCAwEC
 HgcCF4AWIQRR8XbrdUcwHqcpqKtcG3ShZRxfaAUCZNf2FQAKCRBcG3ShZRxfaCzSAP4hZ7cSp0YN
 XYpcjHdsySh2MuBhhoPeLGXs+2kSiqBiOwD/TP8AgPEg/R+SI9GI9on7fBJJ0mp2IT8kZ2rhDOjg
 gA6IkwQTFgoAOxYhBFHxdut1RzAepymoq1wbdKFlHF9oBQJk1+ntAhsDBQsJCAcCAiICBhUKCQgL
 AgQWAgMBAh4HAheAAAoJEFwbdKFlHF9oBgwA/iQHwe0VL4Df4GGTYlNjMSHFlIkBmN4UfYGLYj3E
 TrOUAQC51M+M3cjsL8WHdpBz6VAo6df9d+rVwhQ9vQuFHqevArg4BGTX6T4SCisGAQQBl1UBBQEB
 B0Cbohc3JEfn005/cm0AOGjSsW1ZxAkgaoVNjbpqk4MgNAMBCAeIeAQYFgoAIBYhBFHxdut1RzAe
 pymoq1wbdKFlHF9oBQJk1+k+AhsMAAoJEFwbdKFlHF9ooHABAKGmrGBic/Vys3BBrOQiRB3Z7izO
 HwhqTRpAqFZtXS2nAQDZhp/5aYw1TZjTzkm1KVt9QiYnjd/MvxRE9iaY6x4mDbgzBGTX6T4WCSsG
 AQQB2kcPAQEHQAgRJq/tMcCCB2XyA5WZpu7GvpRx0m9IPRWazeqhOq7uiO8EGBYKACAWIQRR8Xbr
 dUcwHqcpqKtcG3ShZRxfaAUCZNf71AIbIgCBCRBcG3ShZRxfaHYgBBkWCgAdFiEEUfF263VHMB6n
 KairXBt0oWUcX2gFAmTX+9QACgkQXBt0oWUcX2jeSwD6AtWn0cuo8IF35YRo4o3cDRJnUfJnbvJy
 GxyCDThR+zYBAKG6/jdwmZkBQZKslnDAbMMd2WfiZZT5JW3IWC4EaKMO7HkBAKYPGZ3UbfkRvfFK
 S+pQ9CgtNfkSJQBtT1Ob7Y6nsacgAQCpyXN7yppmhW/oBgivITPy9Lkg+V4NK9WZYZCU9Q7LBA==
Date: Sat, 03 Aug 2024 14:12:33 +0300
Message-ID: <878qxdoo66.fsf@>
MIME-Version: 1.0
Content-Type: text/plain
Received-SPF: pass client-ip=185.216.177.71;
 envelope-from=bjorn.bidar@HIDDEN; helo=thaodan.de
X-Spam_score_int: -14
X-Spam_score: -1.5
X-Spam_bar: -
X-Spam_report: (-1.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1,
 DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, INVALID_MSGID=0.568,
 RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001,
 SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no
X-Spam_action: no action
X-Spam-Score: -0.2 (/)
X-Debbugs-Envelope-To: submit
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.2 (-)


I noticed that auth-source-pass doesn't match agains password file
attributes such as those containing :user and only matches password
files which contain a host and a user when
auth-source-pass-extra-query-keywords is true.

Steps to reproduce:
1. Setup pass with the following structure
   WorkingTest/example.com/foo
   FailingTest/example2.com
   FailingTest/example3.com with user: foo in the password file
2. (auth-source-pass-enable)
3. (setq auth-source-pass-extra-query-keywords t)
4. (auth-source-search :host "example" :user "foo") -> works
5. (auth-source-search :host "example2.com") -> fails
6. (auth-source-search :host "example3.com" :user "foo")

Auth-source-pass should be able to query the password file for
additional attributes if one of the previous attributes such as :host
match to it. Quering the file attributes is quite important in use cases where it doesn't make
sense to the user to have a host-folder/user-file structure in cases
where there's only one password for said host.
Same it should maybe also match against :host if no user was provided,
I don't know how other sources do this thou.

In GNU Emacs 31.0.50 (build 1, x86_64-suse-linux-gnu, GTK+ Version
3.24.43, cairo version 1.18.0)
Windowing system distributor 'The X.Org Foundation', version 11.0.12101012
System Description: openSUSE Tumbleweed

Configured using:
 'configure --disable-build-details --without-pop --with-mailutils
 --without-hesiod --with-gameuser=:games --with-kerberos
 --with-kerberos5 --with-file-notification=inotify --with-modules
 --enable-autodepend --enable-link-time-optimization --prefix=/usr
 --mandir=/usr/share/man --infodir=/usr/share/info --datadir=/usr/share
 --localstatedir=/var --sharedstatedir=/var/lib
 --libexecdir=/usr/libexec --with-file-notification=yes
 --libdir=/usr/lib64 --with-native-compilation=aot
 --enable-locallisppath=/usr/share/emacs/31.0.50/site-lisp:/usr/share/emacs/site-lisp
 --with-x --with-xim --with-sound --with-xpm --with-jpeg --with-tiff
 --with-gif --with-png --with-rsvg --with-dbus --with-xft --without-gpm
 --with-tree-sitter --with-x-toolkit=gtk --without-pgtk
 --with-toolkit-scroll-bars --x-includes=/usr/include
 --x-libraries=/usr/lib64 --with-libotf --with-m17n-flt --with-cairo
 --with-xwidgets --build=x86_64-suse-linux --with-dumping=pdumper
 build_alias=x86_64-suse-linux 'CC=sccache cc' 'CFLAGS=-O2 -Wall
 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3 -fstack-protector-strong
 -funwind-tables -fasynchronous-unwind-tables -fstack-clash-protection
 -Werror=return-type -flto=auto -march=znver3 -mmmx -mpopcnt -msse
 -msse2 -msse3 -mssse3 -msse4.1 -msse4.2 -mavx -mavx2 -msse4a -mno-fma4
 -mno-xop -mfma -mno-avx512f -mbmi -mbmi2 -maes -mpclmul -mno-avx512vl
 -mno-avx512bw -mno-avx512dq -mno-avx512cd -mno-avx512er -mno-avx512pf
 -mno-avx512vbmi -mno-avx512ifma -mno-avx5124vnniw -mno-avx5124fmaps
 -mno-avx512vpopcntdq -mno-avx512vbmi2 -mno-gfni -mvpclmulqdq
 -mno-avx512vnni -mno-avx512bitalg -mno-avx512bf16
 -mno-avx512vp2intersect -mno-3dnow -madx -mabm -mno-cldemote
 -mclflushopt -mclwb -mclzero -mcx16 -mno-enqcmd -mf16c -mfsgsbase
 -mfxsr -mno-hle -msahf -mno-lwp -mlzcnt -mmovbe -mno-movdir64b
 -mno-movdiri -mmwaitx -mno-pconfig -mpku -mno-prefetchwt1 -mprfchw
 -mno-ptwrite -mrdpid -mrdrnd -mrdseed -mno-rtm -mno-serialize -mno-sgx
 -msha -mshstk -mno-tbm -mno-tsxldtrk -mvaes -mno-waitpkg -mwbnoinvd
 -mxsave -mxsavec -mxsaveopt -mxsaves -mno-amx-tile -mno-amx-int8
 -mno-amx-bf16 -mno-uintr -mno-hreset -mno-kl -mno-widekl -mno-avxvnni
 -mno-avx512fp16 -mno-avxifma -mno-avxvnniint8 -mno-avxneconvert
 -mno-cmpccxadd -mno-amx-fp16 -mno-prefetchi -mno-raoint
 -mno-amx-complex --param l1-cache-size=32 --param l1-cache-line-size=64
 --param l2-cache-size=512 -mtune=znver3 -fno-optimize-sibling-calls -g
 -D_GNU_SOURCE -DGDK_DISABLE_DEPRECATION_WARNINGS
 -DGLIB_DISABLE_DEPRECATION_WARNINGS -pipe -Wno-pointer-sign
 -Wno-unused-variable -Wno-unused-label -DPDMP_BASE='\''"emacs-gtk"'\'''
 LDFLAGS=-Wl,-O2 'CXX=sccache c++'
 PKG_CONFIG_PATH=:/usr/lib64/pkgconfig:/usr/share/pkgconfig'

Configured features:
ACL CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GSETTINGS HARFBUZZ JPEG
LCMS2 LIBOTF LIBSELINUX LIBSYSTEMD LIBXML2 M17N_FLT MODULES NATIVE_COMP
NOTIFY INOTIFY PDUMPER PNG RSVG SECCOMP SOUND SQLITE3 THREADS TIFF
TOOLKIT_SCROLL_BARS TREE_SITTER WEBP X11 XDBE XIM XINPUT2 XPM XWIDGETS
GTK3 ZLIB

Important settings:
  value of $LC_MONETARY: fi_FI.UTF-8
  value of $LC_NUMERIC: POSIX
  value of $LANG: en_GB.UTF-8
  value of $XMODIFIERS: @im=local
  locale-coding-system: utf-8-unix

Major mode: Eshell

Minor modes in effect:
  eshell-prompt-mode: t
  eshell-pred-mode: t
  eshell-hist-mode: t
  eshell-cmpl-mode: t
  eshell-proc-mode: t
  eshell-arg-mode: t
  circe-lagmon-mode: t
  magit-wip-initial-backup-mode: t
  magit-wip-before-change-mode: t
  magit-wip-after-apply-mode: t
  magit-wip-after-save-mode: t
  magit-wip-mode: t
  magit-auto-revert-mode: t
  pdf-occur-global-minor-mode: t
  pdf-virtual-global-minor-mode: t
  global-atomic-chrome-edit-mode: t
  minions-mode: t
  back-button-mode: t
  recentf-mode: t
  global-auto-revert-mode: t
  savehist-mode: t
  emms-playing-time-display-mode: t
  emms-playing-time-mode: t
  gnus-desktop-notify-mode: t
  tracking-mode: t
  org-super-agenda-mode: t
  goto-address-mode: t
  global-git-commit-mode: t
  projectile-mode: t
  global-company-mode: t
  company-mode: t
  electric-pair-mode: t
  editorconfig-mode: t
  frames-only-mode: t
  windmove-mode: t
  marginalia-mode: t
  which-key-mode: t
  dirvish-override-dired-mode: t
  dired-async-mode: t
  helm-mode: t
  helm-minibuffer-history-mode: t
  global-so-long-mode: t
  global-emojify-mode: t
  emojify-mode: t
  change-cursor-mode: t
  doom-modeline-mode: t
  server-mode: t
  helm-autoresize-mode: t
  desktop-save-mode: t
  Info-persist-history-mode: t
  save-place-mode: t
  delete-selection-mode: t
  override-global-mode: t
  tooltip-mode: t
  global-eldoc-mode: t
  show-paren-mode: t
  electric-indent-mode: t
  mouse-wheel-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  undelete-frame-mode: t
  minibuffer-regexp-mode: t
  line-number-mode: t
  transient-mark-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t

Load-path shadows:
/home/bidar/.local/etc/emacs/lib/org/lisp/ox-koma-letter hides /home/bidar/.local/etc/emacs/lib/lisp/ox-koma-letter
/home/bidar/.local/etc/emacs/lib/org-contrib/lisp/ox-groff hides /home/bidar/.local/etc/emacs/lib/lisp/ox-groff
/home/bidar/.local/etc/emacs/lib/vim-modeline/vim-modeline hides /home/bidar/.local/etc/emacs/lib/lisp/vim-modeline
/home/bidar/.local/etc/emacs/lib/lisp/htmlize hides /home/bidar/.local/etc/emacs/lib/htmlize/htmlize
/home/bidar/.local/etc/emacs/lib/lisp/cursor-chg hides /home/bidar/.local/etc/emacs/lib/cursor-chg/cursor-chg
/home/bidar/.local/etc/emacs/lib/cmake-mode/cmake-mode hides /usr/share/emacs/site-lisp/cmake-mode
/home/bidar/.local/etc/emacs/lib/async/dired-async hides /usr/share/emacs/site-lisp/dired-async
/home/bidar/.local/etc/emacs/lib/async/async-bytecomp hides /usr/share/emacs/site-lisp/async-bytecomp
/home/bidar/.local/etc/emacs/lib/async/async-autoloads hides /usr/share/emacs/site-lisp/async-autoloads
/home/bidar/.local/etc/emacs/lib/async/smtpmail-async hides /usr/share/emacs/site-lisp/smtpmail-async
/home/bidar/.local/etc/emacs/lib/async/async hides /usr/share/emacs/site-lisp/async
/home/bidar/.local/etc/emacs/lib/compat/compat hides /usr/share/emacs/site-lisp/compat
/home/bidar/.local/etc/emacs/lib/compat/compat-29 hides /usr/share/emacs/site-lisp/compat-29
/home/bidar/.local/etc/emacs/lib/compat/compat-28 hides /usr/share/emacs/site-lisp/compat-28
/home/bidar/.local/etc/emacs/lib/compat/compat-27 hides /usr/share/emacs/site-lisp/compat-27
/home/bidar/.local/etc/emacs/lib/compat/compat-26 hides /usr/share/emacs/site-lisp/compat-26
/home/bidar/.local/etc/emacs/lib/compat/compat-25 hides /usr/share/emacs/site-lisp/compat-25
/home/bidar/.local/etc/emacs/lib/which-key/which-key hides /usr/share/emacs/31.0.50/lisp/which-key
/home/bidar/.local/etc/emacs/lib/transient/lisp/transient hides /usr/share/emacs/31.0.50/lisp/transient
/home/bidar/.local/etc/emacs/lib/editorconfig/editorconfig hides /usr/share/emacs/31.0.50/lisp/editorconfig
/home/bidar/.local/etc/emacs/lib/use-package/bind-key hides /usr/share/emacs/31.0.50/lisp/bind-key
/home/bidar/.local/etc/emacs/lib/editorconfig/editorconfig-tools hides /usr/share/emacs/31.0.50/lisp/editorconfig-tools
/home/bidar/.local/etc/emacs/lib/editorconfig/editorconfig-fnmatch hides /usr/share/emacs/31.0.50/lisp/editorconfig-fnmatch
/home/bidar/.local/etc/emacs/lib/editorconfig/editorconfig-core hides /usr/share/emacs/31.0.50/lisp/editorconfig-core
/home/bidar/.local/etc/emacs/lib/editorconfig/editorconfig-core-handle hides /usr/share/emacs/31.0.50/lisp/editorconfig-core-handle
/home/bidar/.local/etc/emacs/lib/editorconfig/editorconfig-conf-mode hides /usr/share/emacs/31.0.50/lisp/editorconfig-conf-mode
/home/bidar/.local/etc/emacs/lib/modus-themes/theme-loaddefs hides /usr/share/emacs/31.0.50/lisp/theme-loaddefs
/home/bidar/.local/etc/emacs/lib/use-package/use-package hides /usr/share/emacs/31.0.50/lisp/use-package/use-package
/home/bidar/.local/etc/emacs/lib/use-package/use-package-lint hides /usr/share/emacs/31.0.50/lisp/use-package/use-package-lint
/home/bidar/.local/etc/emacs/lib/use-package/use-package-jump hides /usr/share/emacs/31.0.50/lisp/use-package/use-package-jump
/home/bidar/.local/etc/emacs/lib/use-package/use-package-ensure hides /usr/share/emacs/31.0.50/lisp/use-package/use-package-ensure
/home/bidar/.local/etc/emacs/lib/use-package/use-package-ensure-system-package hides /usr/share/emacs/31.0.50/lisp/use-package/use-package-ensure-system-package
/home/bidar/.local/etc/emacs/lib/use-package/use-package-diminish hides /usr/share/emacs/31.0.50/lisp/use-package/use-package-diminish
/home/bidar/.local/etc/emacs/lib/use-package/use-package-delight hides /usr/share/emacs/31.0.50/lisp/use-package/use-package-delight
/home/bidar/.local/etc/emacs/lib/use-package/use-package-core hides /usr/share/emacs/31.0.50/lisp/use-package/use-package-core
/home/bidar/.local/etc/emacs/lib/use-package/use-package-bind-key hides /usr/share/emacs/31.0.50/lisp/use-package/use-package-bind-key
/home/bidar/.local/etc/emacs/lib/org/lisp/org-list hides /usr/share/emacs/31.0.50/lisp/org/org-list
/home/bidar/.local/etc/emacs/lib/org/lisp/org-refile hides /usr/share/emacs/31.0.50/lisp/org/org-refile
/home/bidar/.local/etc/emacs/lib/org/lisp/org-loaddefs hides /usr/share/emacs/31.0.50/lisp/org/org-loaddefs
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-lilypond hides /usr/share/emacs/31.0.50/lisp/org/ob-lilypond
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-core hides /usr/share/emacs/31.0.50/lisp/org/ob-core
/home/bidar/.local/etc/emacs/lib/org/lisp/ox-beamer hides /usr/share/emacs/31.0.50/lisp/org/ox-beamer
/home/bidar/.local/etc/emacs/lib/org/lisp/org hides /usr/share/emacs/31.0.50/lisp/org/org
/home/bidar/.local/etc/emacs/lib/org/lisp/org-table hides /usr/share/emacs/31.0.50/lisp/org/org-table
/home/bidar/.local/etc/emacs/lib/org/lisp/org-src hides /usr/share/emacs/31.0.50/lisp/org/org-src
/home/bidar/.local/etc/emacs/lib/org/lisp/org-num hides /usr/share/emacs/31.0.50/lisp/org/org-num
/home/bidar/.local/etc/emacs/lib/org/lisp/org-indent hides /usr/share/emacs/31.0.50/lisp/org/org-indent
/home/bidar/.local/etc/emacs/lib/org/lisp/org-capture hides /usr/share/emacs/31.0.50/lisp/org/org-capture
/home/bidar/.local/etc/emacs/lib/org/lisp/org-persist hides /usr/share/emacs/31.0.50/lisp/org/org-persist
/home/bidar/.local/etc/emacs/lib/org/lisp/org-element hides /usr/share/emacs/31.0.50/lisp/org/org-element
/home/bidar/.local/etc/emacs/lib/org/lisp/org-element-ast hides /usr/share/emacs/31.0.50/lisp/org/org-element-ast
/home/bidar/.local/etc/emacs/lib/org/lisp/org-colview hides /usr/share/emacs/31.0.50/lisp/org/org-colview
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-shell hides /usr/share/emacs/31.0.50/lisp/org/ob-shell
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-python hides /usr/share/emacs/31.0.50/lisp/org/ob-python
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-R hides /usr/share/emacs/31.0.50/lisp/org/ob-R
/home/bidar/.local/etc/emacs/lib/org/lisp/org-version hides /usr/share/emacs/31.0.50/lisp/org/org-version
/home/bidar/.local/etc/emacs/lib/org/lisp/ox hides /usr/share/emacs/31.0.50/lisp/org/ox
/home/bidar/.local/etc/emacs/lib/org/lisp/ox-texinfo hides /usr/share/emacs/31.0.50/lisp/org/ox-texinfo
/home/bidar/.local/etc/emacs/lib/org/lisp/ox-publish hides /usr/share/emacs/31.0.50/lisp/org/ox-publish
/home/bidar/.local/etc/emacs/lib/org/lisp/ox-org hides /usr/share/emacs/31.0.50/lisp/org/ox-org
/home/bidar/.local/etc/emacs/lib/org/lisp/ox-odt hides /usr/share/emacs/31.0.50/lisp/org/ox-odt
/home/bidar/.local/etc/emacs/lib/org/lisp/ox-md hides /usr/share/emacs/31.0.50/lisp/org/ox-md
/home/bidar/.local/etc/emacs/lib/org/lisp/ox-man hides /usr/share/emacs/31.0.50/lisp/org/ox-man
/home/bidar/.local/etc/emacs/lib/org/lisp/ox-latex hides /usr/share/emacs/31.0.50/lisp/org/ox-latex
/home/bidar/.local/etc/emacs/lib/org/lisp/ox-koma-letter hides /usr/share/emacs/31.0.50/lisp/org/ox-koma-letter
/home/bidar/.local/etc/emacs/lib/org/lisp/ox-icalendar hides /usr/share/emacs/31.0.50/lisp/org/ox-icalendar
/home/bidar/.local/etc/emacs/lib/org/lisp/ox-html hides /usr/share/emacs/31.0.50/lisp/org/ox-html
/home/bidar/.local/etc/emacs/lib/org/lisp/ox-ascii hides /usr/share/emacs/31.0.50/lisp/org/ox-ascii
/home/bidar/.local/etc/emacs/lib/org/lisp/org-timer hides /usr/share/emacs/31.0.50/lisp/org/org-timer
/home/bidar/.local/etc/emacs/lib/org/lisp/org-tempo hides /usr/share/emacs/31.0.50/lisp/org/org-tempo
/home/bidar/.local/etc/emacs/lib/org/lisp/org-protocol hides /usr/share/emacs/31.0.50/lisp/org/org-protocol
/home/bidar/.local/etc/emacs/lib/org/lisp/org-plot hides /usr/share/emacs/31.0.50/lisp/org/org-plot
/home/bidar/.local/etc/emacs/lib/org/lisp/org-pcomplete hides /usr/share/emacs/31.0.50/lisp/org/org-pcomplete
/home/bidar/.local/etc/emacs/lib/org/lisp/org-mouse hides /usr/share/emacs/31.0.50/lisp/org/org-mouse
/home/bidar/.local/etc/emacs/lib/org/lisp/org-mobile hides /usr/share/emacs/31.0.50/lisp/org/org-mobile
/home/bidar/.local/etc/emacs/lib/org/lisp/org-macs hides /usr/share/emacs/31.0.50/lisp/org/org-macs
/home/bidar/.local/etc/emacs/lib/org/lisp/org-macro hides /usr/share/emacs/31.0.50/lisp/org/org-macro
/home/bidar/.local/etc/emacs/lib/org/lisp/org-lint hides /usr/share/emacs/31.0.50/lisp/org/org-lint
/home/bidar/.local/etc/emacs/lib/org/lisp/org-keys hides /usr/share/emacs/31.0.50/lisp/org/org-keys
/home/bidar/.local/etc/emacs/lib/org/lisp/org-inlinetask hides /usr/share/emacs/31.0.50/lisp/org/org-inlinetask
/home/bidar/.local/etc/emacs/lib/org/lisp/org-id hides /usr/share/emacs/31.0.50/lisp/org/org-id
/home/bidar/.local/etc/emacs/lib/org/lisp/org-habit hides /usr/share/emacs/31.0.50/lisp/org/org-habit
/home/bidar/.local/etc/emacs/lib/org/lisp/org-goto hides /usr/share/emacs/31.0.50/lisp/org/org-goto
/home/bidar/.local/etc/emacs/lib/org/lisp/org-footnote hides /usr/share/emacs/31.0.50/lisp/org/org-footnote
/home/bidar/.local/etc/emacs/lib/org/lisp/org-fold hides /usr/share/emacs/31.0.50/lisp/org/org-fold
/home/bidar/.local/etc/emacs/lib/org/lisp/org-fold-core hides /usr/share/emacs/31.0.50/lisp/org/org-fold-core
/home/bidar/.local/etc/emacs/lib/org/lisp/org-feed hides /usr/share/emacs/31.0.50/lisp/org/org-feed
/home/bidar/.local/etc/emacs/lib/org/lisp/org-faces hides /usr/share/emacs/31.0.50/lisp/org/org-faces
/home/bidar/.local/etc/emacs/lib/org/lisp/org-entities hides /usr/share/emacs/31.0.50/lisp/org/org-entities
/home/bidar/.local/etc/emacs/lib/org/lisp/org-duration hides /usr/share/emacs/31.0.50/lisp/org/org-duration
/home/bidar/.local/etc/emacs/lib/org/lisp/org-datetree hides /usr/share/emacs/31.0.50/lisp/org/org-datetree
/home/bidar/.local/etc/emacs/lib/org/lisp/org-cycle hides /usr/share/emacs/31.0.50/lisp/org/org-cycle
/home/bidar/.local/etc/emacs/lib/org/lisp/org-ctags hides /usr/share/emacs/31.0.50/lisp/org/org-ctags
/home/bidar/.local/etc/emacs/lib/org/lisp/org-crypt hides /usr/share/emacs/31.0.50/lisp/org/org-crypt
/home/bidar/.local/etc/emacs/lib/org/lisp/org-compat hides /usr/share/emacs/31.0.50/lisp/org/org-compat
/home/bidar/.local/etc/emacs/lib/org/lisp/org-clock hides /usr/share/emacs/31.0.50/lisp/org/org-clock
/home/bidar/.local/etc/emacs/lib/org/lisp/org-attach hides /usr/share/emacs/31.0.50/lisp/org/org-attach
/home/bidar/.local/etc/emacs/lib/org/lisp/org-attach-git hides /usr/share/emacs/31.0.50/lisp/org/org-attach-git
/home/bidar/.local/etc/emacs/lib/org/lisp/org-archive hides /usr/share/emacs/31.0.50/lisp/org/org-archive
/home/bidar/.local/etc/emacs/lib/org/lisp/org-agenda hides /usr/share/emacs/31.0.50/lisp/org/org-agenda
/home/bidar/.local/etc/emacs/lib/org/lisp/ol hides /usr/share/emacs/31.0.50/lisp/org/ol
/home/bidar/.local/etc/emacs/lib/org/lisp/ol-w3m hides /usr/share/emacs/31.0.50/lisp/org/ol-w3m
/home/bidar/.local/etc/emacs/lib/org/lisp/ol-rmail hides /usr/share/emacs/31.0.50/lisp/org/ol-rmail
/home/bidar/.local/etc/emacs/lib/org/lisp/ol-mhe hides /usr/share/emacs/31.0.50/lisp/org/ol-mhe
/home/bidar/.local/etc/emacs/lib/org/lisp/ol-man hides /usr/share/emacs/31.0.50/lisp/org/ol-man
/home/bidar/.local/etc/emacs/lib/org/lisp/ol-irc hides /usr/share/emacs/31.0.50/lisp/org/ol-irc
/home/bidar/.local/etc/emacs/lib/org/lisp/ol-info hides /usr/share/emacs/31.0.50/lisp/org/ol-info
/home/bidar/.local/etc/emacs/lib/org/lisp/ol-gnus hides /usr/share/emacs/31.0.50/lisp/org/ol-gnus
/home/bidar/.local/etc/emacs/lib/org/lisp/ol-eww hides /usr/share/emacs/31.0.50/lisp/org/ol-eww
/home/bidar/.local/etc/emacs/lib/org/lisp/ol-eshell hides /usr/share/emacs/31.0.50/lisp/org/ol-eshell
/home/bidar/.local/etc/emacs/lib/org/lisp/ol-doi hides /usr/share/emacs/31.0.50/lisp/org/ol-doi
/home/bidar/.local/etc/emacs/lib/org/lisp/ol-docview hides /usr/share/emacs/31.0.50/lisp/org/ol-docview
/home/bidar/.local/etc/emacs/lib/org/lisp/ol-bibtex hides /usr/share/emacs/31.0.50/lisp/org/ol-bibtex
/home/bidar/.local/etc/emacs/lib/org/lisp/ol-bbdb hides /usr/share/emacs/31.0.50/lisp/org/ol-bbdb
/home/bidar/.local/etc/emacs/lib/org/lisp/oc hides /usr/share/emacs/31.0.50/lisp/org/oc
/home/bidar/.local/etc/emacs/lib/org/lisp/oc-natbib hides /usr/share/emacs/31.0.50/lisp/org/oc-natbib
/home/bidar/.local/etc/emacs/lib/org/lisp/oc-csl hides /usr/share/emacs/31.0.50/lisp/org/oc-csl
/home/bidar/.local/etc/emacs/lib/org/lisp/oc-bibtex hides /usr/share/emacs/31.0.50/lisp/org/oc-bibtex
/home/bidar/.local/etc/emacs/lib/org/lisp/oc-biblatex hides /usr/share/emacs/31.0.50/lisp/org/oc-biblatex
/home/bidar/.local/etc/emacs/lib/org/lisp/oc-basic hides /usr/share/emacs/31.0.50/lisp/org/oc-basic
/home/bidar/.local/etc/emacs/lib/org/lisp/ob hides /usr/share/emacs/31.0.50/lisp/org/ob
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-tangle hides /usr/share/emacs/31.0.50/lisp/org/ob-tangle
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-table hides /usr/share/emacs/31.0.50/lisp/org/ob-table
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-sqlite hides /usr/share/emacs/31.0.50/lisp/org/ob-sqlite
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-sql hides /usr/share/emacs/31.0.50/lisp/org/ob-sql
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-sed hides /usr/share/emacs/31.0.50/lisp/org/ob-sed
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-screen hides /usr/share/emacs/31.0.50/lisp/org/ob-screen
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-scheme hides /usr/share/emacs/31.0.50/lisp/org/ob-scheme
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-sass hides /usr/share/emacs/31.0.50/lisp/org/ob-sass
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-ruby hides /usr/share/emacs/31.0.50/lisp/org/ob-ruby
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-ref hides /usr/share/emacs/31.0.50/lisp/org/ob-ref
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-processing hides /usr/share/emacs/31.0.50/lisp/org/ob-processing
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-plantuml hides /usr/share/emacs/31.0.50/lisp/org/ob-plantuml
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-perl hides /usr/share/emacs/31.0.50/lisp/org/ob-perl
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-org hides /usr/share/emacs/31.0.50/lisp/org/ob-org
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-octave hides /usr/share/emacs/31.0.50/lisp/org/ob-octave
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-ocaml hides /usr/share/emacs/31.0.50/lisp/org/ob-ocaml
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-maxima hides /usr/share/emacs/31.0.50/lisp/org/ob-maxima
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-matlab hides /usr/share/emacs/31.0.50/lisp/org/ob-matlab
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-makefile hides /usr/share/emacs/31.0.50/lisp/org/ob-makefile
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-lua hides /usr/share/emacs/31.0.50/lisp/org/ob-lua
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-lob hides /usr/share/emacs/31.0.50/lisp/org/ob-lob
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-lisp hides /usr/share/emacs/31.0.50/lisp/org/ob-lisp
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-latex hides /usr/share/emacs/31.0.50/lisp/org/ob-latex
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-julia hides /usr/share/emacs/31.0.50/lisp/org/ob-julia
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-js hides /usr/share/emacs/31.0.50/lisp/org/ob-js
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-java hides /usr/share/emacs/31.0.50/lisp/org/ob-java
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-haskell hides /usr/share/emacs/31.0.50/lisp/org/ob-haskell
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-groovy hides /usr/share/emacs/31.0.50/lisp/org/ob-groovy
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-gnuplot hides /usr/share/emacs/31.0.50/lisp/org/ob-gnuplot
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-fortran hides /usr/share/emacs/31.0.50/lisp/org/ob-fortran
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-forth hides /usr/share/emacs/31.0.50/lisp/org/ob-forth
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-exp hides /usr/share/emacs/31.0.50/lisp/org/ob-exp
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-eval hides /usr/share/emacs/31.0.50/lisp/org/ob-eval
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-eshell hides /usr/share/emacs/31.0.50/lisp/org/ob-eshell
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-emacs-lisp hides /usr/share/emacs/31.0.50/lisp/org/ob-emacs-lisp
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-dot hides /usr/share/emacs/31.0.50/lisp/org/ob-dot
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-ditaa hides /usr/share/emacs/31.0.50/lisp/org/ob-ditaa
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-css hides /usr/share/emacs/31.0.50/lisp/org/ob-css
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-comint hides /usr/share/emacs/31.0.50/lisp/org/ob-comint
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-clojure hides /usr/share/emacs/31.0.50/lisp/org/ob-clojure
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-calc hides /usr/share/emacs/31.0.50/lisp/org/ob-calc
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-awk hides /usr/share/emacs/31.0.50/lisp/org/ob-awk
/home/bidar/.local/etc/emacs/lib/org/lisp/ob-C hides /usr/share/emacs/31.0.50/lisp/org/ob-C
/home/bidar/.local/etc/emacs/lib/compat/compat hides /usr/share/emacs/31.0.50/lisp/emacs-lisp/compat

Features:
(shadow emacsbug em-unix em-term em-script em-prompt em-pred em-ls
em-hist em-glob em-extpipe em-cmpl em-dirs em-basic em-banner em-alias
esh-mode esh-var eshell esh-cmd esh-ext esh-opt esh-proc esh-io esh-arg
esh-module esh-module-loaddefs esh-util make-mode move-text goto-chg
whitespace gitignore-mode dired-open helm-ls-git help-macro tabify
gnus-search eieio-opt speedbar ezimage dframe finder-inf gnus-delay
gnus-draft gitattributes-mode vc-dir two-column helm-descbinds mailalias
bbdb-pgp message-attachment-reminder bbdb-message gnus-alias
autocrypt-message git-rebase magit-extras shortdoc cl-print
adaptive-wrap adaptive-wrap-autoloads gitconfig-mode help-fns
emacsql-sqlite-builtin sqlite org-indent crux smart-region
multiple-cursors mc-separate-operations rectangular-region-mode
mc-mark-pop mc-edit-lines mc-hide-unmatched-lines-mode mc-mark-more
html-mode-expansions sgml-mode mc-cycle-cursors multiple-cursors-core
rect expand-region yaml-mode-expansions subword-mode-expansions
cperl-mode-expansions text-mode-expansions cc-mode-expansions
the-org-mode-expansions python-el-fgallina-expansions
er-basic-expansions expand-region-core expand-region-custom char-fold
helm-org-rifle misearch multi-isearch orgit-forge orgit doctor
helm-command org-clock-helpers flow-fill mastodon-notifications
mastodon-media mastodon-profile mastodon-auth mastodon-client plstore
mastodon mastodon-search mastodon-toot persist mastodon-http request
circe-lagmon ietf-drums-date gnus-gravatar gnus-cite message-view-patch
forge-repos forge-tablist forge-topics forge-commands forge-semi
forge-bitbucket buck forge-gogs gogs forge-gitea gtea forge-gitlab glab
forge-github ghub-graphql treepy gsexp ghub forge-notify forge-revnote
forge-pullreq forge-issue forge-topic yaml eieio-custom forge-post
markdown-mode forge-repo forge forge-core forge-db magit-popup
magit-bookmark magit-submodule magit-blame magit-stash magit-reflog
magit-bisect magit-push magit-pull magit-fetch magit-clone magit-remote
magit-commit magit-sequence magit-notes magit-worktree magit-tag
magit-merge magit-branch magit-reset magit-files magit-refs magit-status
magit magit-repos magit-apply magit-wip magit-log magit-diff smerge-mode
diff magit-core magit-autorevert magit-margin magit-transient
magit-process magit-mode w3m-form w3m-symbol w3m w3m-hist bookmark-w3m
w3m-ems w3m-favicon w3m-image w3m-fb tab-line w3m-proc w3m-util
mm-archive mail-extr textsec uni-scripts idna-mapping ucs-normalize
uni-confusable textsec-check gnus-async gnus-bcklg bbdb-gnus-aux qp
gnus-ml gnus-demon autocrypt-gnus nndraft nnmh gnus-topic utf-7 epa-file
nnfolder bbdb-gnus bbdb-mua nnnil hydra lv winner tramp-archive
tramp-gvfs zeroconf helm-x-files helm-for-files helm-external
network-stream pulse image-file image-converter company-shell
rpm-spec-mode company-anaconda highlight-indent-guides cap-words
superword subword anaconda-mode pythonic tramp-cache time-stamp tramp-sh
dired-collapse dirvish-yank dirvish-subtree dirvish-collapse
dirvish-icons dirvish-vc dirvish-widgets pdf-history pdf-outline
pdf-links pdf-annot pdf-sync pdf-occur tablist tablist-filter
semantic/wisent/comp semantic/wisent semantic/wisent/wisent
semantic/util-modes semantic/util semantic semantic/tag semantic/lex
semantic/fw mode-local cedet pdf-isearch pdf-misc pdf-virtual
whole-line-or-region pdf-tools package pdf-view pdf-cache pdf-info
pdf-util pdf-macs generic-x skeleton generic atomic-chrome websocket
minions back-button smartrep helm-projectile recentf tree-widget
autorevert cus-start savehist org-edit-indirect edit-indirect org-bug
bug-search bug-comment-mode bug-backend-bz-rpc bug-list-mode bug-mode
bug-format bug-rpc bug-debug bug-search-common bug-common-functions
bug-persistent-data bug-custom yeetube yeetube-mpv socks elfeed-autotag
elfeed-score elfeed-score-maint elfeed-score-scoring elfeed-score-serde
elfeed-score-rule-stats elfeed-score-rules elfeed-score-log elfeed-tube
elfeed-tube-utils aio elfeed-protocol-owncloud elfeed-protocol
elfeed-protocol-common elfeed-show elfeed-search rainbow-delimiters
ligature symbol-overlay hideshow vc-hg vc-bzr vc-src vc-sccs vc-svn
vc-cvs vc-rcs log-view bug-reference elfeed-csv elfeed elfeed-curl
elfeed-log elfeed-db elfeed-lib xml-query emms-i18n emms-history
emms-score emms-stream-info emms-metaplaylist-mode emms-bookmarks
emms-cue emms-mode-line-icon emms-browser sort emms-volume
emms-volume-sndioctl emms-volume-mixerctl emms-volume-pulse
emms-volume-amixer emms-playlist-sort emms-last-played emms-player-mpd
emms-playing-time emms-lyrics emms-url emms-player-simple emms-streams
emms-show-all emms-tag-editor emms-tag-tracktag emms-info-mp3info
emms-mark emms-mode-line emms-cache emms-playlist-mode emms-info-native
emms-info-native-spc emms-info-native-mp3 emms-info-native-ogg
emms-info-native-opus emms-info-native-flac emms-info-native-vorbis
emms-info-libtag emms-info emms-later-do emms-source-playlist
emms-source-file locate emms emms-compat khardel gravatar dns smiley
autocrypt gnus-icalendar org-capture smtpmail-async smtpmail gnus-agent
gnus-srvr gnus-score score-mode nnvirtual gnus-msg nntp gnus-cache
gnus-desktop-notify bbdb-vcard bbdb-com bbdb-vcard-vcard21 bbdb
bbdb-site timezone mastodon-async mastodon-tl url-cache mpv tq
mastodon-iso lui-track company-emoji company-emoji-list helm-circe
circe-notifications circe-display-images circe-color-nicks circe
lui-irc-colors irc lcs lui-logging lui-format lui tracking shorten
flyspell circe-compat ical2org org-modern org-caldav icalendar url-dav
url-http url-auth url-gw nsm url-handlers ox-koma-letter ox-extra
org-pomodoro alert notifications org-timer org-expiry ol-man org-clock
org-protocol ob-sqlite ob-sql ob-shell ob-python python ob-plantuml
ob-org ob-octave ob-lua ob-js ob-gnuplot ox-odt rng-loc rng-uri
rng-parse rng-match rng-dt rng-util rng-pttrn nxml-parse nxml-ns
nxml-enc xmltok nxml-util ox-latex ox-icalendar org-super-agenda ts
org-habit org-duration cdlatex reftex reftex-loaddefs reftex-vars
texmathp org-appear ws-butler selected jinx oc-basic ol-eww eww
url-queue mm-url ol-rmail ol-mhe ol-irc ol-info ol-gnus nnselect
gnus-art mm-uu mml2015 mm-view mml-smime smime gnutls dig gnus-sum shr
pixel-fill kinsoku url-file svg dom gnus-group gnus-undo gnus-start
gnus-dbus dbus gnus-cloud nnimap nnmail mail-source utf7 nnoo gnus-spec
gnus-int gnus-range gnus-win gnus nnheader range ol-docview doc-view
ol-bibtex bibtex ol-bbdb ol-w3m ol-doi org-link-doi goto-addr view
mule-util cal-china cal-bahai cal-islam cal-hebrew holidays
holiday-loaddefs cal-iso cal-julian lunar solar cal-dst vim-modeline
appt org-agenda ox-html table ox-ascii ox-publish ox org-element
org-persist org-id org-refile org-element-ast avl-tree ob-dot ob-ditaa
ob-clojure ob-C outshine outshine-org-cmds outorg smartparens-org
smartparens-text smartparens loadhist org-archive-subtree-hierarchy
org-archive org ob ob-tangle ob-ref ob-lob ob-table ob-exp org-macro
org-src ob-comint org-pcomplete org-list org-footnote org-faces
org-entities ob-emacs-lisp ob-core ob-eval org-cycle org-table ol
org-fold org-fold-core org-keys oc org-loaddefs org-version org-compat
org-macs noutline outline salt-mode rst mmm-jinja2 yaml-mode
perl-completion woman man ffap dabbrev cperl-mode facemenu helm-elisp
helm-eval edebug debug backtrace cc-mode cc-fonts cc-guess cc-menus
cc-cmds cc-styles cc-align cc-engine cc-vars cc-defs ggtags ewoc
flycheck-color-mode-line flycheck jka-compr let-alist meson-mode
bitbake-modes bitbake autoinsert conf-bitbake-mode conf-mode bitbake-ff
find-file bitbake-mmm sh-script smie treesit executable mmm-mode
mmm-univ mmm-class mmm-region mmm-auto mmm-vars mmm-utils mmm-compat
bitbake-functions bitbake-compat xterm-color vc-osc vc magit-libgit
libgit libegit2 git-commit magit-git magit-base which-func imenu vc-git
diff-mode track-changes vc-dispatcher magit-section benchmark
cursor-sensor crm log-edit message sendmail yank-media puny rfc822 mml
mml-sec epa epg rfc6068 epg-config gnus-util mm-decode mm-bodies
mm-encode mail-parse rfc2231 rfc2047 rfc2045 mm-util ietf-drums
mail-prsvr mailabbrev mail-utils gmm-utils mailheader pcvs-util add-log
diary-lib diary-loaddefs cal-menu calendar cal-loaddefs midnight
vlf-setup multi-vterm company-yasnippet vterm face-remap color term
disp-table ehelp vterm-module term/xterm xterm projectile ibuf-ext
ibuffer ibuffer-loaddefs company-oddmuse company-keywords company-etags
etags fileloop generator xref project company-gtags company-dabbrev-code
company-dabbrev company-files company-clang company-capf company-cmake
company-semantic company-template company-bbdb company elec-pair
editorconfig editorconfig-core editorconfig-core-handle
editorconfig-fnmatch wgrep-ag frames-only-mode windmove i3-integration
i3 bindat marginalia which-key dirvish transient helm-dired-history
dired-ranger dired-avfs dired-rainbow dired-filter dired-hacks-utils
dired-x dired-async dired-du find-dired wdired dired-aux helm-icons
treemacs-icons treemacs-scope treemacs-themes treemacs-core-utils
treemacs-logging treemacs-customization pfuture inline hl-line
treemacs-faces helm-bookmark helm-net browse-url xml url url-proxy
url-privacy url-expand url-methods url-history url-cookie url-domsuf
url-util mailcap helm-adaptive helm-info bookmark helm-mode helm-misc
helm-files image-dired image-dired-tags image-dired-external
image-dired-util image-mode dired dired-loaddefs exif filenotify tramp
trampver tramp-integration files-x tramp-message tramp-compat xdg
parse-time iso8601 time-date tramp-loaddefs helm-buffers all-the-icons
all-the-icons-faces data-material data-weathericons data-octicons
data-fileicons data-faicons data-alltheicons helm-occur helm-tags
helm-locate helm-grep wgrep-helm wgrep grep compile text-property-search
helm-regexp format-spec helm-utils helm-help helm-types so-long emojify
apropos tar-mode arc-mode archive-mode ht cursor-chg doom-modeline
doom-modeline-segments doom-modeline-env doom-modeline-core shrink-path
f s dash nerd-icons nerd-icons-faces nerd-icons-data
nerd-icons-data-mdicon nerd-icons-data-flicon nerd-icons-data-codicon
nerd-icons-data-devicon nerd-icons-data-sucicon nerd-icons-data-wicon
nerd-icons-data-faicon nerd-icons-data-powerline nerd-icons-data-octicon
nerd-icons-data-pomicon nerd-icons-data-ipsicon modus-vivendi-theme
modus-themes helm-pass password-store with-editor shell pcomplete comint
ansi-osc ansi-color ring server helm helm-global-bindings helm-easymenu
edmacro kmacro helm-core async-bytecomp helm-source helm-multi-match
helm-lib async auth-source-pass url-parse url-vars auth-source
password-cache printing ps-print ps-print-loaddefs lpr desktop frameset
derived advice info+ thingatpt cl saveplace delsel no-littering
epkg-elpa json map epkg-utils epkg-list epkg-desc find-func epkg closql
emacsql-sqlite-common emacsql emacsql-compiler eieio-base eieio byte-opt
eieio-core cl-macs llama comp-run compat use-package use-package-ensure
use-package-delight use-package-diminish use-package-bind-key bind-key
easy-mmode use-package-core zop-to-char-autoloads yeetube-autoloads
yasnippet-autoloads yaml-mode-autoloads yaml-autoloads
xterm-color-autoloads ws-butler-autoloads with-editor-autoloads
whole-line-or-region-autoloads which-key-autoloads wgrep-autoloads
websocket-autoloads web-mode-autoloads w3m-autoloads vlf-autoloads
visual-regexp-autoloads vim-modeline-autoloads vc-osc-autoloads
uuidgen-autoloads use-package-autoloads ts-autoloads treepy-autoloads
treemacs-nerd-icons-autoloads treemacs-autoloads transient-autoloads
toml-mode-autoloads systemd-autoloads symbol-overlay-autoloads
swiper-helm-autoloads ssh-config-mode-autoloads spinner-autoloads
smartrep-autoloads smartparens-autoloads smart-region-autoloads
skewer-mode-autoloads simple-httpd-autoloads shrink-path-autoloads
selected-autoloads salt-mode-autoloads s-autoloads
rpm-spec-mode-autoloads rich-minority-autoloads request-autoloads
rainbow-delimiters-autoloads qt-pro-mode-autoloads qml-mode-autoloads
pythonic-autoloads projectile-autoloads posframe-autoloads
pos-tip-autoloads popup-autoloads plantuml-mode-autoloads
pkgbuild-mode-autoloads piper-autoloads pfuture-autoloads
perspective-autoloads persp-mode-autoloads persist-autoloads
password-store-autoloads pass-autoloads outshine-autoloads
outorg-autoloads orgit-forge-autoloads orgit-autoloads
org-vcard-autoloads org-tree-slide-autoloads org-super-agenda-autoloads
org-pomodoro-autoloads org-modern-autoloads org-edit-indirect-autoloads
org-contrib-autoloads org-contacts-autoloads org-clock-helpers-autoloads
org-caldav-autoloads org-appear-autoloads org-autoloads
no-littering-autoloads nginx-mode-autoloads nerd-icons-ibuffer-autoloads
nerd-icons-autoloads navi-mode-autoloads multiple-cursors-autoloads
multi-vterm-autoloads mpv-autoloads move-text-autoloads
modus-themes-autoloads mode-icons-autoloads mmm-mode-autoloads
mmm-jinja2-autoloads minions-autoloads message-x-autoloads
message-view-patch-autoloads message-attachment-reminder-autoloads
meson-mode-autoloads mastodon-autoloads markdown-mode-autoloads
marginalia-autoloads magit-popup-autoloads magit-autoloads
lua-mode-autoloads lsp-ui-autoloads lsp-treemacs-autoloads
lsp-mode-autoloads lsp-docker-autoloads logview-autoloads
llama-autoloads lisp-autoloads link-hint-autoloads ligature-autoloads
levenshtein-autoloads khardel-autoloads js2-mode-autoloads
journalctl-autoloads jira-markup-mode-autoloads ivy-autoloads
irony-autoloads ir-black-theme-autoloads info+-autoloads iedit-autoloads
ical2org-autoloads ibuffer-projectile-autoloads
i3wm-config-mode-autoloads i3-autoloads hydra-autoloads
htmlize-autoloads ht-autoloads highlight-indent-guides-autoloads
helm-projectile-autoloads helm-pass-autoloads helm-org-rifle-autoloads
helm-make-autoloads helm-ls-git-autoloads helm-icons-autoloads
helm-ext-autoloads helm-emms-autoloads helm-dired-history-autoloads
helm-descbinds-autoloads helm-circe-autoloads helm-autoloads
guess-language-autoloads grep-context-autoloads goto-chg-autoloads
gnus-recent-autoloads gnus-notes-autoloads gnus-desktop-notify-autoloads
gnus-alias-autoloads gitconfig-autoloads git-modes-autoloads
ghub-autoloads ggtags-autoloads frames-only-mode-autoloads
forge-autoloads flycheck-color-mode-line-autoloads flycheck-autoloads
fedi-autoloads f-autoloads extmap-autoloads expand-region-autoloads
evil-multiedit-autoloads evil-autoloads emojify-autoloads
emacsql-autoloads elixir-mode-autoloads elfeed-tube-autoloads
elfeed-summary-autoloads elfeed-score-autoloads
elfeed-protocol-autoloads elfeed-autotag-autoloads elfeed-autoloads
el-mock-autoloads eimp-autoloads editorconfig-autoloads
edit-indirect-autoloads dumb-jump-autoloads doom-modeline-autoloads
docbook-autoloads dirvish-autoloads dired-rsync-autoloads
dired-hacks-autoloads dired-du-autoloads devhelp-autoloads
deferred-autoloads default-text-scale-autoloads debbugs-autoloads
datetime-autoloads dash-autoloads dap-mode-autoloads
cursor-chg-autoloads crux-autoloads copy-as-format-autoloads
compat-autoloads company-shell-autoloads company-quickhelp-autoloads
company-nginx-autoloads company-lua-autoloads company-irony-autoloads
company-emoji-autoloads company-anaconda-autoloads company-autoloads
code-review-autoloads cmake-mode-autoloads cmake-font-lock-autoloads
closql-autoloads circe-notifications-autoloads circe-autoloads
cdlatex-autoloads ccls-autoloads buttercup-autoloads bui-autoloads
bug-mode-autoloads bitbake-modes-autoloads bbdb-vcard-autoloads
bbdb-loaddefs back-button-autoloads avy-autoloads autocrypt-autoloads
auto-compile-autoloads atomic-chrome-autoloads async-autoloads
anaconda-mode-autoloads all-the-icons-autoloads alert-autoloads
aio-autoloads ag-autoloads ace-window-autoloads ace-link-autoloads
a-autoloads 2048-game-autoloads borg loaddefs-gen generate-lisp-file
lisp-mnt radix-tree info cus-edit pp pcase cus-load wid-edit comp cl-seq
comp-cstr cl-extra help-mode comp-common warnings icons subr-x rx gv
cl-loaddefs cl-lib bytecomp byte-compile preview-latex auctex tex-site
ispell rmc iso-transl tooltip cconv eldoc paren electric uniquify
ediff-hook vc-hooks lisp-float-type elisp-mode mwheel term/x-win x-win
term/common-win x-dnd touch-screen tool-bar dnd fontset image regexp-opt
fringe tabulated-list replace newcomment text-mode lisp-mode prog-mode
register page tab-bar menu-bar rfn-eshadow isearch easymenu timer select
scroll-bar mouse jit-lock font-lock syntax font-core term/tty-colors
frame minibuffer nadvice seq simple cl-generic indonesian philippine
cham georgian utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao
korean japanese eucjp-ms cp51932 hebrew greek romanian slovak czech
european ethiopic indian cyrillic chinese composite emoji-zwj charscript
charprop case-table epa-hook jka-cmpr-hook help abbrev obarray oclosure
cl-preloaded button loaddefs theme-loaddefs faces cus-face macroexp
files window text-properties overlay sha1 md5 base64 format env
code-pages mule custom widget keymap hashtable-print-readable backquote
threads xwidget-internal dbusbind inotify lcms2 dynamic-setting
system-font-setting font-render-setting cairo gtk x-toolkit xinput2 x
multi-tty move-toolbar make-network-process native-compile emacs)

Memory information:
((conses 16 8814971 1834230) (symbols 48 113156 6)
 (strings 32 2138810 377553) (string-bytes 1 196033441)
 (vectors 16 420969) (vector-slots 8 7713005 1814464)
 (floats 8 10276 45198) (intervals 56 524388 35453) (buffers 992 455))




Acknowledgement sent to Björn Bidar <bjorn.bidar@HIDDEN>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs@HIDDEN. Full text available.
Report forwarded to bug-gnu-emacs@HIDDEN:
bug#72441; Package emacs. Full text available.
Please note: This is a static page, with minimal formatting, updated once a day.
Click here to see this page with the latest information and nicer formatting.
Last modified: Sun, 12 Jan 2025 05:45:02 UTC

GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997 nCipher Corporation Ltd, 1994-97 Ian Jackson.