Blame src/supplicant/nm-supplicant-settings-verify.c

Packit Service 87a54e
/* SPDX-License-Identifier: GPL-2.0-or-later */
Packit 5756e2
/*
Packit 5756e2
 * Copyright (C) 2006 - 2012 Red Hat, Inc.
Packit 5756e2
 */
Packit 5756e2
Packit 5756e2
#include "nm-default.h"
Packit 5756e2
Packit 5756e2
#include "nm-supplicant-settings-verify.h"
Packit 5756e2
Packit 5756e2
#include <stdio.h>
Packit 5756e2
#include <stdlib.h>
Packit 5756e2
Packit 5756e2
struct Opt {
Packit Service a1bd4f
    const char *         key;
Packit Service a1bd4f
    const char *const *  str_allowed;
Packit Service a1bd4f
    const NMSupplOptType type;
Packit Service a1bd4f
    const guint32        int_low;  /* Inclusive */
Packit Service a1bd4f
    const guint32        int_high; /* Inclusive; max length for strings */
Packit 5756e2
};
Packit 5756e2
Packit Service a1bd4f
typedef gboolean (*validate_func)(const struct Opt *, const char *, const guint32);
Packit Service a1bd4f
Packit Service a1bd4f
#define OPT_INT(_key, _int_low, _int_high)                                                      \
Packit Service a1bd4f
    {                                                                                           \
Packit Service a1bd4f
        .key = _key, .type = NM_SUPPL_OPT_TYPE_INT, .int_high = _int_high, .int_low = _int_low, \
Packit Service a1bd4f
    }
Packit Service a1bd4f
#define OPT_BYTES(_key, _int_high)                                           \
Packit Service a1bd4f
    {                                                                        \
Packit Service a1bd4f
        .key = _key, .type = NM_SUPPL_OPT_TYPE_BYTES, .int_high = _int_high, \
Packit Service a1bd4f
    }
Packit Service a1bd4f
#define OPT_UTF8(_key, _int_high)                                           \
Packit Service a1bd4f
    {                                                                       \
Packit Service a1bd4f
        .key = _key, .type = NM_SUPPL_OPT_TYPE_UTF8, .int_high = _int_high, \
Packit Service a1bd4f
    }
Packit Service a1bd4f
#define OPT_KEYWORD(_key, _str_allowed)                                              \
Packit Service a1bd4f
    {                                                                                \
Packit Service a1bd4f
        .key = _key, .type = NM_SUPPL_OPT_TYPE_KEYWORD, .str_allowed = _str_allowed, \
Packit Service a1bd4f
    }
