From patchwork Sun Jun 3 12:09:56 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: koen.cj.dergent@gmail.com X-Patchwork-Id: 924714 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=lists.openwrt.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="qUAe9Abh"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40zH2s1t4qz9s0x for ; Sun, 3 Jun 2018 22:10:44 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:Subject:Message-Id: Date:To:From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: List-Owner; bh=sLIgIyz+bgLxKWXZ/KkWCYQpxvMb4nGJHa/B26/ySjE=; b=qUAe9AbhDQUhnc xl/xOT7uXuQkAE9aVBYWZr2aTuoGiRd5D0iuCCnwmUloysHR2eD9riZrelwGIgkYkMaMbsdpG05dC wrfPXQcS33PJUoDAiSm1w7kTw8hUJBH3fc5AhQZvk/yeEqqCau1hhlgjP5fq11flQBaIYRcmqHcpi zpVadXQ6FA1SjJwXQwJGkcbXH0SSJ3zto5ZpqDRFWiOhoFyCDi6JFicDjtIGXyhCLmbwVDbh1wCmL KJ1Fa2WQjy95E8v8GS67JWp4Fdka0tN1x8If97OVuILkJG3dpTm2fyKwmT2uV4c3vCIBqXKgmrZNZ roc4ZPHrVzGY6jD8KKmA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1fPRq2-0001VD-4w; Sun, 03 Jun 2018 12:10:22 +0000 Received: from baptiste.telenet-ops.be ([2a02:1800:120:4::f00:13]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1fPRpx-000095-2s for openwrt-devel@lists.openwrt.org; Sun, 03 Jun 2018 12:10:19 +0000 Received: from localhost.localdomain ([94.227.20.125]) by baptiste.telenet-ops.be with bizsmtp id uC9z1x00Q2hvNUm01C9zsb; Sun, 03 Jun 2018 14:09:59 +0200 From: koen.cj.dergent@gmail.com To: openwrt-devel@lists.openwrt.org Date: Sun, 3 Jun 2018 14:09:56 +0200 Message-Id: <20180603120956.3033-1-koen.cj.dergent@gmail.com> X-Mailer: git-send-email 2.17.1 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20180603_051017_281477_F88BF6C9 X-CRM114-Status: GOOD ( 11.85 ) X-Spam-Score: 1.5 (+) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (1.5 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [2a02:1800:120:4:0:0:f00:13 listed in] [list.dnswl.org] 0.0 DKIM_ADSP_CUSTOM_MED No valid author signature, adsp_override is CUSTOM_MED 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (koen.cj.dergent[at]gmail.com) 1.0 SPF_SOFTFAIL SPF: sender does not match SPF record (softfail) 1.2 NML_ADSP_CUSTOM_MED ADSP custom_med hit, and not from a mailing list Subject: [OpenWrt-Devel] [PATCH] ubus: fully allow wildcards in acl X-BeenThere: openwrt-devel@lists.openwrt.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Koen Dergent MIME-Version: 1.0 Sender: "openwrt-devel" Errors-To: openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org From: Koen Dergent Wildcards were supported in the ACL code, but they did not work properly. The compare function used for the tree containing the ACL's was not stable. It violated the expected behaviour. ( cmp(a, b) == -cmp(b, a) ) This made the ACL tree useless in case wildcards were used. Changed so the tree now uses the normal avl_strcmp. As a downside we have to iterate over all ACL entries in order to find a match. Wildcards are now supported for both object and method names. The internal replacement of * with TAB was removed as it looked like a complication with no real benefit. Signed-off-by: Koen Dergent --- ubusd_acl.c | 81 ++++++++++++++++++++++++++----------------------------------- 1 file changed, 34 insertions(+), 47 deletions(-) diff --git a/ubusd_acl.c b/ubusd_acl.c index 4b72663..a1e52e6 100644 --- a/ubusd_acl.c +++ b/ubusd_acl.c @@ -12,6 +12,7 @@ */ #define _GNU_SOURCE +#include #include #include #include @@ -68,53 +69,48 @@ static struct avl_tree ubusd_acls; static int ubusd_acl_seq; static struct ubus_object *acl_obj; -static int -ubusd_acl_match_path(const void *k1, const void *k2, void *ptr) +static bool +name_matches_pattern(const char *name, const char *pattern) { - const char *name = k1; - const char *match = k2; - char *wildcard = strstr(match, "\t"); + char *wildcard = strstr(pattern, "*"); if (wildcard) - return strncmp(name, match, wildcard - match); + return strncmp(name, pattern, wildcard - pattern)==0; - return strcmp(name, match); + return strcmp(name, pattern)==0; } -static int -ubusd_acl_match_cred(struct ubus_client *cl, struct ubusd_acl_obj *obj) +static bool +client_credentials_match_acl(struct ubus_client *cl, struct ubusd_acl_obj *obj) { if (obj->user && !strcmp(cl->user, obj->user)) - return 0; + return true; if (obj->group && !strcmp(cl->group, obj->group)) - return 0; + return true; - return -1; + return false; +} + +static bool +client_is_root(struct ubus_client *cl) +{ + return cl->uid==0; } int -ubusd_acl_check(struct ubus_client *cl, const char *obj, +ubusd_acl_check(struct ubus_client *cl, const char *objname, const char *method, enum ubusd_acl_type type) { - struct ubusd_acl_obj *acl; - struct blob_attr *cur; - int rem; - - if (!cl->uid || !obj) - return 0; - - acl = avl_find_ge_element(&ubusd_acls, obj, acl, avl); - if (!acl) - return -1; - - avl_for_element_to_last(&ubusd_acls, acl, acl, avl) { - int diff = ubusd_acl_match_path(obj, acl->avl.key, NULL); + if (!objname) return 0; + if (client_is_root(cl)) return 0; - if (diff) - break; + struct ubusd_acl_obj *acl; + avl_for_each_element(&ubusd_acls, acl, avl) { + if (!name_matches_pattern(objname, (const char*)acl->avl.key)) + continue; - if (ubusd_acl_match_cred(cl, acl)) + if (!client_credentials_match_acl(cl, acl)) continue; switch (type) { @@ -129,11 +125,14 @@ ubusd_acl_check(struct ubus_client *cl, const char *obj, break; case UBUS_ACL_ACCESS: - if (acl->methods) + if (acl->methods) { + struct blob_attr *cur; + int rem; blobmsg_for_each_attr(cur, acl->methods, rem) if (blobmsg_type(cur) == BLOBMSG_TYPE_STRING) - if (!ubusd_acl_match_path(method, blobmsg_get_string(cur), NULL)) + if (name_matches_pattern(method, blobmsg_get_string(cur))) return 0; + } break; } } @@ -220,12 +219,6 @@ ubusd_acl_alloc_obj(struct ubusd_acl_file *file, const char *obj) o->avl.key = k; strcpy(k, obj); - while (*k) { - if (*k == '*') - *k = '\t'; - k++; - } - list_add(&o->list, &file->acl); avl_insert(&ubusd_acls, &o->avl); @@ -424,20 +417,14 @@ ubusd_reply_add(struct ubus_object *obj) if (!obj->path.key) return; - acl = avl_find_ge_element(&ubusd_acls, obj->path.key, acl, avl); - if (!acl) - return; - - avl_for_element_to_last(&ubusd_acls, acl, acl, avl) { - void *c; - + avl_for_each_element(&ubusd_acls, acl, avl) { if (!acl->priv) continue; - if (ubusd_acl_match_path(obj->path.key, acl->avl.key, NULL)) + if (!name_matches_pattern((const char*)obj->path.key, (const char*)acl->avl.key)) continue; - c = blobmsg_open_table(&b, NULL); + void *c = blobmsg_open_table(&b, NULL); blobmsg_add_string(&b, "obj", obj->path.key); if (acl->user) blobmsg_add_string(&b, "user", acl->user); @@ -489,7 +476,7 @@ static int ubusd_acl_recv(struct ubus_client *cl, struct ubus_msg_buf *ub, const void ubusd_acl_init(void) { - avl_init(&ubusd_acls, ubusd_acl_match_path, true, NULL); + avl_init(&ubusd_acls, avl_strcmp, true, NULL); acl_obj = ubusd_create_object_internal(NULL, UBUS_SYSTEM_OBJECT_ACL); acl_obj->recv_msg = ubusd_acl_recv; }