/* * Check dependencies for an object */ static bool ucl_schema_validate_dependencies (const ucl_object_t *deps, const ucl_object_t *obj, struct ucl_schema_error *err, const ucl_object_t *root) { const ucl_object_t *elt, *cur, *cur_dep; ucl_object_iter_t iter = NULL, piter; bool ret = true; while (ret && (cur = ucl_iterate_object (deps, &iter, true)) != NULL) { elt = ucl_object_find_key (obj, ucl_object_key (cur)); if (elt != NULL) { /* Need to check dependencies */ if (cur->type == UCL_ARRAY) { piter = NULL; while (ret && (cur_dep = ucl_iterate_object (cur, &piter, true)) != NULL) { if (ucl_object_find_key (obj, ucl_object_tostring (cur_dep)) == NULL) { ucl_schema_create_error (err, UCL_SCHEMA_MISSING_DEPENDENCY, elt, "dependency %s is missing for key %s", ucl_object_tostring (cur_dep), ucl_object_key (cur)); ret = false; break; } } } else if (cur->type == UCL_OBJECT) { ret = ucl_schema_validate (cur, obj, true, err, root); } } } return ret; }
static bool ucl_schema_validate_string (const ucl_object_t *schema, const ucl_object_t *obj, struct ucl_schema_error *err) { const ucl_object_t *elt; ucl_object_iter_t iter = NULL; bool ret = true; int64_t constraint; #ifdef HAVE_REGEX_H regex_t re; #endif while (ret && (elt = ucl_iterate_object (schema, &iter, true)) != NULL) { if (elt->type == UCL_INT && strcmp (ucl_object_key (elt), "maxLength") == 0) { constraint = ucl_object_toint (elt); if (obj->len > constraint) { ucl_schema_create_error (err, UCL_SCHEMA_CONSTRAINT, obj, "string is too big: %.3f, maximum is: %.3f", obj->len, constraint); ret = false; break; } } else if (elt->type == UCL_INT && strcmp (ucl_object_key (elt), "minLength") == 0) { constraint = ucl_object_toint (elt); if (obj->len < constraint) { ucl_schema_create_error (err, UCL_SCHEMA_CONSTRAINT, obj, "string is too short: %.3f, minimum is: %.3f", obj->len, constraint); ret = false; break; } } #ifdef HAVE_REGEX_H else if (elt->type == UCL_STRING && strcmp (ucl_object_key (elt), "pattern") == 0) { if (regcomp (&re, ucl_object_tostring (elt), REG_EXTENDED | REG_NOSUB) != 0) { ucl_schema_create_error (err, UCL_SCHEMA_INVALID_SCHEMA, elt, "cannot compile pattern %s", ucl_object_tostring (elt)); ret = false; break; } if (regexec (&re, ucl_object_tostring (obj), 0, NULL, 0) != 0) { ucl_schema_create_error (err, UCL_SCHEMA_CONSTRAINT, obj, "string doesn't match regexp %s", ucl_object_tostring (elt)); ret = false; } regfree (&re); } #endif } return ret; }
static PyObject * _iterate_valid_ucl (ucl_object_t const *obj) { const ucl_object_t *tmp; ucl_object_iter_t it = NULL; tmp = obj; while ((obj = ucl_object_iterate (tmp, &it, false))) { PyObject *val; val = _basic_ucl_type(obj); if (!val) { PyObject *key = NULL; if (obj->key != NULL) { key = Py_BuildValue("s", ucl_object_key(obj)); } if (obj->type == UCL_OBJECT) { const ucl_object_t *cur; ucl_object_iter_t it_obj = NULL; val = PyDict_New(); while ((cur = ucl_object_iterate (obj, &it_obj, true))) { PyObject *keyobj = Py_BuildValue("s",ucl_object_key(cur)); PyDict_SetItem(val, keyobj, _iterate_valid_ucl(cur)); } } else if (obj->type == UCL_ARRAY) { const ucl_object_t *cur; ucl_object_iter_t it_obj = NULL; val = PyList_New(0); while ((cur = ucl_object_iterate (obj, &it_obj, true))) { PyList_Append(val, _iterate_valid_ucl(cur)); } } else if (obj->type == UCL_USERDATA) { // XXX: this should be // PyBytes_FromStringAndSize; where is the // length from? val = PyBytes_FromString(obj->value.ud); } } return val; } PyErr_SetString(PyExc_SystemError, "unhandled type"); return NULL; }
/** * Push a single object to lua * @param L * @param obj * @return */ static int ucl_object_lua_push_object (lua_State *L, const ucl_object_t *obj, bool allow_array) { const ucl_object_t *cur; ucl_object_iter_t it = NULL; int nelt = 0; if (allow_array && obj->next != NULL) { /* Actually we need to push this as an array */ return ucl_object_lua_push_array (L, obj); } /* Optimize allocation by preallocation of table */ while (ucl_iterate_object (obj, &it, true) != NULL) { nelt ++; } lua_createtable (L, 0, nelt); it = NULL; while ((cur = ucl_iterate_object (obj, &it, true)) != NULL) { ucl_object_lua_push_element (L, ucl_object_key (cur), cur); } return 1; }
static int pkg_set_files_from_object(struct pkg *pkg, ucl_object_t *obj) { ucl_object_t *cur; ucl_object_iter_t it = NULL; const char *sum = NULL; const char *uname = NULL; const char *gname = NULL; void *set = NULL; mode_t perm = 0; struct sbuf *fname = NULL; const char *key, *okey; okey = ucl_object_key(obj); if (okey == NULL) return (EPKG_FATAL); urldecode(okey, &fname); while ((cur = ucl_iterate_object(obj, &it, true))) { key = ucl_object_key(cur); if (key == NULL) continue; if (!strcasecmp(key, "uname") && cur->type == UCL_STRING) uname = ucl_object_tostring(cur); else if (!strcasecmp(key, "gname") && cur->type == UCL_STRING) gname = ucl_object_tostring(cur); else if (!strcasecmp(key, "sum") && cur->type == UCL_STRING && strlen(ucl_object_tostring(cur)) == 64) sum = ucl_object_tostring(cur); else if (!strcasecmp(key, "perm") && (cur->type == UCL_STRING || cur->type == UCL_INT)) { if ((set = setmode(ucl_object_tostring_forced(cur))) == NULL) pkg_emit_error("Not a valid mode: %s", ucl_object_tostring(cur)); else perm = getmode(set, 0); } else { pkg_emit_error("Skipping unknown key for file(%s): %s", sbuf_data(fname), ucl_object_tostring(cur)); } } pkg_addfile_attr(pkg, sbuf_data(fname), sum, uname, gname, perm, false); sbuf_delete(fname); return (EPKG_OK); }
const char * pkg_object_key(const pkg_object *o) { if (o == NULL) return (NULL); return (ucl_object_key(o)); }
static void parse_flags (struct fuzzy_rule *rule, struct rspamd_config *cfg, const ucl_object_t *val, gint cb_id) { const ucl_object_t *elt; struct fuzzy_mapping *map; const gchar *sym = NULL; if (val->type == UCL_STRING) { msg_err_config ( "string mappings are deprecated and no longer supported, use new style configuration"); } else if (val->type == UCL_OBJECT) { elt = ucl_object_find_key (val, "symbol"); if (elt == NULL || !ucl_object_tostring_safe (elt, &sym)) { sym = ucl_object_key (val); } if (sym != NULL) { map = rspamd_mempool_alloc (fuzzy_module_ctx->fuzzy_pool, sizeof (struct fuzzy_mapping)); map->symbol = sym; elt = ucl_object_find_key (val, "flag"); if (elt != NULL && ucl_obj_toint_safe (elt, &map->fuzzy_flag)) { elt = ucl_object_find_key (val, "max_score"); if (elt != NULL) { map->weight = ucl_obj_todouble (elt); } else { map->weight = rule->max_score; } /* Add flag to hash table */ g_hash_table_insert (rule->mappings, GINT_TO_POINTER (map->fuzzy_flag), map); rspamd_symbols_cache_add_symbol (cfg->cache, map->symbol, 0, NULL, NULL, SYMBOL_TYPE_VIRTUAL|SYMBOL_TYPE_FINE, cb_id); } else { msg_err_config ("fuzzy_map parameter has no flag definition"); } } else { msg_err_config ("fuzzy_map parameter has no symbol definition"); } } else { msg_err_config ("fuzzy_map parameter is of an unsupported type"); } }
static int pkg_set_dirs_from_object(struct pkg *pkg, ucl_object_t *obj) { ucl_object_t *cur; ucl_object_iter_t it = NULL; const char *uname = NULL; const char *gname = NULL; void *set; mode_t perm = 0; bool try = false; struct sbuf *dirname = NULL; const char *key, *okey; okey = ucl_object_key(obj); if (okey == NULL) return (EPKG_FATAL); urldecode(okey, &dirname); while ((cur = ucl_iterate_object(obj, &it, true))) { key = ucl_object_key(cur); if (key == NULL) continue; if (!strcasecmp(key, "uname") && cur->type == UCL_STRING) uname = ucl_object_tostring(cur); else if (!strcasecmp(key, "gname") && cur->type == UCL_STRING) gname = ucl_object_tostring(cur); else if (!strcasecmp(key, "perm") && (cur->type == UCL_STRING || cur->type == UCL_INT)) { if ((set = setmode(ucl_object_tostring_forced(cur))) == NULL) pkg_emit_error("Not a valid mode: %s", ucl_object_tostring(cur)); else perm = getmode(set, 0); } else if (!strcasecmp(key, "try") && cur->type == UCL_BOOLEAN) { try = ucl_object_toint(cur); } else { pkg_emit_error("Skipping unknown key for dir(%s): %s", sbuf_data(dirname), key); } }
void parse_conf(jail_conf_t *jail_conf, uint8_t *buf, size_t len) { struct ucl_parser *parser = ucl_parser_new(UCL_PARSER_NO_TIME); ucl_parser_add_chunk(parser, buf, len); if (ucl_parser_get_error(parser)) die("Config: Could not parse"); // TODO: output the error ucl_object_t *root = ucl_parser_get_object(parser); jail_conf->hostname = NULL; jail_conf->jailname = NULL; jail_conf->net_iface = NULL; jail_conf->script = NULL; jail_conf->securelevel = 3; jail_conf->devfs_ruleset = 4; bzero(jail_conf->ipv4, sizeof(jail_conf->ipv4)); bzero(jail_conf->ipv6, sizeof(jail_conf->ipv6)); bzero(jail_conf->limits, sizeof(jail_conf->limits)); bzero(jail_conf->mounts, sizeof(jail_conf->mounts)); ucl_iterate(root, true, ^(ucl_object_t *cur) { char *key = ucl_object_key(cur); if (strcmp(key, "hostname") == 0) { STR_TO_ARENA(jail_conf->hostname, ucl_object_tostring_forced(cur)); } else if (strcmp(key, "jailname") == 0) { STR_TO_ARENA(jail_conf->jailname, ucl_object_tostring_forced(cur)); } else if (strcmp(key, "script") == 0) { STR_TO_ARENA(jail_conf->script, ucl_object_tostring_forced(cur)); } else if (strcmp(key, "net_iface") == 0) { STR_TO_ARENA(jail_conf->net_iface, ucl_object_tostring_forced(cur)); } else if (strcmp(key, "securelevel") == 0) { int64_t int_val = -1; if (ucl_object_toint_safe(cur, &int_val) != true) die("Config: securelevel is not a number"); jail_conf->securelevel = (int8_t)int_val; } else if (strcmp(key, "devfs_ruleset") == 0) { int64_t int_val = -1; if (ucl_object_toint_safe(cur, &int_val) != true) die("Config: devfs_ruleset is not a number"); jail_conf->devfs_ruleset = (int16_t)int_val; } else if (strcmp(key, "ipv4") == 0) { __block size_t i = 0; ucl_iterate(cur, false, ^(ucl_object_t *val) { if (i > IPV4_ADDRS_LEN) die("Config: Too many IPv4 addresses"); STR_TO_ARENA(jail_conf->ipv4[i], ucl_object_tostring_forced(val)); i++; });
/*- * Parse new repo style configs in style: * Name: * URL: * MIRROR_TYPE: * etc... */ static void parse_repo_file(ucl_object_t *obj) { ucl_object_iter_t it = NULL; const ucl_object_t *cur; const char *key; while ((cur = ucl_iterate_object(obj, &it, true))) { key = ucl_object_key(cur); if (key == NULL) continue; if (cur->type != UCL_OBJECT) continue; config_parse(cur, CONFFILE_REPO); } }
static void walk_repo_obj(const ucl_object_t *obj, const char *file, pkg_init_flags flags) { const ucl_object_t *cur; ucl_object_iter_t it = NULL; struct pkg_repo *r; const char *key; while ((cur = ucl_iterate_object(obj, &it, true))) { key = ucl_object_key(cur); pkg_debug(1, "PkgConfig: parsing key '%s'", key); r = pkg_repo_find(key); if (r != NULL) pkg_debug(1, "PkgConfig: overwriting repository %s", key); if (cur->type == UCL_OBJECT) add_repo(cur, r, key, flags); else pkg_emit_error("Ignoring bad configuration entry in %s: %s", file, ucl_object_emit(cur, UCL_EMIT_YAML)); } }
/* * Check whether we have a pattern specified */ static const ucl_object_t * ucl_schema_test_pattern (const ucl_object_t *obj, const char *pattern) { const ucl_object_t *res = NULL; #ifdef HAVE_REGEX_H regex_t reg; const ucl_object_t *elt; ucl_object_iter_t iter = NULL; if (regcomp (®, pattern, REG_EXTENDED | REG_NOSUB) == 0) { while ((elt = ucl_iterate_object (obj, &iter, true)) != NULL) { if (regexec (®, ucl_object_key (elt), 0, NULL, 0) == 0) { res = elt; break; } } regfree (®); } #endif return res; }
static bool conf_helper_mapper(struct rtpp_log *log, const ucl_object_t *obj, const conf_helper_map *map, void *target, const conf_helper_map **fentrpp) { ucl_object_iter_t it; const ucl_object_t *cur; const char *key = NULL; int i; bool ret = true, found = false; it = ucl_object_iterate_new(obj); if (it == NULL) return (false); while ((cur = ucl_object_iterate_safe(it, true)) != NULL && ret) { key = ucl_object_key(cur); found = false; for (i = 0; map[i].conf_key; i++) { if (strcasecmp(map[i].conf_key, key) != 0) continue; found = true; if (map[i].callback != NULL) { ret = map[i].callback(log, obj, cur, target); if (!ret && fentrpp != NULL) *fentrpp = &map[i]; } break; } if (!found && map[i].callback != NULL) { /* Call default handler if there is one */ ret = map[i].callback(log, obj, cur, target); if (!ret && fentrpp != NULL) *fentrpp = &map[i]; } } if (cur == NULL && ucl_object_iter_chk_excpn(it)) ret = false; ucl_object_iterate_free(it); return (ret); }
/* * expand extrapolates one or more environment variables from obj. If obj * is of type UCL_OBJECT or UCL_ARRAY then a new variable will be created * will be created containing a list of keys in obj and then expand will be * called recursively for each member. Otherwise a new environment variable * will be created with the value of obj. */ static void expand(size_t keylen, ucl_object_t const *obj) { ucl_object_iter_t it = NULL; ucl_object_t const *o; int i, l; switch (ucl_object_type(obj)) { case UCL_OBJECT: if (snprintkeys(envval, MAX_VALUE_LEN, obj) >= MAX_VALUE_LEN) errx(EX_DATAERR, "value too long \"%s\"", envval); setenv(envkey, envval, 1); while ((o = ucl_iterate_object(obj, &it, true)) != NULL) { l = snprintf(envkey + keylen, MAX_KEY_LEN - keylen, "_%s", ucl_object_key(o)); if (l >= MAX_KEY_LEN - keylen) errx(EX_DATAERR, "key too long \"%s\"", envkey); expand(keylen + l, o); } break; case UCL_ARRAY: if (snprintkeys(envval, MAX_VALUE_LEN, obj) >= MAX_VALUE_LEN) errx(EX_DATAERR, "value too long \"%s\"", envval); setenv(envkey, envval, 1); i = 0; while ((o = ucl_iterate_object(obj, &it, true)) != NULL) { l = snprintf(envkey + keylen, MAX_KEY_LEN - keylen, "_%d", i++); if (l > MAX_KEY_LEN - keylen) errx(EX_DATAERR, "key too long \"%s\"", envkey); expand(keylen + l, o); } break; default: if (snprintval(envval, MAX_VALUE_LEN, obj) >= MAX_VALUE_LEN) errx(EX_DATAERR, "value too long \"%s\"", envval); setenv(envkey, envval, 1); break; } }
static gint lua_config_get_all_opt (lua_State * L) { struct rspamd_config *cfg = lua_check_config (L, 1); const gchar *mname; const ucl_object_t *obj, *cur, *cur_elt; ucl_object_iter_t it = NULL; gint i; if (cfg) { mname = luaL_checkstring (L, 2); if (mname) { obj = ucl_obj_get_key (cfg->rcl_obj, mname); /* Flatten object */ if (obj != NULL && (ucl_object_type (obj) == UCL_OBJECT || ucl_object_type (obj) == UCL_ARRAY)) { lua_newtable (L); it = ucl_object_iterate_new (obj); LL_FOREACH (obj, cur) { it = ucl_object_iterate_reset (it, cur); while ((cur_elt = ucl_object_iterate_safe (it, true))) { lua_pushstring (L, ucl_object_key (cur_elt)); ucl_object_push_lua (L, cur_elt, true); lua_settable (L, -3); } } ucl_object_iterate_free (it); return 1; } else if (obj != NULL) {
/* * snprintkeys writes the keys contained in obj to dst. */ static int snprintkeys(char *dst, size_t size, ucl_object_t const *obj) { ucl_object_iter_t it = NULL; ucl_object_t const *o; int n = 0; int i = 0; switch (ucl_object_type(obj)) { case UCL_OBJECT: for (i = 0; (o = ucl_iterate_object(obj, &it, true)) != NULL; i++) { int l; l = snprintf(dst + n, (size - n > 0) ? size - n: 0, "%s%s", (i == 0)?"":"\n", ucl_object_key(o)); if (l < 0) return l; n += l; } break; case UCL_ARRAY: { for (i = 0; (o = ucl_iterate_object(obj, &it, true)) != NULL; i++) { int l; l = snprintf(dst + n, (size - n > 0) ? size - n: 0, "%s%d", (i == 0)?"":"\n", i); if (l < 0) return l; n += l; } break; } default: *dst = '\0'; break; } return n; }
bool merge_recursive(ucl_object_t *top, ucl_object_t *elt, bool copy) { const ucl_object_t *cur; ucl_object_iter_t it = NULL; ucl_object_t *found = NULL, *cp_obj = NULL; bool success = false; it = ucl_object_iterate_new(elt); while ((cur = ucl_object_iterate_safe(it, false))) { cp_obj = ucl_object_ref(cur); if (debug > 0) { fprintf(stderr, "DEBUG: Looping over (elt)%s, found key: %s\n", ucl_object_key(top), ucl_object_key(cur)); } if (ucl_object_type(cur) == UCL_OBJECT) { found = __DECONST(ucl_object_t *, ucl_object_find_key(top, ucl_object_key(cur))); if (found == NULL) { /* new key not found in old object, insert it */ if (debug > 0) { fprintf(stderr, "DEBUG: unmatched key, inserting: %s into top\n", ucl_object_key(cur)); } success = ucl_object_insert_key_merged(top, cp_obj, ucl_object_key(cp_obj), 0, true); if (success == false) { return false; } continue; } if (debug > 0) { fprintf(stderr, "DEBUG: (obj) Found key %s in (top)%s too, merging...\n", ucl_object_key(found), ucl_object_key(top)); } success = merge_recursive(found, cp_obj, copy); if (success == false) { return false; } } else if (ucl_object_type(cur) == UCL_ARRAY) {
int rtpp_cfile_process(struct rtpp_cfg_stable *csp) { struct ucl_parser *parser; ucl_object_t *conf_root; ucl_object_iter_t it_conf; const ucl_object_t *obj_file; const char *cf_key; int fd, ecode; ecode = 0; fd = open(csp->cfile, O_RDONLY); if (fd < 0) { RTPP_ELOG(csp->glog, RTPP_LOG_ERR, "open failed: %s", csp->cfile); ecode = -1; goto e0; } parser = ucl_parser_new(UCL_PARSER_NO_FILEVARS); if (parser == NULL) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "ucl_parser_new() failed"); ecode = -1; goto e1; } ucl_parser_add_fd(parser, fd); conf_root = ucl_parser_get_object(parser); if (conf_root == NULL) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "ucl_parser_get_object() failed"); ecode = -1; goto e2; } if (ucl_parser_get_error(parser)) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "Parse Error occured: %s", ucl_parser_get_error(parser)); ecode = -1; goto e3; } it_conf = ucl_object_iterate_new(conf_root); if (it_conf == NULL) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "ucl_object_iterate_new() failed"); ecode = -1; goto e3; } while ((obj_file = ucl_object_iterate_safe(it_conf, true)) != NULL) { cf_key = ucl_object_key(obj_file); RTPP_LOG(csp->glog, RTPP_LOG_DBUG, "Entry: %s", cf_key); if (strcasecmp(cf_key, "modules") == 0) { if (parse_modules(csp, obj_file) < 0) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "parse_modules() failed"); ecode = -1; goto e4; } } } if (ucl_object_iter_chk_excpn(it_conf)) { ecode = -1; } e4: ucl_object_iterate_free(it_conf); e3: ucl_object_unref(conf_root); e2: ucl_parser_free(parser); e1: close(fd); e0: return (ecode); }
static void add_repo(const ucl_object_t *obj, struct pkg_repo *r, const char *rname, pkg_init_flags flags) { const ucl_object_t *cur, *enabled; ucl_object_iter_t it = NULL; bool enable = true; const char *url = NULL, *pubkey = NULL, *mirror_type = NULL; const char *signature_type = NULL, *fingerprints = NULL; const char *key; const char *type = NULL; int use_ipvx = 0; pkg_debug(1, "PkgConfig: parsing repository object %s", rname); enabled = ucl_object_find_key(obj, "enabled"); if (enabled == NULL) enabled = ucl_object_find_key(obj, "ENABLED"); if (enabled != NULL) { enable = ucl_object_toboolean(enabled); if (!enable && r == NULL) { pkg_debug(1, "PkgConfig: skipping disabled repo %s", rname); return; } else if (!enable && r != NULL) { /* * We basically want to remove the existing repo r and * forget all stuff parsed */ pkg_debug(1, "PkgConfig: disabling repo %s", rname); HASH_DEL(repos, r); pkg_repo_free(r); return; } } while ((cur = ucl_iterate_object(obj, &it, true))) { key = ucl_object_key(cur); if (key == NULL) continue; if (strcasecmp(key, "url") == 0) { if (cur->type != UCL_STRING) { pkg_emit_error("Expecting a string for the " "'%s' key of the '%s' repo", key, rname); return; } url = ucl_object_tostring(cur); } else if (strcasecmp(key, "pubkey") == 0) { if (cur->type != UCL_STRING) { pkg_emit_error("Expecting a string for the " "'%s' key of the '%s' repo", key, rname); return; } pubkey = ucl_object_tostring(cur); } else if (strcasecmp(key, "mirror_type") == 0) { if (cur->type != UCL_STRING) { pkg_emit_error("Expecting a string for the " "'%s' key of the '%s' repo", key, rname); return; } mirror_type = ucl_object_tostring(cur); } else if (strcasecmp(key, "signature_type") == 0) { if (cur->type != UCL_STRING) { pkg_emit_error("Expecting a string for the " "'%s' key of the '%s' repo", key, rname); return; } signature_type = ucl_object_tostring(cur); } else if (strcasecmp(key, "fingerprints") == 0) { if (cur->type != UCL_STRING) { pkg_emit_error("Expecting a string for the " "'%s' key of the '%s' repo", key, rname); return; } fingerprints = ucl_object_tostring(cur); } else if (strcasecmp(key, "type") == 0) { if (cur->type != UCL_STRING) { pkg_emit_error("Expecting a string for the " "'%s' key of the '%s' repo", key, rname); return; } type = ucl_object_tostring(cur); } else if (strcasecmp(key, "ip_version") == 0) { if (cur->type != UCL_INT) { pkg_emit_error("Expecting a integer for the " "'%s' key of the '%s' repo", key, rname); return; } use_ipvx = ucl_object_toint(cur); if (use_ipvx != 4 && use_ipvx != 6) use_ipvx = 0; } } if (r == NULL && url == NULL) { pkg_debug(1, "No repo and no url for %s", rname); return; } if (r == NULL) r = pkg_repo_new(rname, url, type); else pkg_repo_overwrite(r, rname, url, type); if (signature_type != NULL) { if (strcasecmp(signature_type, "pubkey") == 0) r->signature_type = SIG_PUBKEY; else if (strcasecmp(signature_type, "fingerprints") == 0) r->signature_type = SIG_FINGERPRINT; else r->signature_type = SIG_NONE; } if (fingerprints != NULL) { free(r->fingerprints); r->fingerprints = strdup(fingerprints); } if (pubkey != NULL) { free(r->pubkey); r->pubkey = strdup(pubkey); } r->enable = enable; if (mirror_type != NULL) { if (strcasecmp(mirror_type, "srv") == 0) r->mirror_type = SRV; else if (strcasecmp(mirror_type, "http") == 0) r->mirror_type = HTTP; else r->mirror_type = NOMIRROR; } if ((flags & PKG_INIT_FLAG_USE_IPV4) == PKG_INIT_FLAG_USE_IPV4) use_ipvx = 4; else if ((flags & PKG_INIT_FLAG_USE_IPV6) == PKG_INIT_FLAG_USE_IPV6) use_ipvx = 6; if (use_ipvx != 4 && use_ipvx != 6) use_ipvx = pkg_object_int(pkg_config_get("IP_VERSION")); if (use_ipvx == 4) r->flags = REPO_FLAGS_USE_IPV4; else if (use_ipvx == 6) r->flags = REPO_FLAGS_USE_IPV6; }
static int parse_modules(struct rtpp_cfg_stable *csp, const ucl_object_t *wop) { ucl_object_iter_t it_conf; const ucl_object_t *obj_file; const char *cf_key; const ucl_object_t *obj_key; int ecode, success; void *confp; const conf_helper_map *fent, *map; struct rtpp_module_conf *mcp; char mpath[PATH_MAX + 1]; const char *cp, *mp; struct rtpp_module_if *mif; it_conf = ucl_object_iterate_new(wop); if (it_conf == NULL) return (-1); ecode = 0; while ((obj_file = ucl_object_iterate_safe(it_conf, true)) != NULL) { cf_key = ucl_object_key(obj_file); RTPP_LOG(csp->glog, RTPP_LOG_DBUG, "\tmodule: %s", cf_key); obj_key = ucl_object_find_key(obj_file, "load"); if (obj_key == NULL) { cp = rtpp_module_dsop_canonic(cf_key, mpath, sizeof(mpath)); if (cp == NULL) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "Error: Unable to find load parameter in module: %s", cf_key); ecode = -1; goto e0; } } else { if (obj_key->type != UCL_STRING) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "Error: \"load\" parameter in %s has a wrong type, string is expected", cf_key); ecode = -1; goto e0; } mp = ucl_object_tostring(obj_key); cp = realpath(mp, mpath); if (cp == NULL) { RTPP_ELOG(csp->glog, RTPP_LOG_ERR, "realpath() failed: %s", mp); ecode = -1; goto e0; } } mif = rtpp_module_if_ctor(cp); if (mif == NULL) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "dymanic module constructor has failed: %s", cp); ecode = -1; goto e0; } if (CALL_METHOD(mif, load, csp, csp->glog) != 0) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "%p->load() method has failed: %s", mif, cp); goto e1; } if (CALL_METHOD(mif, get_mconf, &mcp) < 0) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "%p->get_mconf() method has failed: %s", mif, cp); goto e1; } fent = NULL; if (mcp != NULL) { map = mcp->conf_map; confp = mcp->conf_data; } else { map = default_module_map; confp = NULL; } success = conf_helper_mapper(csp->glog, obj_file, map, confp, &fent); if (!success) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "Config parsing issue in section %s", cf_key); if (fent != NULL && fent->conf_key != NULL) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "\tparameter %s", fent->conf_key); } goto e1; } if (CALL_METHOD(mif, config) < 0) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "%p->config() method has failed: %s", mif, cp); goto e1; } rtpp_list_append(csp->modules_cf, mif); continue; e1: ecode = -1; CALL_SMETHOD(mif->rcnt, decref); goto e0; } e0: if (ucl_object_iter_chk_excpn(it_conf)) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "UCL has failed with an internal error"); ecode = -1; } ucl_object_iterate_free(it_conf); return (ecode); }
/* * Validate object */ static bool ucl_schema_validate_object (const ucl_object_t *schema, const ucl_object_t *obj, struct ucl_schema_error *err, const ucl_object_t *root) { const ucl_object_t *elt, *prop, *found, *additional_schema = NULL, *required = NULL, *pat, *pelt; ucl_object_iter_t iter = NULL, piter = NULL; bool ret = true, allow_additional = true; int64_t minmax; while (ret && (elt = ucl_iterate_object (schema, &iter, true)) != NULL) { if (elt->type == UCL_OBJECT && strcmp (ucl_object_key (elt), "properties") == 0) { piter = NULL; while (ret && (prop = ucl_iterate_object (elt, &piter, true)) != NULL) { found = ucl_object_find_key (obj, ucl_object_key (prop)); if (found) { ret = ucl_schema_validate (prop, found, true, err, root); } } } else if (strcmp (ucl_object_key (elt), "additionalProperties") == 0) { if (elt->type == UCL_BOOLEAN) { if (!ucl_object_toboolean (elt)) { /* Deny additional fields completely */ allow_additional = false; } } else if (elt->type == UCL_OBJECT) { /* Define validator for additional fields */ additional_schema = elt; } else { ucl_schema_create_error (err, UCL_SCHEMA_INVALID_SCHEMA, elt, "additionalProperties attribute is invalid in schema"); ret = false; break; } } else if (strcmp (ucl_object_key (elt), "required") == 0) { if (elt->type == UCL_ARRAY) { required = elt; } else { ucl_schema_create_error (err, UCL_SCHEMA_INVALID_SCHEMA, elt, "required attribute is invalid in schema"); ret = false; break; } } else if (strcmp (ucl_object_key (elt), "minProperties") == 0 && ucl_object_toint_safe (elt, &minmax)) { if (obj->len < minmax) { ucl_schema_create_error (err, UCL_SCHEMA_CONSTRAINT, obj, "object has not enough properties: %u, minimum is: %u", obj->len, (unsigned)minmax); ret = false; break; } } else if (strcmp (ucl_object_key (elt), "maxProperties") == 0 && ucl_object_toint_safe (elt, &minmax)) { if (obj->len > minmax) { ucl_schema_create_error (err, UCL_SCHEMA_CONSTRAINT, obj, "object has too many properties: %u, maximum is: %u", obj->len, (unsigned)minmax); ret = false; break; } } else if (strcmp (ucl_object_key (elt), "patternProperties") == 0) { piter = NULL; while (ret && (prop = ucl_iterate_object (elt, &piter, true)) != NULL) { found = ucl_schema_test_pattern (obj, ucl_object_key (prop)); if (found) { ret = ucl_schema_validate (prop, found, true, err, root); } } } else if (elt->type == UCL_OBJECT && strcmp (ucl_object_key (elt), "dependencies") == 0) { ret = ucl_schema_validate_dependencies (elt, obj, err, root); } } if (ret) { /* Additional properties */ if (!allow_additional || additional_schema != NULL) { /* Check if we have exactly the same properties in schema and object */ iter = NULL; prop = ucl_object_find_key (schema, "properties"); while ((elt = ucl_iterate_object (obj, &iter, true)) != NULL) { found = ucl_object_find_key (prop, ucl_object_key (elt)); if (found == NULL) { /* Try patternProperties */ piter = NULL; pat = ucl_object_find_key (schema, "patternProperties"); while ((pelt = ucl_iterate_object (pat, &piter, true)) != NULL) { found = ucl_schema_test_pattern (obj, ucl_object_key (pelt)); if (found != NULL) { break; } } } if (found == NULL) { if (!allow_additional) { ucl_schema_create_error (err, UCL_SCHEMA_CONSTRAINT, obj, "object has non-allowed property %s", ucl_object_key (elt)); ret = false; break; } else if (additional_schema != NULL) { if (!ucl_schema_validate (additional_schema, elt, true, err, root)) { ret = false; break; } } } } } /* Required properties */ if (required != NULL) { iter = NULL; while ((elt = ucl_iterate_object (required, &iter, true)) != NULL) { if (ucl_object_find_key (obj, ucl_object_tostring (elt)) == NULL) { ucl_schema_create_error (err, UCL_SCHEMA_MISSING_PROPERTY, obj, "object has missing property %s", ucl_object_tostring (elt)); ret = false; break; } } } } return ret; }
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include <inttypes.h> #include <stdbool.h> #include "config.h" #include "rtpp_types.h" #include "rtpp_log.h" #include "rtpp_log_obj.h" #include "rtpp_ucl.h" #include "ucl.h" bool rtpp_ucl_set_unknown(struct rtpp_log *log, const ucl_object_t *top, const ucl_object_t *obj, void *target __attribute__((unused))) { RTPP_LOG(log, RTPP_LOG_ERR, "Unknown key '%s' in section '%s'", ucl_object_key(obj), ucl_object_key(top)); return (false); }
void ucl_obj_dump (const ucl_object_t *obj, unsigned int shift) { int num = shift * 4 + 5; char *pre = (char *) malloc (num * sizeof(char)); const ucl_object_t *cur, *tmp; ucl_object_iter_t it = NULL, it_obj = NULL; pre[--num] = 0x00; while (num--) pre[num] = 0x20; tmp = obj; while ((obj = ucl_iterate_object (tmp, &it, false))) { printf ("%sucl object address: %p\n", pre + 4, obj); if (obj->key != NULL) { printf ("%skey: \"%s\"\n", pre, ucl_object_key (obj)); } printf ("%sref: %u\n", pre, obj->ref); printf ("%slen: %u\n", pre, obj->len); printf ("%sprev: %p\n", pre, obj->prev); printf ("%snext: %p\n", pre, obj->next); if (obj->type == UCL_OBJECT) { printf ("%stype: UCL_OBJECT\n", pre); printf ("%svalue: %p\n", pre, obj->value.ov); it_obj = NULL; while ((cur = ucl_iterate_object (obj, &it_obj, true))) { ucl_obj_dump (cur, shift + 2); } } else if (obj->type == UCL_ARRAY) { printf ("%stype: UCL_ARRAY\n", pre); printf ("%svalue: %p\n", pre, obj->value.av); it_obj = NULL; while ((cur = ucl_iterate_object (obj, &it_obj, true))) { ucl_obj_dump (cur, shift + 2); } } else if (obj->type == UCL_INT) { printf ("%stype: UCL_INT\n", pre); printf ("%svalue: %jd\n", pre, (intmax_t)ucl_object_toint (obj)); } else if (obj->type == UCL_FLOAT) { printf ("%stype: UCL_FLOAT\n", pre); printf ("%svalue: %f\n", pre, ucl_object_todouble (obj)); } else if (obj->type == UCL_STRING) { printf ("%stype: UCL_STRING\n", pre); printf ("%svalue: \"%s\"\n", pre, ucl_object_tostring (obj)); } else if (obj->type == UCL_BOOLEAN) { printf ("%stype: UCL_BOOLEAN\n", pre); printf ("%svalue: %s\n", pre, ucl_object_tostring_forced (obj)); } else if (obj->type == UCL_TIME) { printf ("%stype: UCL_TIME\n", pre); printf ("%svalue: %f\n", pre, ucl_object_todouble (obj)); } else if (obj->type == UCL_USERDATA) { printf ("%stype: UCL_USERDATA\n", pre); printf ("%svalue: %p\n", pre, obj->value.ud); } } free (pre); }
static bool ucl_schema_validate_number (const ucl_object_t *schema, const ucl_object_t *obj, struct ucl_schema_error *err) { const ucl_object_t *elt, *test; ucl_object_iter_t iter = NULL; bool ret = true, exclusive = false; double constraint, val; const double alpha = 1e-16; while (ret && (elt = ucl_iterate_object (schema, &iter, true)) != NULL) { if ((elt->type == UCL_FLOAT || elt->type == UCL_INT) && strcmp (ucl_object_key (elt), "multipleOf") == 0) { constraint = ucl_object_todouble (elt); if (constraint <= 0) { ucl_schema_create_error (err, UCL_SCHEMA_INVALID_SCHEMA, elt, "multipleOf must be greater than zero"); ret = false; break; } val = ucl_object_todouble (obj); if (fabs (remainder (val, constraint)) > alpha) { ucl_schema_create_error (err, UCL_SCHEMA_CONSTRAINT, obj, "number %.4f is not multiple of %.4f, remainder is %.7f", val, constraint); ret = false; break; } } else if ((elt->type == UCL_FLOAT || elt->type == UCL_INT) && strcmp (ucl_object_key (elt), "maximum") == 0) { constraint = ucl_object_todouble (elt); test = ucl_object_find_key (schema, "exclusiveMaximum"); if (test && test->type == UCL_BOOLEAN) { exclusive = ucl_object_toboolean (test); } val = ucl_object_todouble (obj); if (val > constraint || (exclusive && val >= constraint)) { ucl_schema_create_error (err, UCL_SCHEMA_CONSTRAINT, obj, "number is too big: %.3f, maximum is: %.3f", val, constraint); ret = false; break; } } else if ((elt->type == UCL_FLOAT || elt->type == UCL_INT) && strcmp (ucl_object_key (elt), "minimum") == 0) { constraint = ucl_object_todouble (elt); test = ucl_object_find_key (schema, "exclusiveMinimum"); if (test && test->type == UCL_BOOLEAN) { exclusive = ucl_object_toboolean (test); } val = ucl_object_todouble (obj); if (val < constraint || (exclusive && val <= constraint)) { ucl_schema_create_error (err, UCL_SCHEMA_CONSTRAINT, obj, "number is too small: %.3f, minimum is: %.3f", val, constraint); ret = false; break; } } } return ret; }
static gboolean rspamd_symbols_cache_load_items (struct symbols_cache *cache, const gchar *name) { struct rspamd_symbols_cache_header *hdr; struct stat st; struct ucl_parser *parser; ucl_object_t *top; const ucl_object_t *cur, *elt; ucl_object_iter_t it; struct cache_item *item, *parent; const guchar *p; gint fd; gpointer map; double w; fd = open (name, O_RDONLY); if (fd == -1) { msg_info ("cannot open file %s, error %d, %s", name, errno, strerror (errno)); return FALSE; } if (fstat (fd, &st) == -1) { close (fd); msg_info ("cannot stat file %s, error %d, %s", name, errno, strerror (errno)); return FALSE; } if (st.st_size < (gint)sizeof (*hdr)) { close (fd); errno = EINVAL; msg_info ("cannot use file %s, error %d, %s", name, errno, strerror (errno)); return FALSE; } map = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0); if (map == MAP_FAILED) { close (fd); msg_info ("cannot mmap file %s, error %d, %s", name, errno, strerror (errno)); return FALSE; } close (fd); hdr = map; if (memcmp (hdr->magic, rspamd_symbols_cache_magic, sizeof (rspamd_symbols_cache_magic)) != 0) { msg_info ("cannot use file %s, bad magic", name); munmap (map, st.st_size); return FALSE; } parser = ucl_parser_new (0); p = (const guchar *)(hdr + 1); if (!ucl_parser_add_chunk (parser, p, st.st_size - sizeof (*hdr))) { msg_info ("cannot use file %s, cannot parse: %s", name, ucl_parser_get_error (parser)); munmap (map, st.st_size); ucl_parser_free (parser); return FALSE; } top = ucl_parser_get_object (parser); munmap (map, st.st_size); ucl_parser_free (parser); if (top == NULL || ucl_object_type (top) != UCL_OBJECT) { msg_info ("cannot use file %s, bad object", name); ucl_object_unref (top); return FALSE; } it = ucl_object_iterate_new (top); while ((cur = ucl_object_iterate_safe (it, true))) { item = g_hash_table_lookup (cache->items_by_symbol, ucl_object_key (cur)); if (item) { /* Copy saved info */ elt = ucl_object_find_key (cur, "weight"); if (elt) { w = ucl_object_todouble (elt); if (w != 0) { item->weight = w; } } elt = ucl_object_find_key (cur, "time"); if (elt) { item->avg_time = ucl_object_todouble (elt); } elt = ucl_object_find_key (cur, "count"); if (elt) { item->avg_counter = ucl_object_toint (elt); } elt = ucl_object_find_key (cur, "frequency"); if (elt) { item->frequency = ucl_object_toint (elt); } if (item->type == SYMBOL_TYPE_VIRTUAL && item->parent != -1) { g_assert (item->parent < (gint)cache->items_by_id->len); parent = g_ptr_array_index (cache->items_by_id, item->parent); if (parent->weight < item->weight) { parent->weight = item->weight; } /* * We maintain avg_time for virtual symbols equal to the * parent item avg_time */ parent->avg_time = item->avg_time; parent->avg_counter = item->avg_counter; } if (fabs (item->weight) > cache->max_weight) { cache->max_weight = fabs (item->weight); } cache->total_freq += item->frequency; } } ucl_object_iterate_free (it); ucl_object_unref (top); return TRUE; }
static int pkg_object(struct pkg *pkg, ucl_object_t *obj, int attr) { struct sbuf *tmp = NULL; ucl_object_t *cur; ucl_object_iter_t it = NULL; pkg_script script_type; const char *key, *buf; size_t len; pkg_debug(3, "%s", "Manifest: parsing object"); while ((cur = ucl_iterate_object(obj, &it, true))) { key = ucl_object_key(cur); if (key == NULL) continue; switch (attr) { case PKG_DEPS: if (cur->type != UCL_OBJECT && cur->type != UCL_ARRAY) pkg_emit_error("Skipping malformed dependency %s", key); else pkg_set_deps_from_object(pkg, cur); break; case PKG_DIRS: if (cur->type != UCL_OBJECT) pkg_emit_error("Skipping malformed dirs %s", key); else pkg_set_dirs_from_object(pkg, cur); break; case PKG_USERS: if (cur->type == UCL_STRING) pkg_adduid(pkg, key, ucl_object_tostring(cur)); else pkg_emit_error("Skipping malformed users %s", key); break; case PKG_GROUPS: if (cur->type == UCL_STRING) pkg_addgid(pkg, key, ucl_object_tostring(cur)); else pkg_emit_error("Skipping malformed groups %s", key); break; case PKG_DIRECTORIES: if (cur->type == UCL_BOOLEAN) { urldecode(key, &tmp); pkg_adddir(pkg, sbuf_data(tmp), ucl_object_toboolean(cur), false); } else if (cur->type == UCL_OBJECT) { pkg_set_dirs_from_object(pkg, cur); } else if (cur->type == UCL_STRING) { urldecode(key, &tmp); if (ucl_object_tostring(cur)[0] == 'y') pkg_adddir(pkg, sbuf_data(tmp), 1, false); else pkg_adddir(pkg, sbuf_data(tmp), 0, false); } else { pkg_emit_error("Skipping malformed directories %s", key); } break; case PKG_FILES: if (cur->type == UCL_STRING) { buf = ucl_object_tolstring(cur, &len); urldecode(key, &tmp); pkg_addfile(pkg, sbuf_get(tmp), len == 64 ? buf : NULL, false); } else if (cur->type == UCL_OBJECT) pkg_set_files_from_object(pkg, cur); else pkg_emit_error("Skipping malformed files %s", key); break; case PKG_OPTIONS: if (cur->type != UCL_STRING && cur->type != UCL_BOOLEAN) pkg_emit_error("Skipping malformed option %s", key); else pkg_addoption(pkg, key, ucl_object_tostring_forced(cur)); break; case PKG_OPTION_DEFAULTS: if (cur->type != UCL_STRING) pkg_emit_error("Skipping malformed option default %s", key); else pkg_addoption_default(pkg, key, ucl_object_tostring(cur)); break; case PKG_OPTION_DESCRIPTIONS: if (cur->type != UCL_STRING) pkg_emit_error("Skipping malformed option description %s", key); else pkg_addoption_description(pkg, key, ucl_object_tostring(cur)); break; case PKG_SCRIPTS: if (cur->type != UCL_STRING) pkg_emit_error("Skipping malformed scripts %s", key); else { script_type = script_type_str(key); if (script_type == PKG_SCRIPT_UNKNOWN) { pkg_emit_error("Skipping unknown script " "type: %s", key); break; } urldecode(ucl_object_tostring(cur), &tmp); pkg_addscript(pkg, sbuf_data(tmp), script_type); } break; case PKG_ANNOTATIONS: if (cur->type != UCL_STRING) pkg_emit_error("Skipping malformed annotation %s", key); else pkg_addannotation(pkg, key, ucl_object_tostring(cur)); break; } } sbuf_free(tmp); return (EPKG_OK); }
gint regexp_module_config (struct rspamd_config *cfg) { struct regexp_module_item *cur_item; const ucl_object_t *sec, *value, *elt; ucl_object_iter_t it = NULL; gint res = TRUE, id; if (!rspamd_config_is_module_enabled (cfg, "regexp")) { return TRUE; } sec = ucl_object_find_key (cfg->rcl_obj, "regexp"); if (sec == NULL) { msg_err_config ("regexp module enabled, but no rules are defined"); return TRUE; } regexp_module_ctx->max_size = 0; while ((value = ucl_iterate_object (sec, &it, true)) != NULL) { if (g_ascii_strncasecmp (ucl_object_key (value), "max_size", sizeof ("max_size") - 1) == 0) { regexp_module_ctx->max_size = ucl_obj_toint (value); rspamd_mime_expression_set_re_limit (regexp_module_ctx->max_size); } else if (g_ascii_strncasecmp (ucl_object_key (value), "max_threads", sizeof ("max_threads") - 1) == 0) { msg_warn_config ("regexp module is now single threaded, max_threads is ignored"); } else if (value->type == UCL_STRING) { cur_item = rspamd_mempool_alloc0 (regexp_module_ctx->regexp_pool, sizeof (struct regexp_module_item)); cur_item->symbol = ucl_object_key (value); if (!read_regexp_expression (regexp_module_ctx->regexp_pool, cur_item, ucl_object_key (value), ucl_obj_tostring (value), cfg)) { res = FALSE; } else { rspamd_symbols_cache_add_symbol (cfg->cache, cur_item->symbol, 0, process_regexp_item, cur_item, SYMBOL_TYPE_NORMAL, -1); } } else if (value->type == UCL_USERDATA) { /* Just a lua function */ cur_item = rspamd_mempool_alloc0 (regexp_module_ctx->regexp_pool, sizeof (struct regexp_module_item)); cur_item->symbol = ucl_object_key (value); cur_item->lua_function = ucl_object_toclosure (value); rspamd_symbols_cache_add_symbol (cfg->cache, cur_item->symbol, 0, process_regexp_item, cur_item, SYMBOL_TYPE_NORMAL, -1); } else if (value->type == UCL_OBJECT) { const gchar *description = NULL, *group = NULL, *metric = DEFAULT_METRIC; gdouble score = 0.0; gboolean one_shot = FALSE, is_lua = FALSE, valid_expression = TRUE; /* We have some lua table, extract its arguments */ elt = ucl_object_find_key (value, "callback"); if (elt == NULL || elt->type != UCL_USERDATA) { /* Try plain regexp expression */ elt = ucl_object_find_any_key (value, "regexp", "re", NULL); if (elt != NULL && ucl_object_type (elt) == UCL_STRING) { cur_item = rspamd_mempool_alloc0 (regexp_module_ctx->regexp_pool, sizeof (struct regexp_module_item)); cur_item->symbol = ucl_object_key (value); if (!read_regexp_expression (regexp_module_ctx->regexp_pool, cur_item, ucl_object_key (value), ucl_obj_tostring (elt), cfg)) { res = FALSE; } else { valid_expression = TRUE; } } else { msg_err_config ( "no callback/expression defined for regexp symbol: " "%s", ucl_object_key (value)); } } else { is_lua = TRUE; cur_item = rspamd_mempool_alloc0 ( regexp_module_ctx->regexp_pool, sizeof (struct regexp_module_item)); cur_item->symbol = ucl_object_key (value); cur_item->lua_function = ucl_object_toclosure (value); } if (cur_item && (is_lua || valid_expression)) { id = rspamd_symbols_cache_add_symbol (cfg->cache, cur_item->symbol, 0, process_regexp_item, cur_item, SYMBOL_TYPE_NORMAL, -1); elt = ucl_object_find_key (value, "condition"); if (elt != NULL && ucl_object_type (elt) == UCL_USERDATA) { struct ucl_lua_funcdata *conddata; conddata = ucl_object_toclosure (elt); rspamd_symbols_cache_add_condition (cfg->cache, id, conddata->L, conddata->idx); } elt = ucl_object_find_key (value, "metric"); if (elt) { metric = ucl_object_tostring (elt); } elt = ucl_object_find_key (value, "description"); if (elt) { description = ucl_object_tostring (elt); } elt = ucl_object_find_key (value, "group"); if (elt) { group = ucl_object_tostring (elt); } elt = ucl_object_find_key (value, "score"); if (elt) { score = ucl_object_todouble (elt); } elt = ucl_object_find_key (value, "one_shot"); if (elt) { one_shot = ucl_object_toboolean (elt); } rspamd_config_add_metric_symbol (cfg, metric, cur_item->symbol, score, description, group, one_shot, FALSE); } } else { msg_warn_config ("unknown type of attribute %s for regexp module", ucl_object_key (value)); } } return res; }
static void config_parse(const ucl_object_t *obj, pkg_conf_file_t conftype) { struct sbuf *buf = sbuf_new_auto(); const ucl_object_t *cur, *seq; ucl_object_iter_t it = NULL, itseq = NULL; struct config_entry *temp_config; struct config_value *cv; const char *key; int i; size_t j; /* Temporary config for configs that may be disabled. */ temp_config = calloc(CONFIG_SIZE, sizeof(struct config_entry)); while ((cur = ucl_iterate_object(obj, &it, true))) { key = ucl_object_key(cur); if (key == NULL) continue; sbuf_clear(buf); if (conftype == CONFFILE_PKG) { for (j = 0; j < strlen(key); ++j) sbuf_putc(buf, key[j]); sbuf_finish(buf); } else if (conftype == CONFFILE_REPO) { if (strcasecmp(key, "url") == 0) sbuf_cpy(buf, "PACKAGESITE"); else if (strcasecmp(key, "mirror_type") == 0) sbuf_cpy(buf, "MIRROR_TYPE"); else if (strcasecmp(key, "signature_type") == 0) sbuf_cpy(buf, "SIGNATURE_TYPE"); else if (strcasecmp(key, "fingerprints") == 0) sbuf_cpy(buf, "FINGERPRINTS"); else if (strcasecmp(key, "enabled") == 0) { if ((cur->type != UCL_BOOLEAN) || !ucl_object_toboolean(cur)) goto cleanup; } else continue; sbuf_finish(buf); } for (i = 0; i < CONFIG_SIZE; i++) { if (strcmp(sbuf_data(buf), c[i].key) == 0) break; } /* Silently skip unknown keys to be future compatible. */ if (i == CONFIG_SIZE) continue; /* env has priority over config file */ if (c[i].envset) continue; /* Parse sequence value ["item1", "item2"] */ switch (c[i].type) { case PKG_CONFIG_LIST: if (cur->type != UCL_ARRAY) { warnx("Skipping invalid array " "value for %s.\n", c[i].key); continue; } temp_config[i].list = malloc(sizeof(*temp_config[i].list)); STAILQ_INIT(temp_config[i].list); while ((seq = ucl_iterate_object(cur, &itseq, true))) { if (seq->type != UCL_STRING) continue; cv = malloc(sizeof(struct config_value)); cv->value = strdup(ucl_object_tostring(seq)); STAILQ_INSERT_TAIL(temp_config[i].list, cv, next); } break; case PKG_CONFIG_BOOL: temp_config[i].value = strdup(ucl_object_toboolean(cur) ? "yes" : "no"); break; default: /* Normal string value. */ temp_config[i].value = strdup(ucl_object_tostring(cur)); break; } } /* Repo is enabled, copy over all settings from temp_config. */ for (i = 0; i < CONFIG_SIZE; i++) { if (c[i].envset) continue; /* Prevent overriding ABI, ASSUME_ALWAYS_YES, etc. */ if (conftype != CONFFILE_PKG && c[i].main_only == true) continue; switch (c[i].type) { case PKG_CONFIG_LIST: c[i].list = temp_config[i].list; break; default: c[i].value = temp_config[i].value; break; } } cleanup: free(temp_config); sbuf_delete(buf); }
int pkg_ini(const char *path, const char *reposdir, pkg_init_flags flags) { struct ucl_parser *p = NULL; size_t i; const char *val = NULL; const char *buf, *walk, *value, *key, *k; const char *evkey = NULL; const char *nsname = NULL; const char *evpipe = NULL; const ucl_object_t *cur, *object; ucl_object_t *obj = NULL, *o, *ncfg; ucl_object_iter_t it = NULL; struct sbuf *ukey = NULL; bool fatal_errors = false; k = NULL; o = NULL; pkg_get_myarch(myabi, BUFSIZ); pkg_get_myarch_legacy(myabi_legacy, BUFSIZ); if (parsed != false) { pkg_emit_error("pkg_init() must only be called once"); return (EPKG_FATAL); } if (((flags & PKG_INIT_FLAG_USE_IPV4) == PKG_INIT_FLAG_USE_IPV4) && ((flags & PKG_INIT_FLAG_USE_IPV6) == PKG_INIT_FLAG_USE_IPV6)) { pkg_emit_error("Invalid flags for pkg_init()"); return (EPKG_FATAL); } config = ucl_object_typed_new(UCL_OBJECT); for (i = 0; i < c_size; i++) { switch (c[i].type) { case PKG_STRING: obj = ucl_object_fromstring_common( c[i].def != NULL ? c[i].def : "", 0, UCL_STRING_TRIM); ucl_object_insert_key(config, obj, c[i].key, strlen(c[i].key), false); break; case PKG_INT: ucl_object_insert_key(config, ucl_object_fromstring_common(c[i].def, 0, UCL_STRING_PARSE_INT), c[i].key, strlen(c[i].key), false); break; case PKG_BOOL: ucl_object_insert_key(config, ucl_object_fromstring_common(c[i].def, 0, UCL_STRING_PARSE_BOOLEAN), c[i].key, strlen(c[i].key), false); break; case PKG_OBJECT: obj = ucl_object_typed_new(UCL_OBJECT); if (c[i].def != NULL) { walk = buf = c[i].def; while ((buf = strchr(buf, ',')) != NULL) { key = walk; value = walk; while (*value != ',') { if (*value == '=') break; value++; } ucl_object_insert_key(obj, ucl_object_fromstring_common(value + 1, buf - value - 1, UCL_STRING_TRIM), key, value - key, false); buf++; walk = buf; } key = walk; value = walk; while (*value != ',') { if (*value == '=') break; value++; } if (o == NULL) o = ucl_object_typed_new(UCL_OBJECT); ucl_object_insert_key(o, ucl_object_fromstring_common(value + 1, strlen(value + 1), UCL_STRING_TRIM), key, value - key, false); } ucl_object_insert_key(config, obj, c[i].key, strlen(c[i].key), false); break; case PKG_ARRAY: obj = ucl_object_typed_new(UCL_ARRAY); if (c[i].def != NULL) { walk = buf = c[i].def; while ((buf = strchr(buf, ',')) != NULL) { ucl_array_append(obj, ucl_object_fromstring_common(walk, buf - walk, UCL_STRING_TRIM)); buf++; walk = buf; } ucl_array_append(obj, ucl_object_fromstring_common(walk, strlen(walk), UCL_STRING_TRIM)); } ucl_object_insert_key(config, obj, c[i].key, strlen(c[i].key), false); break; } } if (path == NULL) path = PREFIX"/etc/pkg.conf"; p = ucl_parser_new(0); errno = 0; obj = NULL; if (!ucl_parser_add_file(p, path)) { if (errno != ENOENT) pkg_emit_error("Invalid configuration file: %s", ucl_parser_get_error(p)); } else { obj = ucl_parser_get_object(p); } ncfg = NULL; while (obj != NULL && (cur = ucl_iterate_object(obj, &it, true))) { sbuf_init(&ukey); key = ucl_object_key(cur); for (i = 0; key[i] != '\0'; i++) sbuf_putc(ukey, toupper(key[i])); sbuf_finish(ukey); object = ucl_object_find_keyl(config, sbuf_data(ukey), sbuf_len(ukey)); if (strncasecmp(sbuf_data(ukey), "PACKAGESITE", sbuf_len(ukey)) == 0 || strncasecmp(sbuf_data(ukey), "PUBKEY", sbuf_len(ukey)) == 0 || strncasecmp(sbuf_data(ukey), "MIRROR_TYPE", sbuf_len(ukey)) == 0) { pkg_emit_error("%s in pkg.conf is no longer " "supported. Convert to the new repository style." " See pkg.conf(5)", sbuf_data(ukey)); fatal_errors = true; continue; } /* ignore unknown keys */ if (object == NULL) continue; if (object->type != cur->type) { pkg_emit_error("Malformed key %s, ignoring", key); continue; } if (ncfg == NULL) ncfg = ucl_object_typed_new(UCL_OBJECT); ucl_object_insert_key(ncfg, ucl_object_copy(cur), sbuf_data(ukey), sbuf_len(ukey), true); } if (fatal_errors) { ucl_object_unref(ncfg); ucl_parser_free(p); return (EPKG_FATAL); } if (ncfg != NULL) { it = NULL; while (( cur = ucl_iterate_object(ncfg, &it, true))) { key = ucl_object_key(cur); ucl_object_replace_key(config, ucl_object_ref(cur), key, strlen(key), true); } ucl_object_unref(ncfg); } ncfg = NULL; it = NULL; while ((cur = ucl_iterate_object(config, &it, true))) { o = NULL; key = ucl_object_key(cur); val = getenv(key); if (val == NULL) continue; switch (cur->type) { case UCL_STRING: o = ucl_object_fromstring_common(val, 0, UCL_STRING_TRIM); break; case UCL_INT: o = ucl_object_fromstring_common(val, 0, UCL_STRING_PARSE_INT); if (o->type != UCL_INT) { pkg_emit_error("Invalid type for environment " "variable %s, got %s, while expecting an integer", key, val); ucl_object_unref(o); continue; } break; case UCL_BOOLEAN: o = ucl_object_fromstring_common(val, 0, UCL_STRING_PARSE_BOOLEAN); if (o->type != UCL_BOOLEAN) { pkg_emit_error("Invalid type for environment " "variable %s, got %s, while expecting a boolean", key, val); ucl_object_unref(o); continue; } break; case UCL_OBJECT: o = ucl_object_typed_new(UCL_OBJECT); walk = buf = val; while ((buf = strchr(buf, ',')) != NULL) { k = walk; value = walk; while (*value != ',') { if (*value == '=') break; value++; } ucl_object_insert_key(o, ucl_object_fromstring_common(value + 1, buf - value - 1, UCL_STRING_TRIM), k, value - k, false); buf++; walk = buf; } key = walk; value = walk; while (*value != '\0') { if (*value == '=') break; value++; } ucl_object_insert_key(o, ucl_object_fromstring_common(value + 1, strlen(value + 1), UCL_STRING_TRIM), k, value - k, false); break; case UCL_ARRAY: o = ucl_object_typed_new(UCL_ARRAY); walk = buf = val; while ((buf = strchr(buf, ',')) != NULL) { ucl_array_append(o, ucl_object_fromstring_common(walk, buf - walk, UCL_STRING_TRIM)); buf++; walk = buf; } ucl_array_append(o, ucl_object_fromstring_common(walk, strlen(walk), UCL_STRING_TRIM)); break; default: /* ignore other types */ break; } if (o != NULL) { if (ncfg == NULL) ncfg = ucl_object_typed_new(UCL_OBJECT); ucl_object_insert_key(ncfg, o, key, strlen(key), true); } } if (ncfg != NULL) { it = NULL; while (( cur = ucl_iterate_object(ncfg, &it, true))) { key = ucl_object_key(cur); ucl_object_replace_key(config, ucl_object_ref(cur), key, strlen(key), true); } ucl_object_unref(ncfg); } disable_plugins_if_static(); parsed = true; ucl_object_unref(obj); ucl_parser_free(p); if (strcmp(pkg_object_string(pkg_config_get("ABI")), "unknown") == 0) { pkg_emit_error("Unable to determine ABI"); return (EPKG_FATAL); } pkg_debug(1, "%s", "pkg initialized"); /* Start the event pipe */ evpipe = pkg_object_string(pkg_config_get("EVENT_PIPE")); if (evpipe != NULL) connect_evpipe(evpipe); debug_level = pkg_object_int(pkg_config_get("DEBUG_LEVEL")); it = NULL; object = ucl_object_find_key(config, "PKG_ENV"); while ((cur = ucl_iterate_object(object, &it, true))) { evkey = ucl_object_key(cur); pkg_debug(1, "Setting env var: %s", evkey); if (evkey != NULL && evkey[0] != '\0') setenv(evkey, ucl_object_tostring_forced(cur), 1); } /* load the repositories */ load_repositories(reposdir, flags); setenv("HTTP_USER_AGENT", "pkg/"PKGVERSION, 1); /* bypass resolv.conf with specified NAMESERVER if any */ nsname = pkg_object_string(pkg_config_get("NAMESERVER")); if (nsname != NULL) set_nameserver(ucl_object_tostring_forced(o)); return (EPKG_OK); }
static void add_repo(ucl_object_t *obj, struct pkg_repo *r, const char *rname) { ucl_object_t *cur, *tmp = NULL; ucl_object_iter_t it = NULL; bool enable = true; const char *url = NULL, *pubkey = NULL, *mirror_type = NULL; const char *signature_type = NULL, *fingerprints = NULL; const char *key; pkg_debug(1, "PkgConfig: parsing repository object %s", rname); while ((cur = ucl_iterate_object(obj, &it, true))) { key = ucl_object_key(cur); if (key == NULL) continue; if (strcasecmp(key, "url") == 0) { if (cur->type != UCL_STRING) { pkg_emit_error("Expecting a string for the " "'%s' key of the '%s' repo", key, rname); return; } url = ucl_object_tostring(cur); } else if (strcasecmp(key, "pubkey") == 0) { if (cur->type != UCL_STRING) { pkg_emit_error("Expecting a string for the " "'%s' key of the '%s' repo", key, rname); return; } pubkey = ucl_object_tostring(cur); } else if (strcasecmp(key, "enabled") == 0) { if (cur->type == UCL_STRING) tmp = ucl_object_fromstring_common(ucl_object_tostring(cur), strlen(ucl_object_tostring(cur)), UCL_STRING_PARSE_BOOLEAN); if (cur->type != UCL_BOOLEAN && (tmp != NULL && tmp->type != UCL_BOOLEAN)) { pkg_emit_error("Expecting a boolean for the " "'%s' key of the '%s' repo", key, rname); if (tmp != NULL) ucl_object_free(tmp); return; } if (tmp != NULL) pkg_emit_error("Warning: expecting a boolean for the '%s' key of the '%s' repo, " " the value has been correctly converted, please consider fixing", key, rname); enable = ucl_object_toboolean(tmp != NULL ? tmp : cur); if (tmp != NULL) ucl_object_free(tmp); } else if (strcasecmp(key, "mirror_type") == 0) { if (cur->type != UCL_STRING) { pkg_emit_error("Expecting a string for the " "'%s' key of the '%s' repo", key, rname); return; } mirror_type = ucl_object_tostring(cur); } else if (strcasecmp(key, "signature_type") == 0) { if (cur->type != UCL_STRING) { pkg_emit_error("Expecting a string for the " "'%s' key of the '%s' repo", key, rname); return; } signature_type = ucl_object_tostring(cur); } else if (strcasecmp(key, "fingerprints") == 0) { if (cur->type != UCL_STRING) { pkg_emit_error("Expecting a string for the " "'%s' key of the '%s' repo", key, rname); return; } fingerprints = ucl_object_tostring(cur); } } if (r == NULL && url == NULL) { pkg_debug(1, "No repo and no url for %s", rname); return; } if (r == NULL) r = pkg_repo_new(rname, url); if (signature_type != NULL) { if (strcasecmp(signature_type, "pubkey") == 0) r->signature_type = SIG_PUBKEY; else if (strcasecmp(signature_type, "fingerprints") == 0) r->signature_type = SIG_FINGERPRINT; else r->signature_type = SIG_NONE; } if (fingerprints != NULL) { free(r->fingerprints); r->fingerprints = strdup(fingerprints); } if (pubkey != NULL) { free(r->pubkey); r->pubkey = strdup(pubkey); } r->enable = enable; if (mirror_type != NULL) { if (strcasecmp(mirror_type, "srv") == 0) r->mirror_type = SRV; else if (strcasecmp(mirror_type, "http") == 0) r->mirror_type = HTTP; else r->mirror_type = NOMIRROR; } }