git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Usman Akinyemi <usmanakinyemi202@gmail.com>
To: christian.couder@gmail.com, git@vger.kernel.org
Cc: Johannes.Schindelin@gmx.de, gitster@pobox.com,
	johncai86@gmail.com, me@ttaylorr.com, phillip.wood@dunelm.org.uk,
	ps@pks.im, rsbecker@nexbridge.com, sunshine@sunshineco.com
Subject: [PATCH v5 0/6][Outreachy] extend agent capability to include OS name
Date: Fri, 14 Feb 2025 18:06:10 +0530	[thread overview]
Message-ID: <20250214123734.1403120-1-usmanakinyemi202@gmail.com> (raw)
In-Reply-To: <20250205185246.111447-1-usmanakinyemi202@gmail.com>

For debugging, statistical analysis, and security purposes, it can
be valuable for Git servers to know the operating system the clients
are using.

For example:
- A server noticing that a client is using an old Git version with
security issues on one platform, like macOS, could verify if the
user is indeed running macOS before sending a message to upgrade."
- Similarly, a server identifying a client that could benefit from
an upgrade (e.g., for performance reasons) could better customize the
message it sends to nudge the client to upgrade.

Our current agent capability is in the form of "package/version" (e.g.,
"git/1.8.3.1"). Let's extend it to include the operating system name (os)
i.e in the form "package/version os" (e.g., "git/1.8.3.1 Linux").
The operating system name is retrieved using the 'sysname' field of 
he `uname(2)` system call or its equivalent.

Including OS details in the agent capability simplifies implementation,
maintains backward compatibility, avoids introducing a new capability,
encourages adoption across Git-compatible software, and enhances
debugging by providing complete environment information without affecting
functionality.

Note that, due to differences between `uname(1)` (command-line
utility) and `uname(2)` (system call) outputs on Windows,
`transfer.advertiseOSVersion` is set to false on Windows during
testing. See the message part of patch 5/6 for more details.

My mentor, Christian Couder, sent a previous patch series about this
before. You can find it here
https://lore.kernel.org/git/20240619125708.3719150-1-christian.couder@gmail.com/

Changes since v4
================
 - Remove the implementation of transfer.advertiseOSInfo config. 
 - Update the documentation.
 - Move the `os_info()` function into "version.c" file.

Usman Akinyemi (6):
  version: replace manual ASCII checks with isprint() for clarity
  version: refactor redact_non_printables()
  version: refactor get_uname_info()
  version: extend get_uname_info() to hide system details
  t5701: add setup test to remove side-effect dependency
  agent: advertise OS name via agent capability

 Documentation/gitprotocol-v2.txt | 13 +++---
 builtin/bugreport.c              | 13 +-----
 t/t5701-git-serve.sh             | 26 ++++++++++--
 t/test-lib-functions.sh          |  8 ++++
 version.c                        | 69 +++++++++++++++++++++++++++++---
 version.h                        | 10 +++++
 6 files changed, 115 insertions(+), 24 deletions(-)

Range-diff versus v4:

