/* * Parse TLS configuration * * If the option given by 'attr' is set, we find the config section * of that name and use that for the TLS configuration. If not, we * fall back to compatibility mode and read the TLS options from * the 'tls' section. */ fr_tls_server_conf_t *eaptls_conf_parse(CONF_SECTION *cs, char const *attr) { char const *tls_conf_name; CONF_PAIR *cp; CONF_SECTION *parent; CONF_SECTION *tls_cs; fr_tls_server_conf_t *tls_conf; if (!cs) return NULL; rad_assert(attr != NULL); parent = cf_item_parent(cf_section_to_item(cs)); cp = cf_pair_find(cs, attr); if (cp) { tls_conf_name = cf_pair_value(cp); tls_cs = cf_section_sub_find_name2(parent, TLS_CONFIG_SECTION, tls_conf_name); if (!tls_cs) { ERROR("Cannot find tls config \"%s\"", tls_conf_name); return NULL; } } else { /* * If we can't find the section given by the 'attr', we * fall-back to looking for the "tls" section, as in * previous versions. * * We don't fall back if the 'attr' is specified, but we can't * find the section - that is just a config error. */ INFO("TLS section \"%s\" missing, trying to use legacy configuration", attr); tls_cs = cf_section_sub_find(parent, "tls"); } if (!tls_cs) return NULL; tls_conf = tls_server_conf_parse(tls_cs); if (!tls_conf) return NULL; /* * The EAP RFC's say 1020, but we're less picky. */ if (tls_conf->fragment_size < 100) { ERROR("Configured fragment size is too small, must be >= 100"); return NULL; } /* * The maximum size for a RADIUS packet is 4096, * minus the header (20), Message-Authenticator (18), * and State (18), etc. results in about 4000 bytes of data * that can be devoted *solely* to EAP. */ if (tls_conf->fragment_size > 4000) { ERROR("Configured fragment size is too large, must be <= 4000"); return NULL; } /* * Account for the EAP header (4), and the EAP-TLS header * (6), as per Section 4.2 of RFC 2716. What's left is * the maximum amount of data we read from a TLS buffer. */ tls_conf->fragment_size -= 10; return tls_conf; }
/** Allocate a #CONF_SECTION * * @param[in] ctx to allocate * @param[in] parent #CONF_SECTION to hang this #CONF_SECTION off of. * If parent is not NULL, the new section will be added as a child. * @param[in] name1 Primary name. * @param[in] name2 Secondary name. * @param[in] filename Caller file name for debugging. May be overridden later. * @param[in] lineno Caller line number for debugging. May be overridden later. * @return * - NULL on error. * - A new #CONF_SECTION parented by parent. */ CONF_SECTION *_cf_section_alloc(TALLOC_CTX *ctx, CONF_SECTION *parent, char const *name1, char const *name2, char const *filename, int lineno) { CONF_SECTION *cs; char buffer[1024]; if (!name1) return NULL; if (name2 && parent) { char const *p; p = strchr(name2, '$'); if (p && (p[1] != '{')) p = NULL; if (p) { name2 = cf_expand_variables(parent->item.filename, &parent->item.lineno, parent, buffer, sizeof(buffer), name2, NULL); if (!name2) { ERROR("Failed expanding section name"); return NULL; } } } cs = talloc_zero(ctx, CONF_SECTION); if (!cs) return NULL; cs->item.type = CONF_ITEM_SECTION; cs->item.parent = cf_section_to_item(parent); fr_cursor_init(&cs->item.cursor, &cs->item.child); MEM(cs->name1 = talloc_typed_strdup(cs, name1)); if (name2) { MEM(cs->name2 = talloc_typed_strdup(cs, name2)); cs->name2_quote = T_BARE_WORD; } talloc_set_destructor(cs, _cf_section_free); if (filename) cf_filename_set(cs, filename); if (lineno) cf_lineno_set(cs, lineno); if (parent) { CONF_DATA const *cd; CONF_PARSER *rule; cs->depth = parent->depth + 1; cf_item_add(parent, &(cs->item)); cd = cf_data_find(CF_TO_ITEM(parent), CONF_PARSER, cf_section_name1(parent)); if (cd) { rule = cf_data_value(cd); /* * The parent has an ON_READ rule. Check * if that rule has a child which matches * this section. */ if ((FR_BASE_TYPE(rule->type) == FR_TYPE_SUBSECTION) && ((rule->type & FR_TYPE_ON_READ) != 0) && rule->subcs) { CONF_PARSER const *rule_p; for (rule_p = rule->subcs; rule_p->name; rule_p++) { if ((FR_BASE_TYPE(rule_p->type) == FR_TYPE_SUBSECTION) && ((rule_p->type & FR_TYPE_ON_READ) != 0) && (strcmp(rule_p->name, name1) == 0)) { (void) _cf_section_rule_push(cs, rule_p, cd->item.filename, cd->item.lineno); (void) rule_p->func(ctx, NULL, NULL, cf_section_to_item(cs), rule_p); return cs; } } } } /* * Call any ON_READ callback. And push this rule * to the child section, so that the child can * pick it up. */ cd = cf_data_find(CF_TO_ITEM(parent), CONF_PARSER, name1); if (cd) { rule = cf_data_value(cd); if (rule->func && (FR_BASE_TYPE(rule->type) == FR_TYPE_SUBSECTION) && ((rule->type & FR_TYPE_ON_READ) != 0)) { (void) cf_section_rules_push(cs, rule); (void) rule->func(ctx, NULL, NULL, cf_section_to_item(cs), rule); } } } return cs; }