tech-pkg archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Cert validation in pkg_add



Take 3:

- For http/ftp URL of a package on command-line, or of package
  repository in semicolon-separated PKG_PATH entry, no change.

- When pkg_add fetches via https URL of package on command-line, or of
  package repository in PKG_PATH, it requires secure transport --
  i.e., requires valid TLS certs and refuses redirect to http/ftp.

- Same deal with pkg_admin audit and PKGVULNURL.

(Change from previous: The rule applies to each semicolon-separated
entry in PKG_PATH, and to the command line, not just to the first
entry in PKG_PATH.)

I also added a build-time conditional on NetBSD>=10 so that this
doesn't affect any other platforms for now -- we can easily remove
that after the 2023Q4 branch.


> Date: Sat, 9 Dec 2023 16:29:46 +0000
> From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
> 
> New proposal:
> 
> - If you set PKG_PATH=ftp://... or http://..., no change to pkg_add.
> 
>   So existing use cases of _explicitly requested_ FTP or HTTP for a
>   package repository continue to work.
> 
> - If you set PKG_PATH=https://... (or file://..., though it doesn't
>   matter here), pkg_add requires secure transport, i.e., requires
>   valid TLS certs and refuses redirect to http/ftp.
> 
>   So https does what it says on the box.  But you can restore the
>   previous non-validating bug by setting INSECURE_TRANSPORT=1.
> 
> (Same applies to PKGVULNURL and pkg_admin audit in new patch.  This
> covers all cases of calls to libfetch in pkg_install.  Will update
> pkgin patch to work similarly.)
> 
> The cases this will break are:
> 1. self-signed certs (solution: Let's Encrypt or custom trust anchors)
> 2. intentional redirect from authenticated https to http/ftp
> 3. asking for https:// on systems without trust anchors
> I think these cases are obscure and not worth worrying about, and if
> you really need them to work you can set INSECURE_TRANSPORT=1.
> 
> Better?
> 
> 
> Some small points below:
> 
> > Date: Sat, 09 Dec 2023 07:34:12 -0500
> > From: Greg Troxel <gdt%lexort.com@localhost>
> > 
> > Taylor R Campbell <riastradh%NetBSD.org@localhost> writes:
> > 
> > > 1. New libfetch flag `V' to enable validation.
> > >
> > >    This is an opt-in so that existing clients of the _library_ don't
> > >    break -- no change to library semantics.
> > 
> > opt-in seems fine.  But it looks like the patch changes the signature of
> > an existing public function, so I'd expect this requires a shlib major
> > bump of libfetch, and accomodation in all users, and I don't understand
> > either how that's being done or why it isn't necessary.
> 
> This isn't a public function -- it's an internal function that is used
> between different .c files inside libfetch.  It may be accidentally
> exported by the .so because nobody has gotten around to sprinkling
> visibility attributes.  But it's not declared in any public header
> file so if any applications are linked against it, they get what they
> deserve.
> 
> As a side note, this function has already diverged between NetBSD base
> and pkgsrc -- it has an extra argument in pkgsrc to pass through the
> URL (although I don't think that's necessary since it's available
> through conn->cache_url).
> 
> > > We could, of course, apply the changes to NetBSD first, and then
> > > pkgsrc, rather than the other way around, if pkgsrc-releng considers
> > > this change too risky for pkgsrc so close to branch-time.
> > 
> > How are you proposing to deal with this for systems that do and don't
> > have trust anchors configured?  I get it that on NetBSD 10, trust
> > anchors are configured in base.  But on older NetBSD -- and who knows
> > about the other ~20 platforms, it's hard to tell.
> 
> 1. Use PKG_PATH=http:// or ftp:// instead.
> 2. Install trust anchors.
> 3. Set INSECURE_TRANSPORT=1 in pkg_install.conf.
> 
> It's a severe bug, meaning a mismatch between reasonable expectations
> and actual implementation leading to user astonishment of exploitable
> security flaws, for pkg_add to quietly accept https:// URLs without
> any cert validation.
> 
> And for _automation_ to rely on that is worse.  So it's _good_ if this
> has the effect of requiring manual intervention for systems where you
> _thought_ you were getting the security of https but were not.
> 
> > (A nit but stability heading to branch is pkgsrc-pmc.  Acceptability of
> > pullups is pkgsrc-releng, in theory with pmc oversight, but I have no
> > memory of *ever* needing to discuss a decision that was made my
> > pkgsrc-releng.)
> 
> Oops, yes, that's what I meant.
> 
> > I don't think it's wise to have different code in NetBSD base
> > pkg_install and in pkgsrc pkg_install, as that will cause behavior
> > changes when flipping between them, which could happen due to unrelated
> > fixes in pkg_install.
> 
> Yes, I guess it would be bad if upgrading pkg_install from pkgsrc had
> the effect of downgrading security, so let's not do that.
> 
> > My quick reaction is that the default to validate TLS is easy to revert
> > if trouble.  When guarded by an ifdef on NetBSD 10, then it addresses
> > what I think you most care about, while not impacting the rest of the
> > systems where we don't have a good handle on the impacts.
> 
> That seems fine to me as a band-aid that we rip off next branch.  Can
> put some #if NetBSD 10 conditionals in the next round of the patch.
> 
> > Not quite on topic, but related to why this is perceived as urgent: I'm
> > not really clear on why we don't have  signed packages.  I see it as
> > "key management is hard" and we don't have a story for supercession and
> > revocation, distribution of trust anchors, etc., for the keys used or
> > signing.
> 
> That is accurate.  Also the package signing system we have has design
> flaws that weaken its security properties (DoS, selective rollback)
> and make key management harder (no thresholds so migration is harder).
> 
> I have some draft work in progress to address all of this but my tuit
> supply is low so I'm prioritizing low-hanging fruit first.
From 217a0b07cc4a7b362fd0d44fd2be429e9a012a68 Mon Sep 17 00:00:00 2001
From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
Date: Sat, 9 Dec 2023 03:39:31 +0000
Subject: [PATCH 1/2] net/libfetch: update to 2.40

New flag `V' to require verification of transport.  This blocks HTTPS
without a valid certificate, and blocks HTTP and FTP.

No change to semantics for existing clients of libfetch.
---
 net/libfetch/Makefile       |  3 +--
 net/libfetch/files/common.c |  6 +++++-
 net/libfetch/files/common.h |  2 +-
 net/libfetch/files/fetch.3  | 10 +++++++++-
 net/libfetch/files/ftp.c    | 11 ++++++++++-
 net/libfetch/files/http.c   | 13 +++++++++++--
 6 files changed, 37 insertions(+), 8 deletions(-)

diff --git a/net/libfetch/Makefile b/net/libfetch/Makefile
index e5cea0f4b830..66d034e66a9c 100644
--- a/net/libfetch/Makefile
+++ b/net/libfetch/Makefile
@@ -1,7 +1,6 @@
 # $NetBSD: Makefile,v 1.64 2023/10/24 22:10:22 wiz Exp $
 
-DISTNAME=	libfetch-2.39
-PKGREVISION=	2
+DISTNAME=	libfetch-2.40
 CATEGORIES=	net
 MASTER_SITES=	# empty
 DISTFILES=	# empty
diff --git a/net/libfetch/files/common.c b/net/libfetch/files/common.c
index c1e158711636..507e2ee81404 100644
--- a/net/libfetch/files/common.c
+++ b/net/libfetch/files/common.c
@@ -436,7 +436,7 @@ fetch_cache_put(conn_t *conn, int (*closecb)(conn_t *))
  * Enable SSL on a connection.
  */
 int
-fetch_ssl(conn_t *conn, const struct url *URL, int verbose)
+fetch_ssl(conn_t *conn, const struct url *URL, int verbose, int verify)
 {
 
 #ifdef WITH_SSL
@@ -451,6 +451,10 @@ fetch_ssl(conn_t *conn, const struct url *URL, int verbose)
 	conn->ssl_meth = SSLv23_client_method();
 	conn->ssl_ctx = SSL_CTX_new(conn->ssl_meth);
 	SSL_CTX_set_mode(conn->ssl_ctx, SSL_MODE_AUTO_RETRY);
+	if (verify) {
+		SSL_CTX_set_default_verify_paths(conn->ssl_ctx);
+		SSL_CTX_set_verify(conn->ssl_ctx, SSL_VERIFY_PEER, NULL);
+	}
 
 	conn->ssl = SSL_new(conn->ssl_ctx);
 	if (conn->ssl == NULL){
diff --git a/net/libfetch/files/common.h b/net/libfetch/files/common.h
index 9a07e3560c8e..43c92e1f2061 100644
--- a/net/libfetch/files/common.h
+++ b/net/libfetch/files/common.h
@@ -106,7 +106,7 @@ conn_t		*fetch_cache_get(const struct url *, int);
 void		 fetch_cache_put(conn_t *, int (*)(conn_t *));
 conn_t		*fetch_connect(struct url *, int, int);
 conn_t		*fetch_reopen(int);
-int		 fetch_ssl(conn_t *, const struct url *, int);
+int		 fetch_ssl(conn_t *, const struct url *, int, int);
 ssize_t		 fetch_read(conn_t *, char *, size_t);
 int		 fetch_getln(conn_t *);
 ssize_t		 fetch_write(conn_t *, const void *, size_t);
diff --git a/net/libfetch/files/fetch.3 b/net/libfetch/files/fetch.3
index bb58071dd088..35e214d223bf 100644
--- a/net/libfetch/files/fetch.3
+++ b/net/libfetch/files/fetch.3
@@ -27,7 +27,7 @@
 .\" $FreeBSD: fetch.3,v 1.64 2007/12/18 11:03:26 des Exp $
 .\" $NetBSD: fetch.3,v 1.17 2016/05/31 18:02:36 abhinav Exp $
 .\"
-.Dd January 22, 2010
+.Dd December 8, 2023
 .Dt FETCH 3
 .Os
 .Sh NAME
@@ -357,6 +357,14 @@ functions is read-only, and that a stream returned by one of the
 functions is write-only.
 .Sh PROTOCOL INDEPENDENT FLAGS
 If the
+.Ql V
+(verify) flag is specified, the library will refuse to fetch from URLs
+that can't be cryptographically verified.
+This limits
+.Nm
+to HTTPS URLs fetched from servers with valid certificates.
+.Pp
+If the
 .Ql i
 (if-modified-since) flag is specified, the library will try to fetch
 the content only if it is newer than
diff --git a/net/libfetch/files/ftp.c b/net/libfetch/files/ftp.c
index 8f3d576526d6..099b4a6826bd 100644
--- a/net/libfetch/files/ftp.c
+++ b/net/libfetch/files/ftp.c
@@ -1034,7 +1034,7 @@ static conn_t *
 ftp_connect(struct url *url, struct url *purl, const char *flags)
 {
 	conn_t *conn;
-	int e, direct, verbose;
+	int e, direct, verbose, verify;
 #ifdef INET6
 	int af = AF_UNSPEC;
 #else
@@ -1043,11 +1043,20 @@ ftp_connect(struct url *url, struct url *purl, const char *flags)
 
 	direct = CHECK_FLAG('d');
 	verbose = CHECK_FLAG('v');
+	verify = CHECK_FLAG('V');
 	if (CHECK_FLAG('4'))
 		af = AF_INET;
 	else if (CHECK_FLAG('6'))
 		af = AF_INET6;
 
+	if (verify) {
+		/* can't verify FTP */
+		fetchLastErrCode = FETCH_AUTH;
+		snprintf(fetchLastErrString, MAXERRSTRING,
+		    "unable to authenticate %s:// URLs", url->scheme);
+		return (NULL);
+	}
+
 	if (direct)
 		purl = NULL;
 
diff --git a/net/libfetch/files/http.c b/net/libfetch/files/http.c
index c2133dbd38f6..e562056f18e7 100644
--- a/net/libfetch/files/http.c
+++ b/net/libfetch/files/http.c
@@ -723,7 +723,7 @@ http_connect(struct url *URL, struct url *purl, const char *flags, int *cached)
 	conn_t *conn;
 	hdr_t h;
 	const char *p;
-	int af, verbose;
+	int af, verbose, verify;
 #if defined(TCP_NOPUSH) && !defined(__APPLE__)
 	int val;
 #endif
@@ -737,6 +737,7 @@ http_connect(struct url *URL, struct url *purl, const char *flags, int *cached)
 #endif
 
 	verbose = CHECK_FLAG('v');
+	verify = CHECK_FLAG('V');
 	if (CHECK_FLAG('4'))
 		af = AF_INET;
 #ifdef INET6
@@ -746,6 +747,14 @@ http_connect(struct url *URL, struct url *purl, const char *flags, int *cached)
 
 	curl = (purl != NULL) ? purl : URL;
 
+	if (verify && strcasecmp(URL->scheme, SCHEME_HTTPS) != 0) {
+		/* can't verify non-HTTPS */
+		fetchLastErrCode = FETCH_AUTH;
+		snprintf(fetchLastErrString, MAXERRSTRING,
+		    "unable to authenticate %s:// URLs", URL->scheme);
+		return (NULL);
+	}
+
 	if ((conn = fetch_cache_get(URL, af)) != NULL) {
 		*cached = 1;
 		return (conn);
@@ -783,7 +792,7 @@ http_connect(struct url *URL, struct url *purl, const char *flags, int *cached)
 		} while (h < hdr_end);
 	}
 	if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0 &&
-	    fetch_ssl(conn, URL, verbose) == -1) {
+	    fetch_ssl(conn, URL, verbose, verify) == -1) {
 		/* grrr */
 #ifdef EAUTH
 		errno = EAUTH;

From e6520a55c995521e4f2fdf6b61f472247054b1aa Mon Sep 17 00:00:00 2001
From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
Date: Sat, 9 Dec 2023 03:43:14 +0000
Subject: [PATCH 2/2] pkg_install: update to 20231208

If you use PKG_PATH=https://..., or you pass an https://... URL on
the command line to identify a package, require secure transport by
default when downloading packages (i.e., validate certs and refuse
redirect to ftp/http) unless you set the new pkg_install.conf option
INSECURE_TRANSPORT=1.  Same with PKGVULNURL and downloading
pkg-vulnerabilities.

If you use PKG_PATH=http://... or ftp://..., or same for PKGVULNURL,
no change.  (This applies to each entry in the semicolon-separated
PKG_PATH list independently: if you use `http://foo;https://bar',
then validation is only applied to https://bar.)
---
 pkgtools/pkg_install/Makefile                 |  1 -
 pkgtools/pkg_install/files/admin/audit.c      | 15 ++++++++++-
 pkgtools/pkg_install/files/lib/lib.h          |  1 +
 pkgtools/pkg_install/files/lib/parse-config.c | 18 ++++++++++++-
 .../files/lib/pkg_install.conf.5.in           |  9 +++++++
 pkgtools/pkg_install/files/lib/pkg_io.c       | 26 ++++++++++++++++---
 pkgtools/pkg_install/files/lib/version.h      |  2 +-
 7 files changed, 65 insertions(+), 7 deletions(-)

diff --git a/pkgtools/pkg_install/Makefile b/pkgtools/pkg_install/Makefile
index 1a2b975bf37f..2d6812433c29 100644
--- a/pkgtools/pkg_install/Makefile
+++ b/pkgtools/pkg_install/Makefile
@@ -7,7 +7,6 @@
 # change in the pkg_* tools that pkgsrc relies on for proper operation.
 
 PKGNAME=		pkg_install-${VERSION}
-PKGREVISION=		1
 CATEGORIES=		pkgtools
 
 MAINTAINER=		agc%NetBSD.org@localhost
diff --git a/pkgtools/pkg_install/files/admin/audit.c b/pkgtools/pkg_install/files/admin/audit.c
index a3b445ef5703..333b782b9f41 100644
--- a/pkgtools/pkg_install/files/admin/audit.c
+++ b/pkgtools/pkg_install/files/admin/audit.c
@@ -318,12 +318,25 @@ fetch_pkg_vulnerabilities(int argc, char **argv)
 		    fetchLastErrString);
 
 	flags = fetch_flags;
+
+	/*
+	 * If the user specified PKGVULNURL=http://... or ftp://... (or
+	 * if that is the default), enable insecure transport to
+	 * download it -- this way we don't break existing setups that
+	 * never expected secure transport in the first place.
+	 *
+	 * If you want secure transport, use https or file URLs.
+	 */
+	if (strcasecmp(url->scheme, SCHEME_HTTP) == 0 ||
+	    strcasecmp(url->scheme, SCHEME_FTP))
+		flags = insecure_fetch_flags;
+
 	if (update_pkg_vuln) {
 		fd = open(pkg_vulnerabilities_file, O_RDONLY);
 		if (fd != -1 && fstat(fd, &sb) != -1) {
 			url->last_modified = sb.st_mtime;
 			snprintf(my_flags, sizeof(my_flags), "%si",
-			    fetch_flags);
+			    flags);
 			flags = my_flags;
 		} else
 			update_pkg_vuln = 0;
diff --git a/pkgtools/pkg_install/files/lib/lib.h b/pkgtools/pkg_install/files/lib/lib.h
index 6a825d4b5834..b55dd6d258bb 100644
--- a/pkgtools/pkg_install/files/lib/lib.h
+++ b/pkgtools/pkg_install/files/lib/lib.h
@@ -461,6 +461,7 @@ extern const char *gpg_keyring_sign;
 extern const char *gpg_keyring_verify;
 extern const char *gpg_sign_as;
 extern char fetch_flags[];
+extern char insecure_fetch_flags[];
 
 extern const char *pkg_vulnerabilities_dir;
 extern const char *pkg_vulnerabilities_file;
diff --git a/pkgtools/pkg_install/files/lib/parse-config.c b/pkgtools/pkg_install/files/lib/parse-config.c
index 107466a1b4ca..7900cc422a1f 100644
--- a/pkgtools/pkg_install/files/lib/parse-config.c
+++ b/pkgtools/pkg_install/files/lib/parse-config.c
@@ -58,6 +58,7 @@ static int cache_connections_host = 4;
 const char     *config_file = SYSCONFDIR"/pkg_install.conf";
 
 char fetch_flags[10] = ""; /* Workaround Mac OS X linker issues with BSS */
+char insecure_fetch_flags[10] = "";
 static const char *active_ftp;
 static const char *verbose_netio;
 static const char *ignore_proxy;
@@ -84,6 +85,7 @@ const char *pkg_vulnerabilities_dir;
 const char *pkg_vulnerabilities_file;
 const char *pkg_vulnerabilities_url;
 const char *ignore_advisories = NULL;
+const char *insecure_transport = NULL;
 const char tnf_vulnerability_base[] = "http://cdn.NetBSD.org/pub/NetBSD/packages/vulns";;
 const char *acceptable_licenses = NULL;
 
@@ -111,6 +113,7 @@ static struct config_variable {
 	{ "GPG_SIGN_AS", &gpg_sign_as },
 	{ "IGNORE_PROXY", &ignore_proxy },
 	{ "IGNORE_URL", &ignore_advisories },
+	{ "INSECURE_TRANSPORT", &insecure_transport },
 	{ "PKG_DBDIR", &config_pkg_dbdir },
 	{ "PKG_PATH", &config_pkg_path },
 	{ "PKG_REFCOUNT_DBDIR", &config_pkg_refcount_dbdir },
@@ -244,11 +247,24 @@ pkg_install_config(void)
 	fetchConnectionCacheInit(cache_connections, cache_connections_host);
 #endif
 
-	snprintf(fetch_flags, sizeof(fetch_flags), "%s%s%s%s",
+	snprintf(insecure_fetch_flags, sizeof(insecure_fetch_flags),
+	    "%s%s%s%s",
 	    (do_cache_index) ? "c" : "",
 	    (verbose_netio && *verbose_netio) ? "v" : "",
 	    (active_ftp && *active_ftp) ? "a" : "",
 	    (ignore_proxy && *ignore_proxy) ? "d" : "");
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 1000000000
+	snprintf(fetch_flags, sizeof(fetch_flags), "%s%s",
+	    insecure_fetch_flags,
+	    (insecure_transport && *insecure_transport) ? "" : "V");
+#else
+	/*
+	 * Provisional until after pkgsrc-2023Q4 is branched -- don't
+	 * require secure transports by default except on NetBSD 10.
+	 */
+	snprintf(fetch_flags, sizeof(fetch_flags), "%s",
+	    insecure_fetch_flags);
+#endif
 }
 
 void
diff --git a/pkgtools/pkg_install/files/lib/pkg_install.conf.5.in b/pkgtools/pkg_install/files/lib/pkg_install.conf.5.in
index fb9d2cb70fde..ff74f0d03379 100644
--- a/pkgtools/pkg_install/files/lib/pkg_install.conf.5.in
+++ b/pkgtools/pkg_install/files/lib/pkg_install.conf.5.in
@@ -159,6 +159,15 @@ One line per advisory which should be ignored when running
 The URL from the
 .Pa pkg-vulnerabilities
 file should be used as value.
+.It Dv INSECURE_TRANSPORT
+Allow downloads over insecure transport, bypassing certificate
+validation, even if
+.Dv PKG_PATH
+or
+.Dv PKGVULNURL
+is set to an
+.Ql https://
+URL.
 .It Dv PKG_DBDIR (*)
 Location of the packages database.
 This option is always overriden by the argument of the
diff --git a/pkgtools/pkg_install/files/lib/pkg_io.c b/pkgtools/pkg_install/files/lib/pkg_io.c
index e961e8147420..4ac83a5b8ada 100644
--- a/pkgtools/pkg_install/files/lib/pkg_io.c
+++ b/pkgtools/pkg_install/files/lib/pkg_io.c
@@ -65,6 +65,26 @@ struct pkg_path {
 static char *orig_cwd, *last_toplevel;
 static TAILQ_HEAD(, pkg_path) pkg_path = TAILQ_HEAD_INITIALIZER(pkg_path);
 
+static const char *
+pkg_fetch_flags(const struct url *url)
+{
+
+	/*
+	 * If the user specified PKG_PATH=http://... or ftp://..., or
+	 * passed an http/ftp URL on the command line of a package to
+	 * install, enable insecure transport to download it -- this
+	 * way we don't break existing setups that never expected
+	 * secure transport in the first place.
+	 *
+	 * If you want secure transport, use https or file URLs.
+	 */
+	if (strcasecmp(url->scheme, SCHEME_HTTP) == 0 ||
+	    strcasecmp(url->scheme, SCHEME_FTP) == 0)
+		return insecure_fetch_flags;
+
+	return fetch_flags;
+}
+
 #ifndef BOOTSTRAP
 struct fetch_archive {
 	struct url *url;
@@ -80,7 +100,7 @@ fetch_archive_open(struct archive *a, void *client_data)
 	struct fetch_archive *f = client_data;
 	struct url_stat us;
 
-	f->fetch = fetchXGet(f->url, &us, fetch_flags);
+	f->fetch = fetchXGet(f->url, &us, pkg_fetch_flags(f->url));
 	if (f->fetch == NULL)
 		return ENOENT;
 	f->size = us.size;
@@ -118,7 +138,7 @@ fetch_archive_read(struct archive *a, void *client_data,
 		free(url);
 	}
 	fetchIO_close(f->fetch);
-	f->fetch = fetchXGet(f->url, &us, fetch_flags);
+	f->fetch = fetchXGet(f->url, &us, pkg_fetch_flags(f->url));
 	if (f->fetch == NULL)
 		return -1;
 	if (us.size != f->size)
@@ -255,7 +275,7 @@ find_best_package_int(struct url *url, const char *pattern,
 	url_pattern = xasprintf("%*.*s*", (int)i, (int)i, pattern);
 
 	fetchInitURLList(&ue);
-	if (fetchList(&ue, url, url_pattern, fetch_flags)) {
+	if (fetchList(&ue, url, url_pattern, pkg_fetch_flags(url))) {
 		char *base_url;
 		base_url = fetchStringifyURL(url);
 		warnx("Can't process %s/%s: %s", base_url, url_pattern,
diff --git a/pkgtools/pkg_install/files/lib/version.h b/pkgtools/pkg_install/files/lib/version.h
index 9bd3ab0a0def..c445d83d26c6 100644
--- a/pkgtools/pkg_install/files/lib/version.h
+++ b/pkgtools/pkg_install/files/lib/version.h
@@ -27,6 +27,6 @@
 #ifndef _INST_LIB_VERSION_H_
 #define _INST_LIB_VERSION_H_
 
-#define PKGTOOLS_VERSION 20211115
+#define PKGTOOLS_VERSION 20231208
 
 #endif /* _INST_LIB_VERSION_H_ */


Home | Main Index | Thread Index | Old Index