1:  82b62c5e66 = 1:  82b62c5e66 version: replace manual ASCII checks with isprint() for clarity
2:  0a7d7ce871 = 2:  0a7d7ce871 version: refactor redact_non_printables()
3:  0187db59a4 = 3:  0187db59a4 version: refactor get_uname_info()
4:  d3a3573594 = 4:  d3a3573594 version: extend get_uname_info() to hide system details
5:  3e0e98f23d = 5:  3e0e98f23d t5701: add setup test to remove side-effect dependency
6:  67a2767026 ! 6:  bcd1130aa1 agent: advertise OS name via agent capability
    @@ Commit message
         maintains backward compatibility, avoids introducing a new capability,
         encourages adoption across Git-compatible software, and enhances
         debugging by providing complete environment information without affecting
    -    functionality.
    -
    -    Add the `transfer.advertiseOSInfo` config option to address privacy
    -    concerns. It defaults to `true` and can be changed to `false`.
    -    When `true`, both the client and server independently append their
    -    operating system name(os) to the `agent` capability value. The `agent`
    -    capability will now be in form of "package/version os" (e.g.,
    -    "git/1.8.3.1 Linux"). When `false`, the `agent` capability will be
    -    in the form of "package/version" e.g "git/1.8.3.1". The server's
    -    configuration is independent of the client's. Defaults to `true`.
    -    The operating system name is retrieved using the 'sysname' field of
    -    the `uname(2)` system call or its equivalent.
    +    functionality. The operating system name is retrieved using the 'sysname'
    +    field of the `uname(2)` system call or its equivalent.
     
         However, there are differences between `uname(1)` (command-line utility)
         and `uname(2)` (system call) outputs on Windows. These discrepancies
    @@ Commit message
         Mentored-by: Christian Couder <chriscool@tuxfamily.org>
         Signed-off-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
     
    - ## Documentation/config/transfer.txt ##
    -@@ Documentation/config/transfer.txt: transfer.bundleURI::
    - transfer.advertiseObjectInfo::
    - 	When `true`, the `object-info` capability is advertised by
    - 	servers. Defaults to false.
    -+
    -+transfer.advertiseOSInfo::
    -+	When `true`, both the client and server independently append their
    -+	operating system name (os) to the `agent` capability value. The `agent`
    -+	capability will now be in form of "package/version os" (e.g.,
    -+	"git/1.8.3.1 Linux"). When `false`, the `agent` capability will be
    -+	in the form of "package/version" e.g "git/1.8.3.1". The server's
    -+	configuration is independent of the client's. Defaults to `true`.
    -
      ## Documentation/gitprotocol-v2.txt ##
     @@ Documentation/gitprotocol-v2.txt: form `agent=X`) to notify the client that the server is running version
      the `agent` capability with a value `Y` (in the form `agent=Y`) in its
    @@ Documentation/gitprotocol-v2.txt: form `agent=X`) to notify the client that the
     -"git/1.8.3.1"). The agent strings are purely informative for statistics
     -and debugging purposes, and MUST NOT be used to programmatically assume
     -the presence or absence of particular features.
    -+printable ASCII characters (i.e., the byte range 32 < x < 127), and are
    ++printable ASCII characters (i.e., the byte range 31 < x < 127), and are
     +typically of the form "package/version os" (e.g., "git/1.8.3.1 Linux")
     +where `os` is the operating system name (e.g., "Linux"). `X` and `Y` can
     +be configured using the GIT_USER_AGENT environment variable and it takes
    -+priority. If `transfer.advertiseOSInfo` is `false` on the server, the server
    -+omits the `os` from X. If it is `false` on the client, the client omits the
    -+`os` from `Y`. The `os` is retrieved using the 'sysname' field of the `uname(2)`
    ++priority. The `os` is retrieved using the 'sysname' field of the `uname(2)`
     +system call or its equivalent. The agent strings are purely informative for
     +statistics and debugging purposes, and MUST NOT be used to programmatically
     +assume the presence or absence of particular features.
    @@ Documentation/gitprotocol-v2.txt: form `agent=X`) to notify the client that the
      ls-refs
      ~~~~~~~
     
    - ## t/t5555-http-smart-common.sh ##
    -@@ t/t5555-http-smart-common.sh: test_expect_success 'git receive-pack --advertise-refs: v1' '
    - '
    - 
    - test_expect_success 'git upload-pack --advertise-refs: v2' '
    -+	printf "agent=FAKE" >agent_capability &&
    -+	if test_have_prereq WINDOWS
    -+	then
    -+		printf "\n" >>agent_capability &&
    -+		git config transfer.advertiseOSInfo false
    -+	else
    -+		printf " %s\n" $(uname -s | test_redact_non_printables) >>agent_capability
    -+	fi &&
    - 	cat >expect <<-EOF &&
    - 	version 2
    --	agent=FAKE
    -+	$(cat agent_capability)
    - 	ls-refs=unborn
    - 	fetch=shallow wait-for-done
    - 	server-option
    -
      ## t/t5701-git-serve.sh ##
     @@ t/t5701-git-serve.sh: export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
      . ./test-lib.sh
    @@ t/t5701-git-serve.sh: export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
      
     +	if test_have_prereq WINDOWS
     +	then
    -+		printf "\n" >>agent_capability &&
    -+		git config transfer.advertiseOSInfo false
    ++		printf "agent=FAKE\n" >agent_capability
     +	else
     +		printf " %s\n" $(uname -s | test_redact_non_printables) >>agent_capability
     +	fi &&
      	cat >expect.base <<-EOF &&
      	version 2
      	$(cat agent_capability)
    +@@ t/t5701-git-serve.sh: test_expect_success 'setup to generate files with expected content' '
    + test_expect_success 'test capability advertisement' '
    + 	cat expect.base expect.trailer >expect &&
    + 
    ++	if test_have_prereq WINDOWS
    ++	then
    ++		GIT_USER_AGENT=FAKE && export GIT_USER_AGENT
    ++	fi &&
    + 	GIT_TEST_SIDEBAND_ALL=0 test-tool serve-v2 \
    + 		--advertise-capabilities >out &&
    + 	test-tool pkt-line unpack <out >actual &&
    +@@ t/t5701-git-serve.sh: test_expect_success 'test capability advertisement with uploadpack.advertiseBund
    + 	    expect.extra \
    + 	    expect.trailer >expect &&
    + 
    ++	if test_have_prereq WINDOWS
    ++	then
    ++		GIT_USER_AGENT=FAKE && export GIT_USER_AGENT
    ++	fi &&
    + 	GIT_TEST_SIDEBAND_ALL=0 test-tool serve-v2 \
    + 		--advertise-capabilities >out &&
    + 	test-tool pkt-line unpack <out >actual &&
     
      ## t/test-lib-functions.sh ##
     @@ t/test-lib-functions.sh: test_trailing_hash () {
    @@ version.c
      #include "version.h"
      #include "version-def.h"
      #include "strbuf.h"
    - #include "sane-ctype.h"
    +-#include "sane-ctype.h"
      #include "gettext.h"
    -+#include "config.h"
      
      const char git_version_string[] = GIT_VERSION;
    - const char git_built_from_commit_string[] = GIT_BUILT_FROM_COMMIT;
    -@@ version.c: const char *git_user_agent_sanitized(void)
    - 
    - 		strbuf_addstr(&buf, git_user_agent());
    - 		redact_non_printables(&buf);
    -+		/* Add os name if the transfer.advertiseosinfo config is true */
    -+		if (advertise_os_info()) {
    -+			/* Add space to space character after git version string */
    -+			strbuf_addch(&buf, ' ');
    -+			strbuf_addstr(&buf, os_info_sanitized());
    -+		}
    - 		agent = strbuf_detach(&buf, NULL);
    - 	}
    - 
    -@@ version.c: int get_uname_info(struct strbuf *buf, unsigned int full)
    - 	     strbuf_addf(buf, "%s\n", uname_info.sysname);
    - 	return 0;
    +@@ version.c: const char *git_user_agent(void)
    + 	return agent;
      }
    -+
    -+const char *os_info_sanitized(void)
    + 
    ++/*
    ++  Retrieve, sanitize and cache operating system info for subsequent
    ++  calls. Return a pointer to the sanitized operating system info
    ++  string.
    ++*/
    ++static const char *os_info(void)
     +{
     +	static const char *os = NULL;
     +
    @@ version.c: int get_uname_info(struct strbuf *buf, unsigned int full)
     +	return os;
     +}
     +
    -+int advertise_os_info(void)
    -+{
    -+	static int transfer_advertise_os_info= -1;
    + const char *git_user_agent_sanitized(void)
    + {
    + 	static const char *agent = NULL;
    +@@ version.c: const char *git_user_agent_sanitized(void)
    + 
    + 		strbuf_addstr(&buf, git_user_agent());
    + 		redact_non_printables(&buf);
     +
    -+	if (transfer_advertise_os_info == -1) {
    -+		repo_config_get_bool(the_repository, "transfer.advertiseosinfo", &transfer_advertise_os_info);
    -+		/* enabled by default */
    -+		transfer_advertise_os_info = !!transfer_advertise_os_info;
    -+	}
    -+	return transfer_advertise_os_info;
    -+}
    ++		if (!getenv("GIT_USER_AGENT")) {
    ++			strbuf_addch(&buf, ' ');
    ++			strbuf_addstr(&buf, os_info());
    ++		}
    + 		agent = strbuf_detach(&buf, NULL);
    + 	}
    + 
     
      ## version.h ##
     @@
    @@ version.h: const char *git_user_agent_sanitized(void);
      */
      int get_uname_info(struct strbuf *buf, unsigned int full);
      
    -+/*
    -+  Retrieve, sanitize and cache operating system info for subsequent
    -+  calls. Return a pointer to the sanitized operating system info
    -+  string.
    -+*/
    -+const char *os_info_sanitized(void);
    -+
    -+/*
    -+  Retrieve and cache transfer.advertiseosinfo config value. Return 1
    -+  if true, 0 if false.
    -+*/
    -+int advertise_os_info(void);
     +
      #endif /* VERSION_H */

