bool pkg_object_bool(const pkg_object *o) { if (o == NULL || o->type != UCL_BOOLEAN) return (false); return (ucl_object_toboolean(o)); }
/** * Emit a single element * @param obj object * @param buf buffer */ static void ucl_elt_write_json (ucl_object_t *obj, struct ucl_emitter_functions *func, unsigned int tabs, bool start_tabs, bool compact) { bool flag; switch (obj->type) { case UCL_INT: if (start_tabs) { ucl_add_tabs (func, tabs, compact); } func->ucl_emitter_append_int (ucl_object_toint (obj), func->ud); break; case UCL_FLOAT: case UCL_TIME: if (start_tabs) { ucl_add_tabs (func, tabs, compact); } func->ucl_emitter_append_double (ucl_object_todouble (obj), func->ud); break; case UCL_BOOLEAN: if (start_tabs) { ucl_add_tabs (func, tabs, compact); } flag = ucl_object_toboolean (obj); if (flag) { func->ucl_emitter_append_len ("true", 4, func->ud); } else { func->ucl_emitter_append_len ("false", 5, func->ud); } break; case UCL_STRING: if (start_tabs) { ucl_add_tabs (func, tabs, compact); } ucl_elt_string_write_json (obj->value.sv, obj->len, func); break; case UCL_NULL: if (start_tabs) { ucl_add_tabs (func, tabs, compact); } func->ucl_emitter_append_len ("null", 4, func->ud); break; case UCL_OBJECT: ucl_elt_obj_write_json (obj, func, tabs, start_tabs, compact); break; case UCL_ARRAY: ucl_elt_array_write_json (obj->value.av, func, tabs, start_tabs, compact); break; case UCL_USERDATA: break; } }
static PyObject * _basic_ucl_type (ucl_object_t const *obj) { switch (obj->type) { case UCL_INT: return Py_BuildValue ("L", (long long)ucl_object_toint (obj)); case UCL_FLOAT: return Py_BuildValue ("d", ucl_object_todouble (obj)); case UCL_STRING: return Py_BuildValue ("s", ucl_object_tostring (obj)); case UCL_BOOLEAN: return ucl_object_toboolean (obj) ? Py_True : Py_False; case UCL_TIME: return Py_BuildValue ("d", ucl_object_todouble (obj)); } return NULL; }
/* * snprintkeys writes the value contained in obj to dst. */ static int snprintval(char *dst, size_t size, ucl_object_t const *obj) { switch (ucl_object_type(obj)) { case UCL_INT: return snprintf(dst, size, "%" PRId64, ucl_object_toint(obj)); case UCL_FLOAT: case UCL_TIME: return snprintf(dst, size, "%0.10f", ucl_object_todouble(obj)); case UCL_STRING: return snprintf(dst, size, "%s", ucl_object_tostring(obj)); case UCL_BOOLEAN: return snprintf(dst, size, "%s", ucl_object_toboolean(obj) ? "true": "false"); default: *dst = '\0'; return 0; } }
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; }
gboolean rspamd_config_is_module_enabled (struct rspamd_config *cfg, const gchar *module_name) { gboolean is_c = FALSE; struct metric *metric; const ucl_object_t *conf, *enabled; GList *cur; struct rspamd_symbols_group *gr; metric = cfg->default_metric; if (g_hash_table_lookup (cfg->c_modules, module_name)) { is_c = TRUE; } if (g_hash_table_lookup (cfg->explicit_modules, module_name) != NULL) { /* Always load module */ return TRUE; } if (is_c) { gboolean found = FALSE; cur = g_list_first (cfg->filters); while (cur) { if (strcmp (cur->data, module_name) == 0) { found = TRUE; break; } cur = g_list_next (cur); } if (!found) { msg_info_config ("internal module %s is disable in `filters` line", module_name); return FALSE; } } conf = ucl_object_find_key (cfg->rcl_obj, module_name); if (conf == NULL) { msg_info_config ("%s module %s is enabled but has not been configured", is_c ? "internal" : "lua", module_name); if (!is_c) { msg_info_config ("%s disabling unconfigured lua module", module_name); return FALSE; } } else { enabled = ucl_object_find_key (conf, "enabled"); if (enabled && ucl_object_type (enabled) == UCL_BOOLEAN) { if (!ucl_object_toboolean (enabled)) { msg_info_config ("%s module %s is disabled in the configuration", is_c ? "internal" : "lua", module_name); return FALSE; } } } /* Now we check symbols group */ gr = g_hash_table_lookup (metric->groups, module_name); if (gr) { if (gr->disabled) { msg_info_config ("%s module %s is disabled in the configuration as " "its group has been disabled", is_c ? "internal" : "lua", module_name); return FALSE; } } 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); }
static struct rspamd_osb_tokenizer_config * rspamd_tokenizer_osb_config_from_ucl (rspamd_mempool_t * pool, const ucl_object_t *obj) { const ucl_object_t *elt; struct rspamd_osb_tokenizer_config *cf, *def; guchar *key = NULL; gsize keylen; if (pool != NULL) { cf = rspamd_mempool_alloc0 (pool, sizeof (*cf)); } else { cf = g_malloc0 (sizeof (*cf)); } /* Use default config */ def = rspamd_tokenizer_osb_default_config (); memcpy (cf, def, sizeof (*cf)); elt = ucl_object_lookup (obj, "hash"); if (elt != NULL && ucl_object_type (elt) == UCL_STRING) { if (g_ascii_strncasecmp (ucl_object_tostring (elt), "xxh", 3) == 0) { cf->ht = RSPAMD_OSB_HASH_XXHASH; elt = ucl_object_lookup (obj, "seed"); if (elt != NULL && ucl_object_type (elt) == UCL_INT) { cf->seed = ucl_object_toint (elt); } } else if (g_ascii_strncasecmp (ucl_object_tostring (elt), "sip", 3) == 0) { cf->ht = RSPAMD_OSB_HASH_SIPHASH; elt = ucl_object_lookup (obj, "key"); if (elt != NULL && ucl_object_type (elt) == UCL_STRING) { key = rspamd_decode_base32 (ucl_object_tostring (elt), 0, &keylen); if (keylen < sizeof (rspamd_sipkey_t)) { msg_warn ("siphash key is too short: %z", keylen); g_free (key); } else { memcpy (cf->sk, key, sizeof (cf->sk)); g_free (key); } } else { msg_warn_pool ("siphash cannot be used without key"); } } } else { elt = ucl_object_lookup (obj, "compat"); if (elt != NULL && ucl_object_toboolean (elt)) { cf->ht = RSPAMD_OSB_HASH_COMPAT; } } elt = ucl_object_lookup (obj, "window"); if (elt != NULL && ucl_object_type (elt) == UCL_INT) { cf->window_size = ucl_object_toint (elt); if (cf->window_size > DEFAULT_FEATURE_WINDOW_SIZE * 4) { msg_err_pool ("too large window size: %d", cf->window_size); cf->window_size = DEFAULT_FEATURE_WINDOW_SIZE; } } return cf; }
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); }
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; } }
static gboolean rspamd_redis_try_ucl (struct redis_stat_ctx *backend, const ucl_object_t *obj, struct rspamd_config *cfg, const gchar *symbol) { const ucl_object_t *elt, *relt, *users_enabled; const gchar *lua_script; elt = ucl_object_lookup_any (obj, "read_servers", "servers", NULL); if (elt == NULL) { return FALSE; } backend->read_servers = rspamd_upstreams_create (cfg->ups_ctx); if (!rspamd_upstreams_from_ucl (backend->read_servers, elt, REDIS_DEFAULT_PORT, NULL)) { msg_err ("statfile %s cannot get read servers configuration", symbol); return FALSE; } relt = elt; elt = ucl_object_lookup (obj, "write_servers"); if (elt == NULL) { /* Use read servers as write ones */ g_assert (relt != NULL); backend->write_servers = rspamd_upstreams_create (cfg->ups_ctx); if (!rspamd_upstreams_from_ucl (backend->write_servers, relt, REDIS_DEFAULT_PORT, NULL)) { msg_err ("statfile %s cannot get write servers configuration", symbol); return FALSE; } } else { backend->write_servers = rspamd_upstreams_create (cfg->ups_ctx); if (!rspamd_upstreams_from_ucl (backend->write_servers, elt, REDIS_DEFAULT_PORT, NULL)) { msg_err ("statfile %s cannot get write servers configuration", symbol); rspamd_upstreams_destroy (backend->write_servers); backend->write_servers = NULL; } } elt = ucl_object_lookup (obj, "prefix"); if (elt == NULL || ucl_object_type (elt) != UCL_STRING) { /* Default non-users statistics */ backend->redis_object = REDIS_DEFAULT_OBJECT; /* * Make redis backend compatible with sqlite3 backend in users settings */ users_enabled = ucl_object_lookup_any (obj, "per_user", "users_enabled", NULL); if (users_enabled != NULL) { if (ucl_object_type (users_enabled) == UCL_BOOLEAN) { backend->enable_users = ucl_object_toboolean (users_enabled); backend->cbref_user = -1; if (backend->enable_users) { backend->redis_object = REDIS_DEFAULT_USERS_OBJECT; } } else if (ucl_object_type (users_enabled) == UCL_STRING) { lua_script = ucl_object_tostring (users_enabled); if (luaL_dostring (cfg->lua_state, lua_script) != 0) { msg_err_config ("cannot execute lua script for users " "extraction: %s", lua_tostring (cfg->lua_state, -1)); } else { if (lua_type (cfg->lua_state, -1) == LUA_TFUNCTION) { backend->enable_users = TRUE; backend->cbref_user = luaL_ref (cfg->lua_state, LUA_REGISTRYINDEX); } else { msg_err_config ("lua script must return " "function(task) and not %s", lua_typename (cfg->lua_state, lua_type ( cfg->lua_state, -1))); } } } } else { backend->enable_users = FALSE; } } else { /* XXX: sanity check */ backend->redis_object = ucl_object_tostring (elt); } elt = ucl_object_lookup (obj, "timeout"); if (elt) { backend->timeout = ucl_object_todouble (elt); } else { backend->timeout = REDIS_DEFAULT_TIMEOUT; } elt = ucl_object_lookup (obj, "password"); if (elt) { backend->password = ucl_object_tostring (elt); } else { backend->password = NULL; } elt = ucl_object_lookup_any (obj, "db", "database", "dbname", NULL); if (elt) { backend->dbname = ucl_object_tostring (elt); } else { backend->dbname = NULL; } return TRUE; }
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 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; }
/* * 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; }