static liAction* mod_limit_action_create(liServer *srv, liPlugin *p, mod_limit_context_type type, liValue *val) { const char* act_names[] = { "limit.con", "limit.con_ip", "limit.req", "limit.req_ip" }; mod_limit_context *ctx; gint limit = 0; liAction *action_limit_reached = NULL; val = li_value_get_single_argument(val); val = li_value_get_single_argument(val); if (LI_VALUE_NUMBER == li_value_type(val) && val->data.number > 0) { /* limit.* N; */ limit = val->data.number; action_limit_reached = NULL; } else if (LI_VALUE_LIST == li_value_type(val) && li_value_list_has_len(val, 2) && LI_VALUE_NUMBER == li_value_list_type_at(val, 0) && li_value_list_at(val, 0)->data.number > 0 && LI_VALUE_ACTION == li_value_list_type_at(val, 1)) { limit = li_value_list_at(val, 0)->data.number; action_limit_reached = li_value_extract_action(li_value_list_at(val, 1)); } else { ERROR(srv, "%s expects either an integer > 0 as parameter, or a list of (int > 0,action)", act_names[type]); return NULL; } ctx = mod_limit_context_new(type, limit, action_limit_reached, p); return li_action_new_function(mod_limit_action_handle, NULL, mod_limit_action_free, ctx); }
static liAction* progress_show_create(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) { mod_progress_show_param *psp; mod_progress_format format = PROGRESS_FORMAT_JSON; UNUSED(srv); UNUSED(wrk); UNUSED(userdata); if (!val) { format = PROGRESS_FORMAT_JSON; } else if (val->type == LI_VALUE_STRING) { gchar *str = val->data.string->str; if (g_str_equal(str, "legacy")) { format = PROGRESS_FORMAT_LEGACY; } else if (g_str_equal(str, "json")) { format = PROGRESS_FORMAT_JSON; } else if (g_str_equal(str, "jsonp")) { format = PROGRESS_FORMAT_JSONP; } else if (g_str_equal(str, "dump")) { format = PROGRESS_FORMAT_DUMP; } else { ERROR(srv, "progress.show: unknown format \"%s\"", str); return NULL; } } else { ERROR(srv, "%s", "progress.show expects an optional string as parameter"); return NULL; } psp = g_slice_new(mod_progress_show_param); psp->format = format; psp->p = p; return li_action_new_function(progress_show, progress_collect_cleanup, progress_show_free, psp); }
static liAction* core_throttle_connection(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) { liThrottleParam *param; guint64 rate, burst; UNUSED(wrk); UNUSED(p); UNUSED(userdata); val = li_value_get_single_argument(val); val = li_value_get_single_argument(val); if (li_value_list_has_len(val, 2)) { liValue *v1 = li_value_list_at(val, 0); liValue *v2 = li_value_list_at(val, 1); if (LI_VALUE_NUMBER != li_value_type(v1) || LI_VALUE_NUMBER != li_value_type(v2)) { ERROR(srv, "%s", "'io.throttle' action expects a positiv integer or a pair of those as parameter"); return NULL; } rate = v2->data.number; burst = v1->data.number; } else if (LI_VALUE_NUMBER == li_value_type(val)) { rate = val->data.number; burst = 2 * rate; } else { ERROR(srv, "'io.throttle' action expects a positiv integer or a pair of those as parameter, %s given", li_value_type_string(val)); return NULL; } if ((rate != 0 || burst != 0) && !sanity_check(srv, rate, burst)) return NULL; param = g_slice_new(liThrottleParam); param->rate = rate; param->burst = burst; return li_action_new_function(core_handle_throttle_connection, NULL, core_throttle_connection_free, param); }
static liAction* lua_handler_create(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) { liValue *v_filename = NULL, *v_options = NULL, *v_args = NULL; lua_config *conf; guint ttl = 0; UNUSED(wrk); UNUSED(userdata); if (LI_VALUE_STRING == li_value_type(val)) { v_filename = val; } else if (LI_VALUE_LIST == li_value_type(val)) { switch (li_value_list_len(val)) { case 3: v_args = li_value_list_at(val, 2); /* fall through */ case 2: v_options = li_value_list_at(val, 1); /* fall through */ case 1: v_filename = li_value_list_at(val, 0); /* fall through */ case 0: break; default: ERROR(srv, "%s", "lua.handler expects at most 3 arguments"); return NULL; } } if (LI_VALUE_STRING != li_value_type(v_filename)) { ERROR(srv, "%s", "lua.handler expects at least a filename, or a filename and some options"); return NULL; } if (NULL != v_options) { if (NULL == (v_options = li_value_to_key_value_list(v_options))) { ERROR(srv, "%s", "lua.handler expects options in a hash/key-value list"); return NULL; } LI_VALUE_FOREACH(entry, v_options) liValue *entryKey = li_value_list_at(entry, 0); liValue *entryValue = li_value_list_at(entry, 1); GString *entryKeyStr; if (LI_VALUE_STRING != li_value_type(entryKey)) { ERROR(srv, "%s", "lua.handler doesn't take default keys"); return NULL; } entryKeyStr = entryKey->data.string; /* keys are either NONE or STRING */ if (g_string_equal(entryKeyStr, &lon_ttl)) { if (LI_VALUE_NUMBER != li_value_type(entryValue) || entryValue->data.number <= 0) { ERROR(srv, "lua.handler option '%s' expects positive integer as parameter", entryKeyStr->str); return NULL; } ttl = entryValue->data.number; } else { ERROR(srv, "unknown option for lua.handler '%s'", entryKeyStr->str); return NULL; } LI_VALUE_END_FOREACH() } conf = lua_config_new(srv, p, li_value_extract_string(v_filename), ttl, li_value_extract(v_args)); return li_action_new_function(lua_handle, NULL, lua_config_free, conf); }
static liAction* redirect_create(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) { redirect_data *rd; UNUSED(wrk); UNUSED(userdata); val = li_value_get_single_argument(val); if (LI_VALUE_STRING != li_value_type(val) && LI_VALUE_LIST != li_value_type(val)) { ERROR(srv, "%s", "redirect expects a either a string, a tuple of strings or a list of string tuples"); return NULL; } rd = g_slice_new(redirect_data); rd->p = p; rd->rules = g_array_new(FALSE, FALSE, sizeof(redirect_rule)); if (LI_VALUE_STRING == li_value_type(val)) { redirect_rule rule; /* redirect "/foo/bar"; */ if (!redirect_rule_parse(srv, NULL, val->data.string, &rule)) { redirect_free(NULL, rd); return NULL; } g_array_append_val(rd->rules, rule); } else if (li_value_list_has_len(val, 2) && LI_VALUE_STRING == li_value_list_type_at(val, 0) && LI_VALUE_STRING == li_value_list_type_at(val, 1)) { redirect_rule rule; /* only one rule */ if (!redirect_rule_parse(srv, li_value_list_at(val, 0)->data.string, li_value_list_at(val, 1)->data.string, &rule)) { redirect_free(NULL, rd); return NULL; } g_array_append_val(rd->rules, rule); } else { /* probably multiple rules */ LI_VALUE_FOREACH(v, val) redirect_rule rule; if (!li_value_list_has_len(v, 2) || LI_VALUE_STRING != li_value_list_type_at(v, 0) || LI_VALUE_STRING != li_value_list_type_at(v, 1)) { redirect_free(NULL, rd); ERROR(srv, "%s", "redirect expects a either a tuple of strings or a list of those"); return NULL; } if (!redirect_rule_parse(srv, li_value_list_at(v, 0)->data.string, li_value_list_at(v, 1)->data.string, &rule)) { redirect_free(NULL, rd); return NULL; } g_array_append_val(rd->rules, rule); LI_VALUE_END_FOREACH() } return li_action_new_function(redirect, NULL, redirect_free, rd); }
static liAction* vhost_map_create(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) { vhost_map_data *md; UNUSED(wrk); UNUSED(userdata); val = li_value_get_single_argument(val); if (NULL == (val = li_value_to_key_value_list(val))) { ERROR(srv, "%s", "vhost.map expects a hashtable/key-value list as parameter"); return NULL; } md = g_slice_new0(vhost_map_data); md->plugin = p; md->hash = li_value_new_hashtable(); LI_VALUE_FOREACH(entry, val) liValue *entryKey = li_value_list_at(entry, 0); liValue *entryValue = li_value_list_at(entry, 1); GString *entryKeyStr; if (LI_VALUE_ACTION != li_value_type(entryValue)) { ERROR(srv, "vhost.map expects a hashtable/key-value list with action values as parameter, %s value given", li_value_type_string(entryValue)); vhost_map_free(srv, md); return NULL; } /* we now own the key string: free it in case of failure */ entryKeyStr = li_value_extract_string(entryKey); if (NULL != entryKeyStr && g_str_equal(entryKeyStr->str, "default")) { WARNING(srv, "%s", "vhost.map: found entry with string key \"default\". please convert the parameter to a key-value list and use the keyword default instead."); /* TODO: remove support for "default" (LI_VALUE_HASH) */ g_string_free(entryKeyStr, TRUE); entryKeyStr = NULL; } if (NULL == entryKeyStr) { if (NULL != md->default_action) { ERROR(srv, "%s", "vhost.map: already have a default action"); /* key string is NULL, nothing to free */ vhost_map_free(srv, md); return NULL; } md->default_action = li_value_extract(entryValue); } else { if (NULL != g_hash_table_lookup(md->hash, entryKeyStr)) { ERROR(srv, "vhost.map: duplicate entry for '%s'", entryKeyStr->str); g_string_free(entryKeyStr, TRUE); vhost_map_free(srv, md); return NULL; } g_hash_table_insert(md->hash, entryKeyStr, li_value_extract(entryValue)); } LI_VALUE_END_FOREACH() return li_action_new_function(vhost_map, NULL, vhost_map_free, md); }
static liAction* progress_track_create(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) { UNUSED(wrk); UNUSED(userdata); if (val) { ERROR(srv, "%s", "progress.show doesn't expect any parameters"); return NULL; } return li_action_new_function(progress_track, NULL, NULL, p); }
static liAction* flv_create(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) { UNUSED(wrk); UNUSED(userdata); if (!li_value_is_nothing(val)) { ERROR(srv, "%s", "flv does not take any parameters"); return NULL; } return li_action_new_function(flv, NULL, NULL, p); }
static liAction* auth_deny(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) { UNUSED(srv); UNUSED(wrk); UNUSED(userdata); if (val) { ERROR(srv, "%s", "'auth.deny' action doesn't have parameters"); return NULL; } return li_action_new_function(auth_handle_deny, NULL, NULL, p); }
static liAction* cache_etag_create(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) { cache_etag_context *ctx; UNUSED(wrk); UNUSED(p); UNUSED(userdata); if (val->type != LI_VALUE_STRING) { ERROR(srv, "%s", "cache.disk.etag expects a string as parameter"); return FALSE; } ctx = g_slice_new0(cache_etag_context); ctx->path = li_value_extract_string(val); return li_action_new_function(cache_etag_handle, cache_etag_cleanup, cache_etag_free, ctx); }
static liAction* proxy_create(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) { proxy_context *ctx; UNUSED(wrk); UNUSED(userdata); if (val->type != LI_VALUE_STRING) { ERROR(srv, "%s", "proxy expects a string as parameter"); return FALSE; } ctx = proxy_context_new(srv, p, val->data.string); if (!ctx) return NULL; return li_action_new_function(proxy_handle, NULL, proxy_free, ctx); }
static liAction* proxy_create(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) { proxy_context *ctx; UNUSED(wrk); UNUSED(userdata); UNUSED(p); val = li_value_get_single_argument(val); if (LI_VALUE_STRING != li_value_type(val)) { ERROR(srv, "%s", "proxy expects a string as parameter"); return FALSE; } ctx = proxy_context_new(srv, val->data.string); if (NULL == ctx) return NULL; return li_action_new_function(proxy_handle, proxy_handle_abort, proxy_free, ctx); }
static liAction* core_throttle_pool(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) { liThrottlePool *pool = NULL; gint64 rate, burst; UNUSED(wrk); UNUSED(p); UNUSED(userdata); val = li_value_get_single_argument(val); if (LI_VALUE_NUMBER != li_value_type(val)) { ERROR(srv, "'io.throttle_pool' action expects a number as parameter, %s given", li_value_type_string(val)); return NULL; } rate = val->data.number; burst = rate; if (!sanity_check(srv, rate, burst)) return NULL; pool = li_throttle_pool_new(srv, rate, burst); return li_action_new_function(core_handle_throttle_pool, NULL, core_throttle_pool_free, pool); }
static int filter_lua_action_create(lua_State *L, liActionFuncCB act_cb) { liLuaState *LL = li_lua_state_get(L); liServer *srv = lua_touserdata(L, lua_upvalueindex(1)); liAction *act; filter_lua_config *config; if (lua_gettop(L) != 1 || lua_isnil(L, 1)) { int n = lua_gettop(L); lua_pushstring(L, "expected exactly one parameter for lighty.filter_[in/out], got "); lua_pushinteger(L, n); lua_concat(L, 2); return lua_error(L); } config = g_slice_new0(filter_lua_config); config->LL = LL; config->class_ref = luaL_ref(L, LUA_REGISTRYINDEX); act = li_action_new_function(act_cb, NULL, filter_lua_action_free, config); return li_lua_push_action(srv, L, act); }
static liAction* core_throttle_ip(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) { gint64 rate, burst = 0; guint masklen_ipv4 = 32, masklen_ipv6 = 56; throttle_ip_pools *pools; UNUSED(wrk); UNUSED(p); UNUSED(userdata); val = li_value_get_single_argument(val); if (LI_VALUE_NUMBER != li_value_type(val)) { ERROR(srv, "'io.throttle_ip' action expects a positiv integer as parameter, %s given", li_value_type_string(val)); return NULL; } rate = val->data.number; burst = rate; if (!sanity_check(srv, rate, burst)) return NULL; pools = ip_pools_new(p->id, rate, burst, masklen_ipv4, masklen_ipv6); return li_action_new_function(core_handle_throttle_ip, NULL, core_throttle_ip_free, pools); }
static liAction* openssl_setenv_create(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) { guint i; liValue *v; guint params = 0; UNUSED(srv); UNUSED(wrk); UNUSED(p); UNUSED(userdata); if (val && val->type == LI_VALUE_STRING) li_value_wrap_in_list(val); if (!val || val->type != LI_VALUE_LIST) { ERROR(srv, "%s", openssl_setenv_config_error); return NULL; } for (i = 0; i < val->data.list->len; i++) { v = g_array_index(val->data.list, liValue*, i); if (v->type != LI_VALUE_STRING) { ERROR(srv, "%s", openssl_setenv_config_error); return NULL; } if (li_strncase_equal(v->data.string, CONST_STR_LEN("client"))) { params |= SE_CLIENT; } else if (li_strncase_equal(v->data.string, CONST_STR_LEN("client-cert"))) { params |= SE_CLIENT_CERT; } else if (li_strncase_equal(v->data.string, CONST_STR_LEN("server"))) { params |= SE_SERVER; } else if (li_strncase_equal(v->data.string, CONST_STR_LEN("server-cert"))) { params |= SE_SERVER_CERT; } else { ERROR(srv, "%s", openssl_setenv_config_error); return NULL; } } return li_action_new_function(openssl_setenv, NULL, NULL, GUINT_TO_POINTER(params)); }
static liAction* vhost_map_regex_create(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) { vhost_map_regex_data *mrd; UNUSED(wrk); UNUSED(userdata); val = li_value_get_single_argument(val); if (NULL == (val = li_value_to_key_value_list(val))) { ERROR(srv, "%s", "vhost.map_regex expects a hashtable/key-value list as parameter"); return NULL; } mrd = g_slice_new0(vhost_map_regex_data); mrd->plugin = p; mrd->list = g_array_new(FALSE, FALSE, sizeof(vhost_map_regex_entry)); LI_VALUE_FOREACH(entry, val) liValue *entryKey = li_value_list_at(entry, 0); liValue *entryValue = li_value_list_at(entry, 1); GString *entryKeyStr; if (LI_VALUE_ACTION != li_value_type(entryValue)) { ERROR(srv, "vhost.map_regex expects a hashtable/key-value list with action values as parameter, %s value given", li_value_type_string(entryValue)); vhost_map_free(srv, mrd); return NULL; } /* we now own the key string: free it in case of failure */ entryKeyStr = li_value_extract_string(entryKey); if (NULL != entryKeyStr && g_str_equal(entryKeyStr->str, "default")) { WARNING(srv, "%s", "vhost.map_regex: found entry with string key \"default\". please convert the parameter to a key-value list and use the keyword default instead."); /* TODO: remove support for "default" (LI_VALUE_HASH) */ g_string_free(entryKeyStr, TRUE); entryKeyStr = NULL; } if (NULL == entryKeyStr) { if (NULL != mrd->default_action) { ERROR(srv, "%s", "vhost.map_regex: already have a default action"); vhost_map_free(srv, mrd); return NULL; } mrd->default_action = li_value_extract(entryValue); } else { GError *err = NULL; vhost_map_regex_entry map_entry; map_entry.regex = g_regex_new(entryKeyStr->str, G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, &err); g_string_free(entryKeyStr, TRUE); if (NULL == map_entry.regex) { assert(NULL != err); vhost_map_regex_free(srv, mrd); ERROR(srv, "vhost.map_regex: error compiling regex \"%s\": %s", entryKeyStr->str, err->message); g_error_free(err); return NULL; } assert(NULL == err); map_entry.action = li_value_extract(entryValue); g_array_append_val(mrd->list, map_entry); } LI_VALUE_END_FOREACH() return li_action_new_function(vhost_map_regex, NULL, vhost_map_regex_free, mrd); }
static liAction* auth_generic_create(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, const char *actname, AuthBasicBackend basic_action, gboolean has_realm) { AuthFile *afd; liValue *method = NULL, *realm = NULL, *file = NULL; gint ttl = 10; GHashTableIter it; gpointer pkey, pvalue; if (!val || val->type != LI_VALUE_HASH) { ERROR(srv, "%s expects a hashtable with at least 3 elements: method, realm and file", actname); return NULL; } g_hash_table_iter_init(&it, val->data.hash); while (g_hash_table_iter_next(&it, &pkey, &pvalue)) { GString *key = pkey; liValue *value = pvalue; if (g_string_equal(key, &aon_method)) { if (value->type != LI_VALUE_STRING) { ERROR(srv, "auth option '%s' expects string as parameter", aon_method.str); return NULL; } method = value; } else if (g_string_equal(key, &aon_realm)) { if (value->type != LI_VALUE_STRING) { ERROR(srv, "auth option '%s' expects string as parameter", aon_realm.str); return NULL; } realm = value; } else if (g_string_equal(key, &aon_file)) { if (value->type != LI_VALUE_STRING) { ERROR(srv, "auth option '%s' expects string as parameter", aon_file.str); return NULL; } file = value; } else if (g_string_equal(key, &aon_ttl)) { if (value->type != LI_VALUE_NUMBER || value->data.number < 0) { ERROR(srv, "auth option '%s' expects non-negative number as parameter", aon_ttl.str); return NULL; } ttl = value->data.number; } } if (NULL == method || NULL == realm || NULL == file) { ERROR(srv, "%s expects a hashtable with 3 elements: method, realm and file", actname); return NULL; } if (!g_str_equal(method->data.string->str, "basic") && !g_str_equal(method->data.string->str, "digest")) { ERROR(srv, "%s: unknown method: %s", actname, method->data.string->str); return NULL; } if (g_str_equal(method->data.string->str, "digest")) { ERROR(srv, "%s: digest authentication not implemented yet", actname); return NULL; } /* load users from file */ afd = auth_file_new(wrk, file->data.string, has_realm, ttl); if (!afd) return FALSE; if (g_str_equal(method->data.string->str, "basic")) { AuthBasicData *bdata; bdata = g_slice_new(AuthBasicData); bdata->p = p; bdata->realm = li_value_extract_string(realm); bdata->backend = basic_action; bdata->data = afd; return li_action_new_function(auth_basic, NULL, auth_basic_free, bdata); } else { auth_file_free(afd); return NULL; /* li_action_new_function(NULL, NULL, auth_backend_plain_free, ad); */ } }
static liAction* expire_create(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) { expire_rule *rule; gchar *str; UNUSED(wrk); UNUSED(p); UNUSED(userdata); val = li_value_get_single_argument(val); if (LI_VALUE_STRING != li_value_type(val)) { ERROR(srv, "%s", "expire expects a string as parameter"); return NULL; } rule = g_slice_new(expire_rule); str = val->data.string->str; /* check if we have "access", "now" or "modification as <base> */ if (g_str_has_prefix(str, "access ")) { rule->base = EXPIRE_ACCESS; str += sizeof("access ") - 1; } else if (g_str_has_prefix(str, "now ")) { rule->base = EXPIRE_ACCESS; str += sizeof("now ") - 1; } else if (g_str_has_prefix(str, "modification ")) { rule->base = EXPIRE_MODIFICATION; str += sizeof("modification ") - 1; } else { g_slice_free(expire_rule, rule); ERROR(srv, "expire: error parsing rule \"%s\"", val->data.string->str); return NULL; } /* skip the optional "plus", it does nothing */ if (g_str_has_prefix(str, "plus ")) str += sizeof("plus ") - 1; rule->num = 0; /* parse (<num> <type>)+ */ while (*str) { guint num; /* parse <num> */ num = 0; for (; *str; str++) { if (*str < '0' || *str > '9') break; num *= 10; num += (*str) - '0'; } if (!num) { g_slice_free(expire_rule, rule); ERROR(srv, "expire: error parsing rule \"%s\", <num> must be a positive integer", val->data.string->str); return NULL; } /* parse <type> */ if (g_str_has_prefix(str, " second")) { num *= 1; str += sizeof(" second") - 1; } else if (g_str_has_prefix(str, " minute")) { num *= 60; str += sizeof(" minute") - 1; } else if (g_str_has_prefix(str, " hour")) { num *= 3600; str += sizeof(" hour") - 1; } else if (g_str_has_prefix(str, " day")) { num *= 3600*24; str += sizeof(" day") - 1; } else if (g_str_has_prefix(str, " week")) { num *= 3600*24*7; str += sizeof(" week") - 1; } else if (g_str_has_prefix(str, " month")) { num *= 3600*24*30; str += sizeof(" month") - 1; } else if (g_str_has_prefix(str, " year")) { num *= 3600*24*365; str += sizeof(" year") - 1; } else { g_slice_free(expire_rule, rule); ERROR(srv, "expire: error parsing rule \"%s\", <type> must be one of 'seconds', 'minutes', 'hours', 'days', 'weeks', 'months' or 'years'", val->data.string->str); return NULL; } rule->num += num; if (*str == 's') str++; if (*str == ' ') str++; else if (*str) { g_slice_free(expire_rule, rule); ERROR(srv, "expire: error parsing rule \"%s\", <type> must be one of 'seconds', 'minutes', 'hours', 'days', 'weeks', 'months' or 'years'", val->data.string->str); return NULL; } } return li_action_new_function(expire, NULL, expire_free, rule); }
static liAction* auth_generic_create(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, const char *actname, AuthBasicBackend basic_action, gboolean has_realm) { AuthFile *afd; GString *method = NULL, *file = NULL; liValue *realm = NULL; gboolean have_ttl_parameter = FALSE; gint ttl = 10; val = li_value_get_single_argument(val); if (NULL == (val = li_value_to_key_value_list(val))) { ERROR(srv, "%s expects a hashtable/key-value list with at least 3 elements: method, realm and file", actname); return NULL; } LI_VALUE_FOREACH(entry, val) liValue *entryKey = li_value_list_at(entry, 0); liValue *entryValue = li_value_list_at(entry, 1); GString *entryKeyStr; if (LI_VALUE_NONE == li_value_type(entryKey)) { ERROR(srv, "%s doesn't take default keys", actname); return NULL; } entryKeyStr = entryKey->data.string; /* keys are either NONE or STRING */ if (g_string_equal(entryKeyStr, &aon_method)) { if (LI_VALUE_STRING != li_value_type(entryValue)) { ERROR(srv, "auth option '%s' expects string as parameter", entryKeyStr->str); return NULL; } if (NULL != method) { ERROR(srv, "duplicate auth option '%s'", entryKeyStr->str); return NULL; } method = entryValue->data.string; } else if (g_string_equal(entryKeyStr, &aon_realm)) { if (LI_VALUE_STRING != li_value_type(entryValue)) { ERROR(srv, "auth option '%s' expects string as parameter", entryKeyStr->str); return NULL; } if (NULL != realm) { ERROR(srv, "duplicate auth option '%s'", entryKeyStr->str); return NULL; } realm = entryValue; } else if (g_string_equal(entryKeyStr, &aon_file)) { if (LI_VALUE_STRING != li_value_type(entryValue)) { ERROR(srv, "auth option '%s' expects string as parameter", entryKeyStr->str); return NULL; } if (NULL != file) { ERROR(srv, "duplicate auth option '%s'", entryKeyStr->str); return NULL; } file = entryValue->data.string; } else if (g_string_equal(entryKeyStr, &aon_ttl)) { if (LI_VALUE_NUMBER != li_value_type(entryValue) || entryValue->data.number < 0) { ERROR(srv, "auth option '%s' expects non-negative number as parameter", entryKeyStr->str); return NULL; } if (have_ttl_parameter) { ERROR(srv, "duplicate auth option '%s'", entryKeyStr->str); return NULL; } have_ttl_parameter = TRUE; ttl = entryValue->data.number; } else { ERROR(srv, "unknown auth option '%s'", entryKeyStr->str); return NULL; } LI_VALUE_END_FOREACH() if (NULL == method || NULL == realm || NULL == file) { ERROR(srv, "%s expects a hashtable/key-value list with 3 elements: method, realm and file", actname); return NULL; } if (!g_str_equal(method->str, "basic") && !g_str_equal(method->str, "digest")) { ERROR(srv, "%s: unknown method: %s", actname, method->str); return NULL; } if (g_str_equal(method->str, "digest")) { ERROR(srv, "%s: digest authentication not implemented yet", actname); return NULL; } /* load users from file */ afd = auth_file_new(wrk, file, has_realm, ttl); if (!afd) return FALSE; if (g_str_equal(method->str, "basic")) { AuthBasicData *bdata; bdata = g_slice_new(AuthBasicData); bdata->p = p; bdata->realm = li_value_extract_string(realm); bdata->backend = basic_action; bdata->data = afd; return li_action_new_function(auth_basic, NULL, auth_basic_free, bdata); } else { auth_file_free(afd); return NULL; /* li_action_new_function(NULL, NULL, auth_backend_plain_free, ad); */ } }