BUG/MINOR: config: crt-list keywords mistaken for bind ssl keywords

This patch fixes an issue in the "-dK" keywords dumper, which was
mistakenly displaying the "crt-list" keywords for "bind ssl" keywords.

The patch fixes the issue by dumping the "crt-list" keywords in its own
section, and dumping the "bind" keywords which are in the "SSL" scope
with a "bind ssl" prefix.

This commit depends on the previous "MINOR: ssl: rename confusing
ssl_bind_kws" commit.

Must be backported in 2.6.

Diff of the `./haproxy -dKall -q -c -f /dev/null` output before and
after the patch in 2.8-dev4:

     | @@ -190,30 +190,9 @@ listen
     |  	use-fcgi-app
     |  	bind <addr> accept-netscaler-cip +1
     |  	bind <addr> accept-proxy
     | -	bind <addr> allow-0rtt
     | -	bind <addr> alpn +1
     |  	bind <addr> backlog +1
     | -	bind <addr> ca-file +1
     | -	bind <addr> ca-ignore-err +1
     | -	bind <addr> ca-sign-file +1
     | -	bind <addr> ca-sign-pass +1
     | -	bind <addr> ca-verify-file +1
     | -	bind <addr> ciphers +1
     | -	bind <addr> ciphersuites +1
     | -	bind <addr> crl-file +1
     | -	bind <addr> crt +1
     | -	bind <addr> crt-ignore-err +1
     | -	bind <addr> crt-list +1
     | -	bind <addr> curves +1
     |  	bind <addr> defer-accept
     | -	bind <addr> ecdhe +1
     |  	bind <addr> expose-fd +1
     | -	bind <addr> force-sslv3
     | -	bind <addr> force-tlsv10
     | -	bind <addr> force-tlsv11
     | -	bind <addr> force-tlsv12
     | -	bind <addr> force-tlsv13
     | -	bind <addr> generate-certificates
     |  	bind <addr> gid +1
     |  	bind <addr> group +1
     |  	bind <addr> id +1
     | @@ -225,48 +204,52 @@ listen
     |  	bind <addr> name +1
     |  	bind <addr> namespace +1
     |  	bind <addr> nice +1
     | -	bind <addr> no-ca-names
     | -	bind <addr> no-sslv3
     | -	bind <addr> no-tls-tickets
     | -	bind <addr> no-tlsv10
     | -	bind <addr> no-tlsv11
     | -	bind <addr> no-tlsv12
     | -	bind <addr> no-tlsv13
     | -	bind <addr> npn +1
     | -	bind <addr> prefer-client-ciphers
     |  	bind <addr> process +1
     |  	bind <addr> proto +1
     |  	bind <addr> severity-output +1
     |  	bind <addr> shards +1
     | -	bind <addr> ssl
     | -	bind <addr> ssl-max-ver +1
     | -	bind <addr> ssl-min-ver +1
     | -	bind <addr> strict-sni
     |  	bind <addr> tcp-ut +1
     |  	bind <addr> tfo
     |  	bind <addr> thread +1
     | -	bind <addr> tls-ticket-keys +1
     |  	bind <addr> transparent
     |  	bind <addr> uid +1
     |  	bind <addr> user +1
     |  	bind <addr> v4v6
     |  	bind <addr> v6only
     | -	bind <addr> verify +1
     |  	bind <addr> ssl allow-0rtt
     |  	bind <addr> ssl alpn +1
     |  	bind <addr> ssl ca-file +1
     | +	bind <addr> ssl ca-ignore-err +1
     | +	bind <addr> ssl ca-sign-file +1
     | +	bind <addr> ssl ca-sign-pass +1
     |  	bind <addr> ssl ca-verify-file +1
     |  	bind <addr> ssl ciphers +1
     |  	bind <addr> ssl ciphersuites +1
     |  	bind <addr> ssl crl-file +1
     | +	bind <addr> ssl crt +1
     | +	bind <addr> ssl crt-ignore-err +1
     | +	bind <addr> ssl crt-list +1
     |  	bind <addr> ssl curves +1
     |  	bind <addr> ssl ecdhe +1
     | +	bind <addr> ssl force-sslv3
     | +	bind <addr> ssl force-tlsv10
     | +	bind <addr> ssl force-tlsv11
     | +	bind <addr> ssl force-tlsv12
     | +	bind <addr> ssl force-tlsv13
     | +	bind <addr> ssl generate-certificates
     |  	bind <addr> ssl no-ca-names
     | +	bind <addr> ssl no-sslv3
     | +	bind <addr> ssl no-tls-tickets
     | +	bind <addr> ssl no-tlsv10
     | +	bind <addr> ssl no-tlsv11
     | +	bind <addr> ssl no-tlsv12
     | +	bind <addr> ssl no-tlsv13
     |  	bind <addr> ssl npn +1
     | -	bind <addr> ssl ocsp-update +1
     | +	bind <addr> ssl prefer-client-ciphers
     |  	bind <addr> ssl ssl-max-ver +1
     |  	bind <addr> ssl ssl-min-ver +1
     | +	bind <addr> ssl strict-sni
     | +	bind <addr> ssl tls-ticket-keys +1
     |  	bind <addr> ssl verify +1
     |  	server <name> <addr> addr +1
     |  	server <name> <addr> agent-addr +1
     | @@ -591,6 +574,23 @@ listen
     |  	http-after-response unset-var*
     |  userlist
     |  peers
     | +crt-list
     | +	allow-0rtt
     | +	alpn +1
     | +	ca-file +1
     | +	ca-verify-file +1
     | +	ciphers +1
     | +	ciphersuites +1
     | +	crl-file +1
     | +	curves +1
     | +	ecdhe +1
     | +	no-ca-names
     | +	npn +1
     | +	ocsp-update +1
     | +	ssl-max-ver +1
     | +	ssl-min-ver +1
     | +	verify +1
     |  # List of registered CLI keywords:
     |  @!<pid> [MASTER]
     |  @<relative pid> [MASTER]