-- 
2.48.1


  parent reply	other threads:[~2025-02-14 12:37 UTC|newest]

Thread overview: 107+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-01-06 10:30 [PATCH 0/4][Outreachy] Introduce os-version Capability with Configurable Options Usman Akinyemi
2025-01-06 10:30 ` [PATCH 1/4] version: refactor redact_non_printables() Usman Akinyemi
2025-01-06 22:35   ` Eric Sunshine
2025-01-08 12:58     ` Usman Akinyemi
2025-01-06 10:30 ` [PATCH 2/4] version: refactor get_uname_info() Usman Akinyemi
2025-01-06 16:04   ` Junio C Hamano
2025-01-08 13:06     ` Usman Akinyemi
2025-01-06 10:30 ` [PATCH 3/4] connect: advertise OS version Usman Akinyemi
2025-01-06 16:22   ` Junio C Hamano
2025-01-08 13:06     ` Usman Akinyemi
2025-01-08 16:15       ` Junio C Hamano
2025-01-09 14:25         ` Usman Akinyemi
2025-01-09 15:46           ` Junio C Hamano
2025-01-10 17:56             ` Usman Akinyemi
2025-01-10 19:24               ` Junio C Hamano
2025-01-11 11:07                 ` Usman Akinyemi
2025-01-13 15:46                   ` Junio C Hamano
2025-01-13 18:26                     ` Usman Akinyemi
2025-01-13 19:47                       ` Junio C Hamano
2025-01-13 20:07                         ` rsbecker
2025-01-06 23:17   ` Eric Sunshine
2025-01-08 13:14     ` Usman Akinyemi
2025-01-06 10:30 ` [PATCH 4/4] version: introduce osversion.command config for os-version output Usman Akinyemi
2025-01-17 10:46 ` [PATCH v2 0/6][Outreachy] Introduce os-version Capability with Configurable Options Usman Akinyemi
2025-01-17 10:46   ` [PATCH v2 1/6] version: refactor redact_non_printables() Usman Akinyemi
2025-01-17 18:26     ` Junio C Hamano
2025-01-17 19:48       ` Junio C Hamano
2025-01-20 17:10       ` Usman Akinyemi
2025-01-21  8:12         ` Christian Couder
2025-01-21 18:01           ` Junio C Hamano
2025-01-17 10:46   ` [PATCH v2 2/6] version: refactor get_uname_info() Usman Akinyemi
2025-01-17 10:46   ` [PATCH v2 3/6] version: extend get_uname_info() to hide system details Usman Akinyemi
2025-01-17 18:27     ` Junio C Hamano
2025-01-17 10:46   ` [PATCH v2 4/6] t5701: add setup test to remove side-effect dependency Usman Akinyemi
2025-01-17 19:31     ` Junio C Hamano
2025-01-20 17:32       ` Usman Akinyemi
2025-01-20 19:52         ` Junio C Hamano
2025-01-21 13:43           ` Usman Akinyemi
2025-01-17 10:46   ` [PATCH v2 5/6] connect: advertise OS version Usman Akinyemi
2025-01-17 19:35     ` Junio C Hamano
2025-01-17 22:22     ` Junio C Hamano
2025-01-17 22:47       ` rsbecker
2025-01-17 23:04         ` Junio C Hamano
2025-01-20 18:15       ` Usman Akinyemi
2025-01-21 19:06         ` Junio C Hamano
2025-01-17 10:46   ` [PATCH v2 6/6] version: introduce osversion.command config for os-version output Usman Akinyemi
2025-01-17 21:44     ` Eric Sunshine
2025-01-20 18:17       ` Usman Akinyemi
2025-01-20 18:41         ` Eric Sunshine
2025-01-20 19:08           ` Usman Akinyemi
2025-01-17 22:33     ` Junio C Hamano
2025-01-17 22:49       ` rsbecker
2025-01-17 23:06         ` Junio C Hamano
2025-01-17 23:18           ` rsbecker
2025-01-20 18:58       ` Usman Akinyemi
2025-01-21 19:14         ` Junio C Hamano
2025-01-21 19:51           ` rsbecker
2025-01-24 12:21   ` [PATCH v3 0/6][Outreachy] Introduce os-version Capability with Configurable Options Usman Akinyemi
2025-01-24 12:21     ` [PATCH v3 1/6] version: replace manual ASCII checks with isprint() for clarity Usman Akinyemi
2025-01-24 18:13       ` Junio C Hamano
2025-01-24 12:21     ` [PATCH v3 2/6] version: refactor redact_non_printables() Usman Akinyemi
2025-01-24 12:21     ` [PATCH v3 3/6] version: refactor get_uname_info() Usman Akinyemi
2025-01-24 12:21     ` [PATCH v3 4/6] version: extend get_uname_info() to hide system details Usman Akinyemi
2025-01-24 12:21     ` [PATCH v3 5/6] t5701: add setup test to remove side-effect dependency Usman Akinyemi
2025-01-24 18:12       ` Junio C Hamano
2025-01-24 12:21     ` [PATCH v3 6/6] connect: advertise OS version Usman Akinyemi
2025-02-05 18:52       ` [PATCH v4 0/6][Outreachy] extend agent capability to include OS name Usman Akinyemi
2025-02-05 18:52         ` [PATCH v4 1/6] version: replace manual ASCII checks with isprint() for clarity Usman Akinyemi
2025-02-05 18:52         ` [PATCH v4 2/6] version: refactor redact_non_printables() Usman Akinyemi
2025-02-05 18:52         ` [PATCH v4 3/6] version: refactor get_uname_info() Usman Akinyemi
2025-02-05 18:52         ` [PATCH v4 4/6] version: extend get_uname_info() to hide system details Usman Akinyemi
2025-02-05 18:52         ` [PATCH v4 5/6] t5701: add setup test to remove side-effect dependency Usman Akinyemi
2025-02-05 18:52         ` [PATCH v4 6/6] agent: advertise OS name via agent capability Usman Akinyemi
2025-02-05 21:48           ` Junio C Hamano
2025-02-06  6:37             ` Usman Akinyemi
2025-02-06 15:13               ` Junio C Hamano
2025-02-07 17:27                 ` Usman Akinyemi
2025-02-07 17:57                   ` Junio C Hamano
2025-02-07 19:25             ` Usman Akinyemi
2025-02-14 12:36         ` Usman Akinyemi [this message]
2025-02-14 12:36           ` [PATCH v5 1/6] version: replace manual ASCII checks with isprint() for clarity Usman Akinyemi
2025-02-14 12:36           ` [PATCH v5 2/6] version: refactor redact_non_printables() Usman Akinyemi
2025-02-14 12:36           ` [PATCH v5 3/6] version: refactor get_uname_info() Usman Akinyemi
2025-02-14 12:36           ` [PATCH v5 4/6] version: extend get_uname_info() to hide system details Usman Akinyemi
2025-02-14 12:36           ` [PATCH v5 5/6] t5701: add setup test to remove side-effect dependency Usman Akinyemi
2025-02-14 21:49             ` Junio C Hamano
2025-02-14 12:36           ` [PATCH v5 6/6] agent: advertise OS name via agent capability Usman Akinyemi
2025-02-14 22:07             ` Junio C Hamano
2025-02-15 15:29               ` Usman Akinyemi
2025-02-15 15:50           ` [PATCH v6 0/6][Outreachy] extend agent capability to include OS name Usman Akinyemi
2025-02-15 15:50             ` [PATCH v6 1/6] version: replace manual ASCII checks with isprint() for clarity Usman Akinyemi
2025-02-15 15:50             ` [PATCH v6 2/6] version: refactor redact_non_printables() Usman Akinyemi
2025-02-15 15:50             ` [PATCH v6 3/6] version: refactor get_uname_info() Usman Akinyemi
2025-02-15 15:50             ` [PATCH v6 4/6] version: extend get_uname_info() to hide system details Usman Akinyemi
2025-02-15 15:50             ` [PATCH v6 5/6] t5701: add setup test to remove side-effect dependency Usman Akinyemi
2025-02-15 15:50             ` [PATCH v6 6/6] agent: advertise OS name via agent capability Usman Akinyemi
2025-02-18 17:14               ` Junio C Hamano
2025-02-18 17:09             ` [PATCH v6 0/6][Outreachy] extend agent capability to include OS name Junio C Hamano
2025-01-24 18:39     ` [PATCH v3 0/6][Outreachy] Introduce os-version Capability with Configurable Options Junio C Hamano
2025-01-27 13:38       ` Christian Couder
2025-01-27 15:26         ` Junio C Hamano
2025-01-31 14:30           ` Christian Couder
2025-01-31 16:37             ` Junio C Hamano
2025-01-31 19:42               ` Usman Akinyemi
2025-01-31 20:15                 ` Junio C Hamano
2025-01-31 19:46               ` Usman Akinyemi
2025-01-31 20:17                 ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250214123734.1403120-1-usmanakinyemi202@gmail.com \
    --to=usmanakinyemi202@gmail.com \
    --cc=Johannes.Schindelin@gmx.de \
    --cc=christian.couder@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=johncai86@gmail.com \
    --cc=me@ttaylorr.com \
    --cc=phillip.wood@dunelm.org.uk \
    --cc=ps@pks.im \
    --cc=rsbecker@nexbridge.com \
    --cc=sunshine@sunshineco.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).