Beispiel #1
0
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);
}
Beispiel #2
0
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);
}
Beispiel #3
0
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);
}
Beispiel #4
0
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);
}
Beispiel #5
0
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);
}
Beispiel #6
0
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);
}
Beispiel #7
0
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);
}
Beispiel #8
0
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);
}
Beispiel #9
0
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);
}
Beispiel #10
0
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);
}
Beispiel #11
0
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);
}
Beispiel #12
0
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);
}
Beispiel #13
0
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);
}
Beispiel #14
0
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);
}
Beispiel #15
0
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);
}
Beispiel #16
0
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));
}
Beispiel #17
0
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);
}
Beispiel #18
0
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); */
	}
}
Beispiel #19
0
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);
}
Beispiel #20
0
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); */
	}
}