diff --git a/include/haproxy/cfgparse.h b/include/haproxy/cfgparse.h
index b569b4d..29937ff 100644
--- a/include/haproxy/cfgparse.h
+++ b/include/haproxy/cfgparse.h
@@ -35,6 +35,7 @@
 #define CFG_LISTEN	2
 #define CFG_USERLIST	3
 #define CFG_PEERS	4
+#define CFG_CRTLIST	5
 
 /* various keyword modifiers */
 enum kw_mod {
diff --git a/src/cfgparse.c b/src/cfgparse.c
index f404115..06ee980 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -4715,7 +4715,8 @@
 /* dumps all registered keywords by section on stdout */
 void cfg_dump_registered_keywords()
 {
-	const char* sect_names[] = { "", "global", "listen", "userlist", "peers", 0 };
+	/*                             CFG_GLOBAL, CFG_LISTEN, CFG_USERLIST, CFG_PEERS, CFG_CRTLIST */
+	const char* sect_names[] = { "", "global", "listen", "userlist", "peers", "crt-list", 0 };
 	int section;
 	int index;
 
@@ -4742,22 +4743,24 @@
 			extern struct list tcp_req_conn_keywords, tcp_req_sess_keywords,
 				tcp_req_cont_keywords, tcp_res_cont_keywords;
 			extern struct bind_kw_list bind_keywords;
-			extern struct ssl_crtlist_kw ssl_crtlist_kws[] __maybe_unused;
 			extern struct srv_kw_list srv_keywords;
 			struct bind_kw_list *bkwl;
 			struct srv_kw_list *skwl;
 			const struct bind_kw *bkwp, *bkwn;
 			const struct srv_kw *skwp, *skwn;
-			const struct ssl_crtlist_kw *sbkwp __maybe_unused, *sbkwn __maybe_unused;
 			const struct cfg_opt *coptp, *coptn;
 
+			/* display the non-ssl keywords */
 			for (bkwn = bkwp = NULL;; bkwp = bkwn) {
 				list_for_each_entry(bkwl, &bind_keywords.list, list) {
-					for (index = 0; bkwl->kw[index].kw != NULL; index++)
+					if (strcmp(bkwl->scope, "SSL") == 0) /* skip SSL keywords */
+						continue;
+					for (index = 0; bkwl->kw[index].kw != NULL; index++) {
 						if (strordered(bkwp ? bkwp->kw : NULL,
 							       bkwl->kw[index].kw,
 							       bkwn != bkwp ? bkwn->kw : NULL))
 							bkwn = &bkwl->kw[index];
+					}
 				}
 				if (bkwn == bkwp)
 					break;
@@ -4767,24 +4770,31 @@
 				else
 					printf("\tbind <addr> %s +%d\n", bkwn->kw, bkwn->skip);
 			}
-
 #if defined(USE_OPENSSL)
-			for (sbkwn = sbkwp = NULL;; sbkwp = sbkwn) {
-				for (index = 0; ssl_crtlist_kws[index].kw != NULL; index++) {
-					if (strordered(sbkwp ? sbkwp->kw : NULL,
-						       ssl_crtlist_kws[index].kw,
-						       sbkwn != sbkwp ? sbkwn->kw : NULL))
-						sbkwn = &ssl_crtlist_kws[index];
+			/* displays the "ssl" keywords */
+			for (bkwn = bkwp = NULL;; bkwp = bkwn) {
+				list_for_each_entry(bkwl, &bind_keywords.list, list) {
+					if (strcmp(bkwl->scope, "SSL") != 0) /* skip non-SSL keywords */
+						continue;
+					for (index = 0; bkwl->kw[index].kw != NULL; index++) {
+						if (strordered(bkwp ? bkwp->kw : NULL,
+						               bkwl->kw[index].kw,
+						               bkwn != bkwp ? bkwn->kw : NULL))
+							bkwn = &bkwl->kw[index];
+					}
 				}
-				if (sbkwn == sbkwp)
+				if (bkwn == bkwp)
 					break;
-				if (!sbkwn->skip)
-					printf("\tbind <addr> ssl %s\n", sbkwn->kw);
+
+				if (strcmp(bkwn->kw, "ssl") == 0) /* skip "bind <addr> ssl ssl" */
+					continue;
+
+				if (!bkwn->skip)
+					printf("\tbind <addr> ssl %s\n", bkwn->kw);
 				else
-					printf("\tbind <addr> ssl %s +%d\n", sbkwn->kw, sbkwn->skip);
+					printf("\tbind <addr> ssl %s +%d\n", bkwn->kw, bkwn->skip);
 			}
 #endif
-
 			for (skwn = skwp = NULL;; skwp = skwn) {
 				list_for_each_entry(skwl, &srv_keywords.list, list) {
 					for (index = 0; skwl->kw[index].kw != NULL; index++)
@@ -4835,6 +4845,29 @@
 			dump_act_rules(&http_res_keywords.list,       "\thttp-response ");
 			dump_act_rules(&http_after_res_keywords.list, "\thttp-after-response ");
 		}
+		if (section == CFG_CRTLIST) {
+			/* displays the keyword available for the crt-lists */
+			extern struct ssl_crtlist_kw ssl_crtlist_kws[] __maybe_unused;
+			const struct ssl_crtlist_kw *sbkwp __maybe_unused, *sbkwn __maybe_unused;
+
+#if defined(USE_OPENSSL)
+			for (sbkwn = sbkwp = NULL;; sbkwp = sbkwn) {
+				for (index = 0; ssl_crtlist_kws[index].kw != NULL; index++) {
+					if (strordered(sbkwp ? sbkwp->kw : NULL,
+						       ssl_crtlist_kws[index].kw,
+						       sbkwn != sbkwp ? sbkwn->kw : NULL))
+						sbkwn = &ssl_crtlist_kws[index];
+				}
+				if (sbkwn == sbkwp)
+					break;
+				if (!sbkwn->skip)
+					printf("\t%s\n", sbkwn->kw);
+				else
+					printf("\t%s +%d\n", sbkwn->kw, sbkwn->skip);
+			}
+#endif
+
+		}
 	}
 }