Packit 5756e2
Packit 5756e2
static const struct Opt opt_table[] = {
Packit Service a1bd4f
    OPT_BYTES("altsubject_match", 0),
Packit Service a1bd4f
    OPT_BYTES("altsubject_match2", 0),
Packit Service a1bd4f
    OPT_BYTES("anonymous_identity", 0),
Packit Service a1bd4f
    OPT_KEYWORD("auth_alg", NM_MAKE_STRV("OPEN", "SHARED", "LEAP", )),
Packit Service a1bd4f
    OPT_BYTES("bgscan", 0),
Packit Service a1bd4f
    OPT_KEYWORD("bssid", NULL),
Packit Service a1bd4f
    OPT_BYTES("ca_cert", 65536),
Packit Service a1bd4f
    OPT_BYTES("ca_cert2", 65536),
Packit Service a1bd4f
    OPT_BYTES("ca_path", 0),
Packit Service a1bd4f
    OPT_BYTES("ca_path2", 0),
Packit Service a1bd4f
    OPT_BYTES("client_cert", 65536),
Packit Service a1bd4f
    OPT_BYTES("client_cert2", 65536),
Packit Service a1bd4f
    OPT_BYTES("domain_match", 0),
Packit Service a1bd4f
    OPT_BYTES("domain_match2", 0),
Packit Service a1bd4f
    OPT_BYTES("domain_suffix_match", 0),
Packit Service a1bd4f
    OPT_BYTES("domain_suffix_match2", 0),
Packit Service a1bd4f
    OPT_KEYWORD("eap",
Packit Service a1bd4f
                NM_MAKE_STRV("LEAP", "MD5", "TLS", "PEAP", "TTLS", "SIM", "PSK", "FAST", "PWD", )),
Packit Service a1bd4f
    OPT_INT("eapol_flags", 0, 3),
Packit Service a1bd4f
    OPT_BYTES("eappsk", 0),
Packit Service a1bd4f
    OPT_INT("engine", 0, 1),
Packit Service a1bd4f
    OPT_BYTES("engine_id", 0),
Packit Service a1bd4f
    OPT_INT("fragment_size", 1, 2000),
Packit Service a1bd4f
    OPT_KEYWORD("freq_list", NULL),
Packit Service a1bd4f
    OPT_INT("frequency", 2412, 5825),
Packit Service d0b836
    OPT_KEYWORD("group", NM_MAKE_STRV("CCMP", "TKIP", "WEP104", "WEP40", "GCMP-256", )),
Packit Service a1bd4f
    OPT_BYTES("identity", 0),
Packit Service a1bd4f
    OPT_INT("ieee80211w", 0, 2),
Packit Service a1bd4f
    OPT_INT("ignore_broadcast_ssid", 0, 2),
Packit Service a1bd4f
    OPT_BYTES("key_id", 0),
Packit Service a1bd4f
    OPT_KEYWORD("key_mgmt",
Packit Service a1bd4f
                NM_MAKE_STRV("WPA-PSK",
Packit Service a1bd4f
                             "WPA-PSK-SHA256",
Packit Service a1bd4f
                             "FT-PSK",
Packit Service a1bd4f
                             "WPA-EAP",
Packit Service a1bd4f
                             "WPA-EAP-SHA256",
Packit Service a1bd4f
                             "FT-EAP",
Packit Service a1bd4f
                             "FT-EAP-SHA384",
Packit Service a1bd4f
                             "FILS-SHA256",
Packit Service a1bd4f
                             "FILS-SHA384",
Packit Service a1bd4f
                             "FT-FILS-SHA256",
Packit Service a1bd4f
                             "FT-FILS-SHA384",
Packit Service a1bd4f
                             "IEEE8021X",
Packit Service a1bd4f
                             "SAE",
Packit Service d0b836
                             "WPA-EAP-SUITE-B-192",
Packit Service a1bd4f
                             "FT-SAE",
Packit Service a1bd4f
                             "OWE",
Packit Service a1bd4f
                             "NONE", )),
Packit Service a1bd4f
    OPT_INT("macsec_integ_only", 0, 1),
Packit Service a1bd4f
    OPT_INT("macsec_policy", 0, 1),
Packit Service a1bd4f
    OPT_INT("macsec_port", 1, 65534),
Packit Service a1bd4f
    OPT_BYTES("mka_cak", 65536),
Packit Service a1bd4f
    OPT_BYTES("mka_ckn", 65536),
Packit Service a1bd4f
    OPT_BYTES("nai", 0),
Packit Service a1bd4f
    OPT_BYTES("pac_file", 0),
Packit Service d0b836
    OPT_KEYWORD("pairwise", NM_MAKE_STRV("CCMP", "TKIP", "GCMP-256", "NONE", )),
Packit Service a1bd4f
    OPT_UTF8("password", 0),
Packit Service a1bd4f
    OPT_BYTES("pcsc", 0),
Packit Service a1bd4f
    OPT_KEYWORD("phase1",
Packit Service a1bd4f
                NM_MAKE_STRV("peapver=0",
Packit Service a1bd4f
                             "peapver=1",
Packit Service a1bd4f
                             "peaplabel=1",
Packit Service a1bd4f
                             "peap_outer_success=0",
Packit Service a1bd4f
                             "include_tls_length=1",
Packit Service a1bd4f
                             "sim_min_num_chal=3",
Packit Service a1bd4f
                             "fast_provisioning=0",
Packit Service a1bd4f
                             "fast_provisioning=1",
Packit Service a1bd4f
                             "fast_provisioning=2",
Packit Service a1bd4f
                             "fast_provisioning=3",
Packit Service a1bd4f
                             "tls_disable_tlsv1_0=0",
Packit Service a1bd4f
                             "tls_disable_tlsv1_0=1",
Packit Service a1bd4f
                             "tls_disable_tlsv1_1=0",
Packit Service a1bd4f
                             "tls_disable_tlsv1_1=1",
Packit Service a1bd4f
                             "tls_disable_tlsv1_2=0",
Packit Service a1bd4f
                             "tls_disable_tlsv1_2=1", )),
Packit Service a1bd4f
    OPT_KEYWORD("phase2",
Packit Service a1bd4f
                NM_MAKE_STRV("auth=PAP",
Packit Service a1bd4f
                             "auth=CHAP",
Packit Service a1bd4f
                             "auth=MSCHAP",
Packit Service a1bd4f
                             "auth=MSCHAPV2",
Packit Service a1bd4f
                             "auth=GTC",
Packit Service a1bd4f
                             "auth=OTP",
Packit Service a1bd4f
                             "auth=MD5",
Packit Service a1bd4f
                             "auth=TLS",
Packit Service a1bd4f
                             "autheap=MD5",
Packit Service a1bd4f
                             "autheap=MSCHAPV2",
Packit Service a1bd4f
                             "autheap=OTP",
Packit Service a1bd4f
                             "autheap=GTC",
Packit Service a1bd4f
                             "autheap=TLS", )),
Packit Service a1bd4f
    OPT_BYTES("pin", 0),
Packit Service a1bd4f
    OPT_BYTES("private_key", 65536),
Packit Service a1bd4f
    OPT_BYTES("private_key2", 65536),
Packit Service a1bd4f
    OPT_BYTES("private_key2_passwd", 1024),
Packit Service a1bd4f
    OPT_BYTES("private_key_passwd", 1024),
Packit Service a1bd4f
    OPT_INT("proactive_key_caching", 0, 1),
Packit Service a1bd4f
    OPT_KEYWORD("proto", NM_MAKE_STRV("WPA", "RSN", )),
Packit Service a1bd4f
    OPT_BYTES("psk", 0),
Packit Service a1bd4f
    OPT_INT("scan_ssid", 0, 1),
Packit Service a1bd4f
    OPT_BYTES("ssid", 32),
Packit Service a1bd4f
    OPT_BYTES("subject_match", 0),
Packit Service a1bd4f
    OPT_BYTES("subject_match2", 0),
Packit Service a1bd4f
    OPT_BYTES("wep_key0", 0),
Packit Service a1bd4f
    OPT_BYTES("wep_key1", 0),
Packit Service a1bd4f
    OPT_BYTES("wep_key2", 0),
Packit Service a1bd4f
    OPT_BYTES("wep_key3", 0),
Packit Service a1bd4f
    OPT_INT("wep_tx_keyidx", 0, 3),
Packit 5756e2
};
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
validate_type_int(const struct Opt *opt, const char *value, const guint32 len)
Packit 5756e2
{
Packit Service a1bd4f
    gint64 v;
Packit 5756e2
Packit Service a1bd4f
    nm_assert(opt);
Packit Service a1bd4f
    nm_assert(value);
Packit 5756e2
Packit Service a1bd4f
    v = _nm_utils_ascii_str_to_int64(value, 10, opt->int_low, opt->int_high, G_MININT64);
Packit Service a1bd4f
    return v != G_MININT64 || errno == 0;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
validate_type_bytes(const struct Opt *opt, const char *value, const guint32 len)
Packit 5756e2
{
Packit Service a1bd4f
    guint32 check_len;
Packit 5756e2
Packit Service a1bd4f
    nm_assert(opt);
Packit Service a1bd4f
    nm_assert(value);
Packit 5756e2
Packit Service a1bd4f
    check_len = opt->int_high ?: 255;
Packit Service a1bd4f
    if (len > check_len)
Packit Service a1bd4f
        return FALSE;
Packit 5756e2
Packit Service a1bd4f
    return TRUE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
validate_type_utf8(const struct Opt *opt, const char *value, const guint32 len)
Packit 5756e2
{
Packit Service a1bd4f
    guint32 check_len;
Packit 5756e2
Packit Service a1bd4f
    nm_assert(opt);
Packit Service a1bd4f
    nm_assert(value);
Packit 5756e2
Packit Service a1bd4f
    check_len = opt->int_high ?: 255;
Packit Service a1bd4f
    /* Note that we deliberately don't validate the UTF-8, because
Packit Service a1bd4f
     * some "UTF-8" fields, such as 8021x.password, do not actually
Packit Service a1bd4f
     * have to be valid UTF-8 */
Packit Service a1bd4f
    if (g_utf8_strlen(value, len) > check_len)
Packit Service a1bd4f
        return FALSE;
Packit 5756e2
Packit Service a1bd4f
    return TRUE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
validate_type_keyword(const struct Opt *opt, const char *value, const guint32 len)
Packit 5756e2
{
Packit Service a1bd4f
    gs_free char *value_free = NULL;
Packit 5756e2
Packit Service a1bd4f
    nm_assert(opt);
Packit Service a1bd4f
    nm_assert(value);
Packit 5756e2
Packit Service a1bd4f
    /* Allow everything */
Packit Service a1bd4f
    if (!opt->str_allowed)
Packit Service a1bd4f
        return TRUE;
Packit 5756e2
Packit Service a1bd4f
    value = nm_strndup_a(300, value, len, &value_free);
Packit 5756e2
Packit Service a1bd4f
    /* validate each space-separated word in 'value' */
Packit 5756e2
Packit Service a1bd4f
    while (TRUE) {
Packit Service a1bd4f
        char *s;
Packit 5756e2
Packit Service a1bd4f
        while (value[0] == ' ')
Packit Service a1bd4f
            value++;
Packit 5756e2
Packit Service a1bd4f
        if (value[0] == '\0')
Packit Service a1bd4f
            return TRUE;
Packit 5756e2
Packit Service a1bd4f
        s = strchr(value, ' ');
Packit Service a1bd4f
        if (s) {
Packit Service a1bd4f
            s[0] = '\0';
Packit Service a1bd4f
            s++;
Packit Service a1bd4f
        }
Packit 5756e2
Packit Service a1bd4f
        if (nm_utils_strv_find_first((char **) opt->str_allowed, -1, value) < 0)
Packit Service a1bd4f
            return FALSE;
Packit 5756e2
Packit Service a1bd4f
        if (!s)
Packit Service a1bd4f
            return TRUE;
Packit 5756e2
Packit Service a1bd4f
        value = s;
Packit Service a1bd4f
    }
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
NMSupplOptType
Packit Service a1bd4f
nm_supplicant_settings_verify_setting(const char *key, const char *value, const guint32 len)
Packit 5756e2
{
Packit Service a1bd4f
    static const validate_func validate_table[_NM_SUPPL_OPT_TYPE_NUM - 1] = {
Packit Service a1bd4f
        [NM_SUPPL_OPT_TYPE_INT - 1]     = validate_type_int,
Packit Service a1bd4f
        [NM_SUPPL_OPT_TYPE_BYTES - 1]   = validate_type_bytes,
Packit Service a1bd4f
        [NM_SUPPL_OPT_TYPE_UTF8 - 1]    = validate_type_utf8,
Packit Service a1bd4f
        [NM_SUPPL_OPT_TYPE_KEYWORD - 1] = validate_type_keyword,
Packit Service a1bd4f
    };
Packit Service a1bd4f
    const struct Opt *opt;
Packit Service a1bd4f
    gssize            opt_idx;
Packit Service a1bd4f
Packit Service a1bd4f
    g_return_val_if_fail(key, FALSE);
Packit Service a1bd4f
    g_return_val_if_fail(value, FALSE);
Packit Service a1bd4f
Packit Service a1bd4f
    if (NM_MORE_ASSERT_ONCE(5)) {
Packit Service a1bd4f
        gsize i;
Packit Service a1bd4f
Packit Service a1bd4f
        for (i = 0; i < G_N_ELEMENTS(opt_table); i++) {
Packit Service a1bd4f
            opt = &opt_table[i];
Packit Service a1bd4f
Packit Service a1bd4f
            nm_assert(opt->key);
Packit Service a1bd4f
            nm_assert(opt->type > NM_SUPPL_OPT_TYPE_INVALID);
Packit Service a1bd4f
            nm_assert(opt->type < _NM_SUPPL_OPT_TYPE_NUM);
Packit Service a1bd4f
            if (i > 0)
Packit Service a1bd4f
                nm_assert(strcmp(opt[-1].key, opt->key) < 0);
Packit Service a1bd4f
            nm_assert(validate_table[opt->type - 1]);
Packit Service a1bd4f
Packit Service a1bd4f
            nm_assert(!opt->str_allowed || (opt->type == NM_SUPPL_OPT_TYPE_KEYWORD));
Packit Service a1bd4f
            nm_assert(!opt->str_allowed || NM_PTRARRAY_LEN(opt->str_allowed) > 0);
Packit Service a1bd4f
Packit Service a1bd4f
            nm_assert(opt->int_low == 0 || opt->type == NM_SUPPL_OPT_TYPE_INT);
Packit Service a1bd4f
Packit Service a1bd4f
            nm_assert(opt->int_high == 0
Packit Service a1bd4f
                      || NM_IN_SET(opt->type,
Packit Service a1bd4f
                                   NM_SUPPL_OPT_TYPE_INT,
Packit Service a1bd4f
                                   NM_SUPPL_OPT_TYPE_UTF8,
Packit Service a1bd4f
                                   NM_SUPPL_OPT_TYPE_BYTES));
Packit Service a1bd4f
Packit Service a1bd4f
            nm_assert(opt->type != NM_SUPPL_OPT_TYPE_INT || opt->int_low < opt->int_high);
Packit Service a1bd4f
        }
Packit Service a1bd4f
    }
Packit Service a1bd4f
Packit Service a1bd4f
    opt_idx = nm_utils_array_find_binary_search(opt_table,
Packit Service a1bd4f
                                                sizeof(opt_table[0]),
Packit Service a1bd4f
                                                G_N_ELEMENTS(opt_table),
Packit Service a1bd4f
                                                &key,
Packit Service a1bd4f
                                                nm_strcmp_p_with_data,
Packit Service a1bd4f
                                                NULL);
Packit Service a1bd4f
    if (opt_idx < 0) {
Packit Service a1bd4f
        if (nm_streq(key, "mode")) {
Packit Service a1bd4f
            if (len != 1)
Packit Service a1bd4f
                return NM_SUPPL_OPT_TYPE_INVALID;
Packit Service a1bd4f
            if (!NM_IN_SET(value[0], '1', '2', '5'))
Packit Service a1bd4f
                return NM_SUPPL_OPT_TYPE_INVALID;
Packit Service a1bd4f
            return NM_SUPPL_OPT_TYPE_INT;
Packit Service a1bd4f
        }
Packit Service a1bd4f
        return NM_SUPPL_OPT_TYPE_INVALID;
Packit Service a1bd4f
    }
Packit Service a1bd4f
Packit Service a1bd4f
    opt = &opt_table[opt_idx];
Packit Service a1bd4f
    if (!((validate_table[opt->type - 1])(opt, value, len)))
Packit Service a1bd4f
        return NM_SUPPL_OPT_TYPE_INVALID;
Packit Service a1bd4f
Packit Service a1bd4f
    return opt->type;
Packit 5756e2
}