summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeels Hofmeyr <neels@hofmeyr.de>2019-04-11 06:58:44 +0200
committerNeels Hofmeyr <neels@hofmeyr.de>2019-04-12 01:00:16 +0200
commitb480b74192a7c00c4ea077286b921b96e42efabc (patch)
tree89829b89409dab7121d1dce89c0c455e7879cfa9
parentecef7ec3c36805e70e3da88ea694aeaf526e751d (diff)
add identifier sanitation for setting FSM instance ids
We often compose FSM instance IDs from context information, for example placing an MSISDN string or IP:port information in the FSM instance id, using osmo_fsm_inst_update_id_f(). This fails if any characters are contained that don't pass osmo_identifier_valid(). Hence it is the task of the caller to make sure only characters allowed in an FSM id are applied. Provide API to trivially allow this by replacing illegal chars: - osmo_identifier_sanitize_buf(), with access to the same set of illegal characters defined in utils.c, - osmo_fsm_inst_update_id_f_sanitize() implicitly replaces non-identifier chars. This makes it easy to add strings like '192.168.0.1:2342' or '+4987654321' to an FSM instance id, without adding string mangling to each place that sets an id; e.g. replacing with '-' to yield '192-168-0-1:2342' or '-4987654321'. Change-Id: Ia40a6f3b2243c95fe428a080b938e11d8ab771a7
-rw-r--r--include/osmocom/core/fsm.h1
-rw-r--r--include/osmocom/core/utils.h1
-rw-r--r--src/fsm.c29
-rw-r--r--src/utils.c24
4 files changed, 53 insertions, 2 deletions
diff --git a/include/osmocom/core/fsm.h b/include/osmocom/core/fsm.h
index c9e1e0cf..41d01a58 100644
--- a/include/osmocom/core/fsm.h
+++ b/include/osmocom/core/fsm.h
@@ -220,6 +220,7 @@ void osmo_fsm_inst_free(struct osmo_fsm_inst *fi);
int osmo_fsm_inst_update_id(struct osmo_fsm_inst *fi, const char *id);
int osmo_fsm_inst_update_id_f(struct osmo_fsm_inst *fi, const char *fmt, ...);
+int osmo_fsm_inst_update_id_f_sanitize(struct osmo_fsm_inst *fi, char replace_with, const char *fmt, ...);
const char *osmo_fsm_event_name(struct osmo_fsm *fsm, uint32_t event);
const char *osmo_fsm_inst_name(struct osmo_fsm_inst *fi);
diff --git a/include/osmocom/core/utils.h b/include/osmocom/core/utils.h
index 08735fdb..f27359cb 100644
--- a/include/osmocom/core/utils.h
+++ b/include/osmocom/core/utils.h
@@ -140,6 +140,7 @@ bool osmo_is_hexstr(const char *str, int min_digits, int max_digits,
bool osmo_identifier_valid(const char *str);
bool osmo_separated_identifiers_valid(const char *str, const char *sep_chars);
+void osmo_identifier_sanitize_buf(char *str, const char *sep_chars, char replace_with);
const char *osmo_escape_str(const char *str, int len);
char *osmo_escape_str_buf2(char *buf, size_t bufsize, const char *str, int in_len);
diff --git a/src/fsm.c b/src/fsm.c
index b6912c6b..c32767b2 100644
--- a/src/fsm.c
+++ b/src/fsm.c
@@ -364,6 +364,35 @@ int osmo_fsm_inst_update_id_f(struct osmo_fsm_inst *fi, const char *fmt, ...)
return 0;
}
+/*! Change id of the FSM instance using a string format, and ensuring a valid id.
+ * Replace any characters that are not permitted as FSM identifier with replace_with.
+ * \param[in] fi FSM instance.
+ * \param[in] replace_with Character to use instead of non-permitted FSM id characters.
+ * Make sure to choose a legal character, e.g. '-'.
+ * \param[in] fmt format string to compose new ID.
+ * \param[in] ... variable argument list for format string.
+ * \returns 0 if the ID was updated, otherwise -EINVAL.
+ */
+int osmo_fsm_inst_update_id_f_sanitize(struct osmo_fsm_inst *fi, char replace_with, const char *fmt, ...)
+{
+ char *id = NULL;
+ va_list ap;
+ int rc;
+
+ if (!fmt)
+ return osmo_fsm_inst_update_id(fi, NULL);
+
+ va_start(ap, fmt);
+ id = talloc_vasprintf(fi, fmt, ap);
+ va_end(ap);
+
+ osmo_identifier_sanitize_buf(id, NULL, replace_with);
+
+ rc = osmo_fsm_inst_update_id(fi, id);
+ talloc_free(id);
+ return rc;
+}
+
/*! allocate a new instance of a specified FSM
* \param[in] fsm Descriptor of the FSM
* \param[in] ctx talloc context from which to allocate memory
diff --git a/src/utils.c b/src/utils.c
index 6116d3ad..896e9177 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -553,6 +553,8 @@ bool osmo_is_hexstr(const char *str, int min_digits, int max_digits,
return true;
}
+static const char osmo_identifier_illegal_chars[] = "., {}[]()<>|~\\^`'\"?=;/+*&%$#!";
+
/*! Determine if a given identifier is valid, i.e. doesn't contain illegal chars
* \param[in] str String to validate
* \param[in] sep_chars Permitted separation characters between identifiers.
@@ -561,7 +563,6 @@ bool osmo_is_hexstr(const char *str, int min_digits, int max_digits,
bool osmo_separated_identifiers_valid(const char *str, const char *sep_chars)
{
/* characters that are illegal in names */
- static const char illegal_chars[] = "., {}[]()<>|~\\^`'\"?=;/+*&%$#!";
unsigned int i;
size_t len;
@@ -578,7 +579,7 @@ bool osmo_separated_identifiers_valid(const char *str, const char *sep_chars)
if (!isprint((int)str[i]))
return false;
/* check for some explicit reserved control characters */
- if (strchr(illegal_chars, str[i]))
+ if (strchr(osmo_identifier_illegal_chars, str[i]))
return false;
}
@@ -594,6 +595,25 @@ bool osmo_identifier_valid(const char *str)
return osmo_separated_identifiers_valid(str, NULL);
}
+/*! Replace characters in the given string buffer so that it is guaranteed to pass osmo_separated_identifiers_valid().
+ * To guarantee passing osmo_separated_identifiers_valid(), replace_with must not itself be an illegal character. If in
+ * doubt, use '-'.
+ * \param[inout] str Identifier to sanitize, must be nul terminated and in a writable buffer.
+ * \param[in] sep_chars Additional characters that are allowed besides osmo_identifier_illegal_chars.
+ * \param[in] replace_with Replace any illegal characters with this character.
+ */
+void osmo_identifier_sanitize_buf(char *str, const char *sep_chars, char replace_with)
+{
+ char *pos;
+ if (!str)
+ return;
+ for (pos = str; *pos; pos++) {
+ if (strchr(osmo_identifier_illegal_chars, *pos)
+ || (sep_chars && strchr(sep_chars, *pos)))
+ *pos = replace_with;
+ }
+}
+
/*! Like osmo_escape_str_buf2, but with unusual ordering of arguments, and may sometimes return string constants instead
* of writing to buf for error cases or empty input.
* Most *_buf() functions have the buffer and size as first arguments, here the arguments are last.