git: 5a2767d20325 - stable/14 - Fix multiple bugs with ctld's UCL parsing

From: Alan Somers <asomers_at_FreeBSD.org>
Date: Sat, 20 Jan 2024 01:53:31 UTC
The branch stable/14 has been updated by asomers:

URL: https://cgit.FreeBSD.org/src/commit/?id=5a2767d20325d5065ae4bc04d954530150551016

commit 5a2767d20325d5065ae4bc04d954530150551016
Author:     Alan Somers <asomers@FreeBSD.org>
AuthorDate: 2023-10-09 18:26:25 +0000
Commit:     Alan Somers <asomers@FreeBSD.org>
CommitDate: 2024-01-20 01:52:38 +0000

    Fix multiple bugs with ctld's UCL parsing
    
    * Don't segfault when parsing a misformatted auth-group section
    * If the config file specifies a chap section within a target but no
      auth-group, create a new anonymous auth-group.  That matches the
      behavior with non-UCL config files.
    * Protect some potential segfaults with assertions
    
    PR:             274380
    Sponsored by:   Axcient
    Reviewed by:    jhb
    Differential Revision: https://reviews.freebsd.org/D43198
    
    (cherry picked from commit 2391e536c01cb51d2a2c11a0f5820481314e9ec2)
---
 usr.sbin/ctld/ctld.c     |  1 +
 usr.sbin/ctld/uclparse.c | 26 ++++++++++++++++++++++++--
 2 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/usr.sbin/ctld/ctld.c b/usr.sbin/ctld/ctld.c
index 2a69308ff067..f2b2de5b9a57 100644
--- a/usr.sbin/ctld/ctld.c
+++ b/usr.sbin/ctld/ctld.c
@@ -533,6 +533,7 @@ auth_group_find(const struct conf *conf, const char *name)
 {
 	struct auth_group *ag;
 
+	assert(name != NULL);
 	TAILQ_FOREACH(ag, &conf->conf_auth_groups, ag_next) {
 		if (ag->ag_name != NULL && strcmp(ag->ag_name, name) == 0)
 			return (ag);
diff --git a/usr.sbin/ctld/uclparse.c b/usr.sbin/ctld/uclparse.c
index f3f8df81e492..8bd1ca88d166 100644
--- a/usr.sbin/ctld/uclparse.c
+++ b/usr.sbin/ctld/uclparse.c
@@ -60,6 +60,7 @@ uclparse_chap(struct auth_group *auth_group, const ucl_object_t *obj)
 	const struct auth *ca;
 	const ucl_object_t *user, *secret;
 
+	assert(auth_group != NULL);
 	user = ucl_object_find_key(obj, "user");
 	if (!user || user->type != UCL_STRING) {
 		log_warnx("chap section in auth-group \"%s\" is missing "
@@ -90,6 +91,7 @@ uclparse_chap_mutual(struct auth_group *auth_group, const ucl_object_t *obj)
 	const ucl_object_t *user, *secret, *mutual_user;
 	const ucl_object_t *mutual_secret;
 
+	assert(auth_group != NULL);
 	user = ucl_object_find_key(obj, "user");
 	if (!user || user->type != UCL_STRING) {
 		log_warnx("chap-mutual section in auth-group \"%s\" is missing "
@@ -714,6 +716,8 @@ uclparse_target(const char *name, const ucl_object_t *top)
 		}
 
 		if (!strcmp(key, "auth-group")) {
+			const char *ag;
+
 			if (target->t_auth_group != NULL) {
 				if (target->t_auth_group->ag_name != NULL)
 					log_warnx("auth-group for target \"%s\" "
@@ -725,8 +729,12 @@ uclparse_target(const char *name, const ucl_object_t *top)
 					    "target \"%s\"", target->t_name);
 				return (1);
 			}
-			target->t_auth_group = auth_group_find(conf,
-			    ucl_object_tostring(obj));
+			ag = ucl_object_tostring(obj);
+			if (!ag) {
+				log_warnx("auth-group must be a string");
+				return (1);
+			}
+			target->t_auth_group = auth_group_find(conf, ag);
 			if (target->t_auth_group == NULL) {
 				log_warnx("unknown auth-group \"%s\" for target "
 				    "\"%s\"", ucl_object_tostring(obj),
@@ -759,6 +767,20 @@ uclparse_target(const char *name, const ucl_object_t *top)
 		}
 
 		if (!strcmp(key, "chap")) {
+			if (target->t_auth_group != NULL) {
+				if (target->t_auth_group->ag_name != NULL) {
+					log_warnx("cannot use both auth-group "
+					    "and chap for target \"%s\"",
+					    target->t_name);
+					return (1);
+				}
+			} else {
+				target->t_auth_group = auth_group_new(conf, NULL);
+				if (target->t_auth_group == NULL) {
+					return (1);
+				}
+				target->t_auth_group->ag_target = target;
+			}
 			if (uclparse_chap(target->t_auth_group, obj) != 0)
 				return (1);
 		}