db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose/*
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose SSSD
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose Library for rule based certificate to user mapping - KRB5 matching rules
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose Authors:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose Sumit Bose <sbose@redhat.com>
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose Copyright (C) 2017 Red Hat
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose This program is free software; you can redistribute it and/or modify
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose it under the terms of the GNU General Public License as published by
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose the Free Software Foundation; either version 3 of the License, or
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose (at your option) any later version.
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose This program is distributed in the hope that it will be useful,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose but WITHOUT ANY WARRANTY; without even the implied warranty of
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose GNU General Public License for more details.
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose You should have received a copy of the GNU General Public License
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose along with this program. If not, see <http://www.gnu.org/licenses/>.
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose*/
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
96e1794db6915a655d97ecab7ab71ad53d1f527bLukas Slebodnik#include <ctype.h>
96e1794db6915a655d97ecab7ab71ad53d1f527bLukas Slebodnik
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#include "util/util.h"
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#include "util/crypto/sss_crypto.h"
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#include "lib/certmap/sss_certmap.h"
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#include "lib/certmap/sss_certmap_int.h"
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic bool is_dotted_decimal(const char *s, size_t len)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose{
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose size_t c = 0;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose bool has_dot = false;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (s == NULL || !isdigit(s[c++])) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return false;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose while ((len == 0 && s[c] != '\0') || (len != 0 && c < len)) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (s[c] != '.' && !isdigit(s[c])) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return false;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (!has_dot && s[c] == '.') {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose has_dot = true;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose c++;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return (has_dot && isdigit(s[c - 1]));
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic int component_list_destructor(void *data)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose{
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct component_list *comp = talloc_get_type(data, struct component_list);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (comp != NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose regfree(&(comp->regexp));
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return 0;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose/*
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose * The syntax of the MIT Kerberos style matching rules is:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose * [KRB5:][relation-operator]component-rule ...
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose *
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose * where:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose *
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose * relation-operator
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose * can be either &&, meaning all component rules must match, or ||,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose * meaning only one component rule must match. The default is &&.
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose *
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose * component-rule
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose * can be one of the following. Note that there is no punctuation or whitespace between component rules.
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose * <SUBJECT>regular-expression
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose * <ISSUER>regular-expression
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose * <SAN>regular-expression
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose * <EKU>extended-key-usage
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose * <KU>key-usage
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose *
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose * see man sss-certmap for more details
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose *
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose */
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic int get_comp_value(TALLOC_CTX *mem_ctx,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct sss_certmap_ctx *ctx,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose const char **cur,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct component_list **_comp)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose{
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct component_list *comp = NULL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose const char *end;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose int ret;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose comp = talloc_zero(mem_ctx, struct component_list);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (comp == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = ENOMEM;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose talloc_set_destructor((TALLOC_CTX *) comp, component_list_destructor);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose end = strchr(*cur, '<');
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (end == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose comp->val = talloc_strdup(comp, *cur);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose } else {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose comp->val = talloc_strndup(comp, *cur, end - *cur);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (comp->val == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = ENOMEM;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (*(comp->val) == '\0') {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose CM_DEBUG(ctx, "Missing component value.");
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = EINVAL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose *cur += strlen(comp->val);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose *_comp = comp;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = 0;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosedone:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose talloc_free(comp);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return ret;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic int parse_krb5_get_eku_value(TALLOC_CTX *mem_ctx,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct sss_certmap_ctx *ctx,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose const char **cur,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct component_list **_comp)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose{
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct component_list *comp = NULL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose int ret;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose char **eku_list;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose size_t c;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose size_t k;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose const char *o;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose size_t e = 0;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose int eku_list_size;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct ext_key_usage {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose const char *name;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose const char *oid;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose } ext_key_usage[] = {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose /* RFC 3280 section 4.2.1.13 */
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {"serverAuth", "1.3.6.1.5.5.7.3.1"},
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {"clientAuth", "1.3.6.1.5.5.7.3.2"},
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {"codeSigning", "1.3.6.1.5.5.7.3.3"},
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {"emailProtection", "1.3.6.1.5.5.7.3.4"},
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {"timeStamping", "1.3.6.1.5.5.7.3.8"},
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {"OCSPSigning", "1.3.6.1.5.5.7.3.9"},
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose /* RFC 4556 section 3.2.2 */
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {"KPClientAuth", "1.3.6.1.5.2.3.4"},
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {"pkinit", "1.3.6.1.5.2.3.4"},
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose /* https://support.microsoft.com/en-us/help/287547/object-ids-associated-with-microsoft-cryptography*/
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {"msScLogin", "1.3.6.1.4.1.311.20.2.2"},
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {NULL ,0}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose };
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = get_comp_value(mem_ctx, ctx, cur, &comp);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose CM_DEBUG(ctx, "Failed to parse regexp.");
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = split_on_separator(mem_ctx, comp->val, ',', true, true,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose &eku_list, &eku_list_size);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose CM_DEBUG(ctx, "Failed to split list.");
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
f5a8cd60c6f377af1954b58f007d16cf3f6dc846Sumit Bose comp->eku_oid_list = talloc_zero_array(comp, const char *,
f5a8cd60c6f377af1954b58f007d16cf3f6dc846Sumit Bose eku_list_size + 1);
f5a8cd60c6f377af1954b58f007d16cf3f6dc846Sumit Bose if (comp->eku_oid_list == NULL) {
f5a8cd60c6f377af1954b58f007d16cf3f6dc846Sumit Bose ret = ENOMEM;
f5a8cd60c6f377af1954b58f007d16cf3f6dc846Sumit Bose goto done;
f5a8cd60c6f377af1954b58f007d16cf3f6dc846Sumit Bose }
f5a8cd60c6f377af1954b58f007d16cf3f6dc846Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose for (c = 0; eku_list[c] != NULL; c++) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose for (k = 0; ext_key_usage[k].name != NULL; k++) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit BoseCM_DEBUG(ctx, "[%s][%s].", eku_list[c], ext_key_usage[k].name);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (strcasecmp(eku_list[c], ext_key_usage[k].name) == 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose comp->eku_oid_list[e] = talloc_strdup(comp->eku_oid_list,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ext_key_usage[k].oid);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (comp->eku_oid_list[e] == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = ENOMEM;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose e++;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose break;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ext_key_usage[k].name == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose /* check for an dotted-decimal OID */
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (*(eku_list[c]) != '.') {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose o = eku_list[c];
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (is_dotted_decimal(o, 0)) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose /* looks like a OID, only '.' and digits */
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose comp->eku_oid_list[e] = talloc_strdup(comp->eku_oid_list,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose eku_list[c]);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (comp->eku_oid_list[e] == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = ENOMEM;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose e++;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose continue;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose CM_DEBUG(ctx, "No matching extended key usage found.");
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = EINVAL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
f5a8cd60c6f377af1954b58f007d16cf3f6dc846Sumit Bose if (e == 0) {
f5a8cd60c6f377af1954b58f007d16cf3f6dc846Sumit Bose talloc_free(comp->eku_oid_list);
f5a8cd60c6f377af1954b58f007d16cf3f6dc846Sumit Bose comp->eku_oid_list = NULL;
f5a8cd60c6f377af1954b58f007d16cf3f6dc846Sumit Bose }
f5a8cd60c6f377af1954b58f007d16cf3f6dc846Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = 0;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosedone:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret == 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose *_comp = comp;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose } else {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose talloc_free(comp);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return ret;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic int parse_krb5_get_ku_value(TALLOC_CTX *mem_ctx,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct sss_certmap_ctx *ctx,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose const char **cur,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct component_list **_comp)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose{
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct component_list *comp = NULL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose int ret;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose char **ku_list;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose size_t c;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose size_t k;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct key_usage {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose const char *name;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose uint32_t flag;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose } key_usage[] = {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {"digitalSignature" , SSS_KU_DIGITAL_SIGNATURE},
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {"nonRepudiation" , SSS_KU_NON_REPUDIATION},
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {"keyEncipherment" , SSS_KU_KEY_ENCIPHERMENT},
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {"dataEncipherment" , SSS_KU_DATA_ENCIPHERMENT},
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {"keyAgreement" , SSS_KU_KEY_AGREEMENT},
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {"keyCertSign" , SSS_KU_KEY_CERT_SIGN},
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {"cRLSign" , SSS_KU_CRL_SIGN},
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {"encipherOnly" , SSS_KU_ENCIPHER_ONLY},
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {"decipherOnly" , SSS_KU_DECIPHER_ONLY},
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {NULL ,0}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose };
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = get_comp_value(mem_ctx, ctx, cur, &comp);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose CM_DEBUG(ctx, "Failed to get value.");
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = split_on_separator(mem_ctx, comp->val, ',', true, true,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose &ku_list, NULL);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose CM_DEBUG(ctx, "Failed to split list.");
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose for (c = 0; ku_list[c] != NULL; c++) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose for (k = 0; key_usage[k].name != NULL; k++) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (strcasecmp(ku_list[c], key_usage[k].name) == 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose comp->ku |= key_usage[k].flag;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose break;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (key_usage[k].name == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose /* FIXME: add check for numerical ku */
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose CM_DEBUG(ctx, "No matching key usage found.");
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = EINVAL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = 0;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosedone:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret == 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose *_comp = comp;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose } else {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose talloc_free(comp);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return ret;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic int parse_krb5_get_component_value(TALLOC_CTX *mem_ctx,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct sss_certmap_ctx *ctx,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose const char **cur,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct component_list **_comp)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose{
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct component_list *comp = NULL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose int ret;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = get_comp_value(mem_ctx, ctx, cur, &comp);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose CM_DEBUG(ctx, "Failed to parse regexp.");
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = regcomp(&(comp->regexp), comp->val, REG_EXTENDED);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose CM_DEBUG(ctx, "Failed to parse regexp.");
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = 0;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosedone:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret == 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose *_comp = comp;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose } else {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose talloc_free(comp);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return ret;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestruct san_name {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose const char *name;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose enum san_opt san_opt;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose bool is_string;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose} san_names[] = {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose /* https://www.ietf.org/rfc/rfc3280.txt section 4.2.1.7 */
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {"otherName", SAN_OTHER_NAME, false},
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {"rfc822Name", SAN_RFC822_NAME,true},
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {"dNSName", SAN_DNS_NAME, true},
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {"x400Address", SAN_X400_ADDRESS, false},
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {"directoryName", SAN_DIRECTORY_NAME, true},
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {"ediPartyName", SAN_EDIPART_NAME, false},
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {"uniformResourceIdentifier", SAN_URI, true},
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {"iPAddress", SAN_IP_ADDRESS, true},
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {"registeredID", SAN_REGISTERED_ID, true},
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose /* https://www.ietf.org/rfc/rfc4556.txt section 3.2.2 */
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {"pkinitSAN", SAN_PKINIT, true},
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose /* https://support.microsoft.com/en-us/help/287547/object-ids-associated-with-microsoft-cryptography */
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {"ntPrincipalName", SAN_NT, true},
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose /* both previous principal types */
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {"Principal", SAN_PRINCIPAL, true},
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {"stringOtherName", SAN_STRING_OTHER_NAME, true},
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {NULL, SAN_END, false}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose};
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic int parse_krb5_get_san_option(TALLOC_CTX *mem_ctx,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct sss_certmap_ctx *ctx,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose const char **cur,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose enum san_opt *option,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose char **str_other_name_oid)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose{
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose char *end;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose size_t c;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose size_t len;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose end = strchr(*cur, '>');
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (end == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose CM_DEBUG(ctx, "Failed to parse SAN option.");
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return EINVAL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose len = end - *cur;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (len == 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose c= SAN_PRINCIPAL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose } else {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose for (c = 0; san_names[c].name != NULL; c++) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (strncasecmp(*cur, san_names[c].name, len) == 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose break;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (san_names[c].name == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (is_dotted_decimal(*cur, len)) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose c = SAN_STRING_OTHER_NAME;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose *str_other_name_oid = talloc_strndup(mem_ctx, *cur, len);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (*str_other_name_oid == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose CM_DEBUG(ctx, "talloc_strndup failed.");
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return ENOMEM;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose } else {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose CM_DEBUG(ctx, "Unknown SAN option.");
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return EINVAL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose *option = san_names[c].san_opt;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose *cur = end + 1;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return 0;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic int parse_krb5_get_san_value(TALLOC_CTX *mem_ctx,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct sss_certmap_ctx *ctx,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose const char **cur,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct component_list **_comp)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose{
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct component_list *comp = NULL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose enum san_opt san_opt = SAN_PRINCIPAL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose int ret;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose char *str_other_name_oid = NULL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (*(*cur - 1) == ':') {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = parse_krb5_get_san_option(mem_ctx, ctx, cur, &san_opt,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose &str_other_name_oid);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (san_names[san_opt].is_string) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = parse_krb5_get_component_value(mem_ctx, ctx, cur, &comp);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose } else {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = get_comp_value(mem_ctx, ctx, cur, &comp);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (comp->val != NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose comp->bin_val = sss_base64_decode(comp, comp->val,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose &comp->bin_val_len);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose /* for some reasons the NSS version of sss_base64_decode might
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose * return a non-NULL value on error but len is still 0, so better
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose * check both. */
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (comp->bin_val == NULL || comp->bin_val_len == 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose CM_DEBUG(ctx, "Base64 decode failed.");
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = EINVAL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose comp->san_opt = san_opt;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosedone:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret == 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose comp->str_other_name_oid = talloc_steal(comp, str_other_name_oid);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose *_comp = comp;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose } else {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose talloc_free(comp);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose talloc_free(str_other_name_oid);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return ret;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Boseint parse_krb5_match_rule(struct sss_certmap_ctx *ctx,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose const char *rule_start,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct krb5_match_rule **match_rule)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose{
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose const char *cur;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct krb5_match_rule *rule;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct component_list *comp;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose int ret;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose rule = talloc_zero(ctx, struct krb5_match_rule);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (rule == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = ENOMEM;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose cur = rule_start;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose /* check relation */
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (strncmp(cur, "&&", 2) == 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose rule->r = relation_and;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose cur += 2;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose } else if (strncmp(cur, "||", 2) == 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose rule->r = relation_or;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose cur += 2;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose } else {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose rule->r = relation_and;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose while (*cur != '\0') {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose /* new component must start with '<' */
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (*cur != '<') {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose CM_DEBUG(ctx, "Invalid KRB5 matching rule.");
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = EINVAL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose cur++;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (strncmp(cur, "ISSUER>", 7) == 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose cur += 7;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = parse_krb5_get_component_value(rule, ctx, &cur, &comp);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose DLIST_ADD(rule->issuer, comp);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose } else if (strncmp(cur, "SUBJECT>", 8) == 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose cur += 8;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = parse_krb5_get_component_value(rule, ctx, &cur, &comp);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose DLIST_ADD(rule->subject, comp);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose } else if (strncmp(cur, "KU>", 3) == 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose cur += 3;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = parse_krb5_get_ku_value(rule, ctx, &cur, &comp);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose DLIST_ADD(rule->ku, comp);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose } else if (strncmp(cur, "EKU>", 4) == 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose cur += 4;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = parse_krb5_get_eku_value(rule, ctx, &cur, &comp);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose DLIST_ADD(rule->eku, comp);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose } else if (strncmp(cur, "SAN>", 4) == 0
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose || strncmp(cur, "SAN:", 4) == 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose cur += 4;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = parse_krb5_get_san_value(rule, ctx, &cur, &comp);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose DLIST_ADD(rule->san, comp);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose } else {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose CM_DEBUG(ctx, "Invalid KRB5 matching rule.");
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = EINVAL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = 0;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosedone:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret == 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose *match_rule = rule;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose } else {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose talloc_free(rule);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return ret;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose}