diff --git a/include/h.h b/include/h.h index 582084f0e..fea283399 100644 --- a/include/h.h +++ b/include/h.h @@ -1207,6 +1207,7 @@ extern void _del_name_list(NameList **list, const char *name); extern NameList *duplicate_name_list(NameList *e); extern NameList *find_name_list(NameList *list, const char *name); extern NameList *find_name_list_match(NameList *list, const char *name); +extern NameList *find_name_list_integer(NameList *list, int v); extern int minimum_msec_since_last_run(struct timeval *tv_old, long minimum); extern int unrl_utf8_validate(const char *str, const char **end); extern char *unrl_utf8_make_valid(const char *str, char *outputbuf, size_t outputbuflen, int strict_length_check); diff --git a/include/struct.h b/include/struct.h index b8567c069..90613f7e1 100644 --- a/include/struct.h +++ b/include/struct.h @@ -2242,6 +2242,7 @@ struct SecurityGroup { int tls; NameList *ip; ConfigItem_mask *mask; + NameList *server_port; NameList *security_group; char *prettyrule; /* ::rule as a string */ CRuleNode *rule; /**< parsed crule */ @@ -2256,6 +2257,7 @@ struct SecurityGroup { int exclude_tls; NameList *exclude_ip; ConfigItem_mask *exclude_mask; + NameList *exclude_server_port; NameList *exclude_security_group; char *exclude_prettyrule; /* ::exclude-rule as a string */ CRuleNode *exclude_rule; /**< parsed crule */ diff --git a/src/list.c b/src/list.c index eb848b5cd..3bb8d76f9 100644 --- a/src/list.c +++ b/src/list.c @@ -618,6 +618,16 @@ NameList *find_name_list_match(NameList *list, const char *name) return NULL; } +/** Find an entry in a NameList - argument is an integer. + * @ingroup ListFunctions + */ +NameList *find_name_list_integer(NameList *list, int v) +{ + char buf[32]; + snprintf(buf, sizeof(buf), "%d", v); + return find_name_list(list, buf); +} + NameValuePrioList *add_nvplist(NameValuePrioList **lst, int priority, const char *name, const char *value) { va_list vl; diff --git a/src/modules/crule.c b/src/modules/crule.c index 13a68102d..467843711 100644 --- a/src/modules/crule.c +++ b/src/modules/crule.c @@ -145,6 +145,7 @@ static int crule_match_asn(crule_context *, int, void **); static int crule_match_certfp(crule_context *, int, void **); static int crule_match_realname(crule_context *, int, void **); static int crule_unicode_count(crule_context *, int, void **); +static int crule_server_port(crule_context *, int, void **); /* parsing function prototypes - local! */ static int crule_gettoken(crule_token *next_tokp, const char **str); @@ -206,6 +207,7 @@ struct crule_funclistent crule_funclist[] = { {"match_certfp", 1, crule_match_certfp}, {"match_realname", 1, crule_match_realname}, {"unicode_count", 1, crule_unicode_count}, + {"server_port", 0, crule_server_port}, {"", 0, NULL} /* this must be here to mark end of list */ }; @@ -566,6 +568,14 @@ static int crule_unicode_count(crule_context *context, int numargs, void *crulea return 0; } +static int crule_server_port(crule_context *context, int numargs, void *crulearg[]) +{ + if (context && context->client) + return get_server_port(context->client); + + return 0; +} + /** Evaluate a connection rule. * @param[in] rule Rule to evalute. * @return Non-zero if the rule allows the connection, zero otherwise. diff --git a/src/securitygroup.c b/src/securitygroup.c index c71947763..e057b276a 100644 --- a/src/securitygroup.c +++ b/src/securitygroup.c @@ -246,6 +246,9 @@ int test_match_item(ConfigFile *conf, ConfigEntry *cep, int *errors) if (!strcmp(cep->name, "ip") || !strcmp(cep->name, "exclude-ip")) { } else + if (!strcmp(cep->name, "server-port") || !strcmp(cep->name, "exclude-server-port")) + { + } else if (!strcmp(cep->name, "security-group") || !strcmp(cep->name, "exclude-security-group")) { } else @@ -437,6 +440,10 @@ int conf_match_item(ConfigFile *conf, ConfigEntry *cep, SecurityGroup **block) { unreal_add_names(&s->ip, cep); } + else if (!strcmp(cep->name, "server-port")) + { + unreal_add_names(&s->server_port, cep); + } else if (!strcmp(cep->name, "security-group")) { unreal_add_names(&s->security_group, cep); @@ -473,6 +480,10 @@ int conf_match_item(ConfigFile *conf, ConfigEntry *cep, SecurityGroup **block) { unreal_add_names(&s->exclude_ip, cep); } + else if (!strcmp(cep->name, "exclude-server-port")) + { + unreal_add_names(&s->exclude_server_port, cep); + } else if (!strcmp(cep->name, "exclude-security-group")) { unreal_add_names(&s->exclude_security_group, cep); @@ -657,6 +668,8 @@ void free_security_group(SecurityGroup *s) safe_free(s->exclude_prettyrule); free_entire_name_list(s->ip); free_entire_name_list(s->exclude_ip); + free_entire_name_list(s->server_port); + free_entire_name_list(s->exclude_server_port); free_nvplist(s->extended); free_nvplist(s->exclude_extended); free_nvplist(s->printable_list); @@ -691,6 +704,8 @@ SecurityGroup *duplicate_security_group(SecurityGroup *s) } n->ip = duplicate_name_list(s->ip); n->exclude_ip = duplicate_name_list(s->exclude_ip); + n->server_port = duplicate_name_list(s->server_port); + n->exclude_server_port = duplicate_name_list(s->exclude_server_port); n->extended = duplicate_nvplist(s->extended); n->exclude_extended = duplicate_nvplist(s->exclude_extended); n->printable_list = duplicate_nvplist(s->printable_list); @@ -876,6 +891,8 @@ int user_allowed_by_security_group_context(Client *client, SecurityGroup *s, cru goto user_not_allowed; if (s->exclude_ip && unreal_match_iplist(client, s->exclude_ip)) goto user_not_allowed; + if (s->exclude_server_port && find_name_list_integer(s->exclude_server_port, get_server_port(client))) + goto user_not_allowed; if (s->exclude_rule && crule_eval(context, s->exclude_rule)) goto user_not_allowed; if (s->exclude_extended && user_matches_extended_list(client, s->exclude_extended)) @@ -925,6 +942,8 @@ int user_allowed_by_security_group_context(Client *client, SecurityGroup *s, cru goto user_allowed; if (s->ip && unreal_match_iplist(client, s->ip)) goto user_allowed; + if (s->server_port && find_name_list_integer(s->server_port, get_server_port(client))) + goto user_allowed; if (s->rule && crule_eval(context, s->rule)) goto user_allowed; if (s->extended && user_matches_extended_list(client, s->extended))