--- openbsc/include/openbsc/db.h | 2 ++ openbsc/src/libmsc/db.c | 77 +++++++++++++++++++++++++++++++++++++++- openbsc/src/libmsc/token_auth.c | 7 ++-- openbsc/src/osmo-nitb/bsc_hack.c | 5 +++ 4 files changed, 86 insertions(+), 5 deletions(-)
diff --git a/openbsc/include/openbsc/db.h b/openbsc/include/openbsc/db.h index 6699a86..348a627 100644 --- a/openbsc/include/openbsc/db.h +++ b/openbsc/include/openbsc/db.h @@ -79,4 +79,6 @@ int db_store_counter(struct osmo_counter *ctr); struct rate_ctr_group; int db_store_rate_ctr_group(struct rate_ctr_group *ctrg);
+char * db_get_text(const char *key); + #endif /* _DB_H */ diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c index 656c661..1e8f000 100644 --- a/openbsc/src/libmsc/db.c +++ b/openbsc/src/libmsc/db.c @@ -45,11 +45,13 @@ static char *db_basename = NULL; static char *db_dirname = NULL; static dbi_conn conn;
-#define SCHEMA_REVISION "4" +#define SCHEMA_REVISION "5"
enum { SCHEMA_META, INSERT_META, + SCHEMA_TEXT, + INSERT_TEXT, SCHEMA_SUBSCRIBER, SCHEMA_AUTH, SCHEMA_EQUIPMENT, @@ -73,6 +75,16 @@ static const char *create_stmts[] = { "(key, value) " "VALUES " "('revision', " SCHEMA_REVISION ")", + [SCHEMA_TEXT] = "CREATE TABLE IF NOT EXISTS Text (" + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + "key TEXT UNIQUE NOT NULL, " + "value TEXT NOT NULL" + ")", + [INSERT_TEXT] = "INSERT OR IGNORE INTO Text " + "(key, value) " + "VALUES " + "('auth_token_sms', 'Welcome to the GSM network. " + "Your IMSI is %s, auth token is %08X, phone no is %s.')", [SCHEMA_SUBSCRIBER] = "CREATE TABLE IF NOT EXISTS Subscriber (" "id INTEGER PRIMARY KEY AUTOINCREMENT, " "created TIMESTAMP NOT NULL, " @@ -367,6 +379,40 @@ rollback: return -EINVAL; }
+static int update_db_revision_4(void) +{ + dbi_result result; + + result = dbi_conn_query(conn, create_stmts[SCHEMA_TEXT]); + if (!result) { + LOGP(DDB, LOGL_ERROR, + "Failed to create Text table (upgrade from rev 4).\n"); + return -EINVAL; + } + dbi_result_free(result); + + result = dbi_conn_query(conn, create_stmts[INSERT_TEXT]); + if (!result) { + LOGP(DDB, LOGL_ERROR, + "Failed to inserting Text (upgrade from rev 4).\n"); + return -EINVAL; + } + dbi_result_free(result); + + result = dbi_conn_query(conn, + "UPDATE Meta " + "SET value = '5' " + "WHERE key = 'revision'"); + if (!result) { + LOGP(DDB, LOGL_ERROR, + "Failed to update DB schema revision (upgrade from rev 4).\n"); + return -EINVAL; + } + dbi_result_free(result); + + return 0; +} + static int check_db_revision(void) { dbi_result result; @@ -398,6 +444,12 @@ static int check_db_revision(void) dbi_result_free(result); return -EINVAL; } + } else if (!strcmp(rev_s, "4")) { + if (update_db_revision_4()) { + LOGP(DDB, LOGL_FATAL, "Failed to update database from schema revision '%s'.\n", rev_s); + dbi_result_free(result); + return -EINVAL; + } } else if (!strcmp(rev_s, SCHEMA_REVISION)) { /* everything is fine */ } else { @@ -498,6 +550,29 @@ int db_fini(void) return 0; }
+char * db_get_text(const char *key) { + dbi_result result; + const char * string; + char * text; + unsigned int len; + + result = dbi_conn_queryf(conn, + "SELECT value FROM Text WHERE key='%s'", key); + if (!result) + return NULL; + + if (!dbi_result_next_row(result)) { + dbi_result_free(result); + return NULL; + } + string = dbi_result_get_string(result, "value"); + text = talloc_strdup(NULL, string); + + dbi_result_free(result); + + return text; +} + struct gsm_subscriber *db_create_subscriber(const char *imsi) { dbi_result result; diff --git a/openbsc/src/libmsc/token_auth.c b/openbsc/src/libmsc/token_auth.c index 45b5a8e..3ee8564 100644 --- a/openbsc/src/libmsc/token_auth.c +++ b/openbsc/src/libmsc/token_auth.c @@ -29,20 +29,19 @@ #include <openbsc/chan_alloc.h> #include <openbsc/db.h>
-#define TOKEN_SMS_TEXT "HAR 2009 GSM. Register at http://har2009.gnumonks.org/ " \ - "Your IMSI is %s, auth token is %08X, phone no is %s." +extern char * auth_token_sms_text;
static char *build_sms_string(struct gsm_subscriber *subscr, uint32_t token) { char *sms_str; unsigned int len;
- len = strlen(subscr->imsi) + 8 + strlen(TOKEN_SMS_TEXT); + len = strlen(subscr->imsi) + 8 + strlen(auth_token_sms_text) + strlen(subscr->extension); sms_str = talloc_size(tall_bsc_ctx, len); if (!sms_str) return NULL;
- snprintf(sms_str, len, TOKEN_SMS_TEXT, subscr->imsi, token, + snprintf(sms_str, len, auth_token_sms_text, subscr->imsi, token, subscr->extension); sms_str[len-1] = '\0';
diff --git a/openbsc/src/osmo-nitb/bsc_hack.c b/openbsc/src/osmo-nitb/bsc_hack.c index 031cb99..9d552c2 100644 --- a/openbsc/src/osmo-nitb/bsc_hack.c +++ b/openbsc/src/osmo-nitb/bsc_hack.c @@ -67,6 +67,9 @@ static int use_db_counter = 1; #define DB_SYNC_INTERVAL 60, 0 #define EXPIRE_INTERVAL 10, 0
+/* for token auth */ +char * auth_token_sms_text = ""; + static struct osmo_timer_list db_sync_timer;
static void create_pcap_file(char *file) @@ -322,6 +325,8 @@ int main(int argc, char **argv) } printf("DB: Database prepared.\n");
+ auth_token_sms_text = db_get_text("auth_token_sms"); + /* setup the timer */ db_sync_timer.cb = db_sync_timer_cb; db_sync_timer.data = NULL;
On Fri, Nov 14, 2014 at 06:47:40PM -0600, Ruben Pollan wrote:
Good Morning,
why does this need to go into the DB and not the configuration file? What is your stand on checking the configured string for the right amount of printf placeholders?
holger
Good morning,
Quoting Holger Hans Peter Freyther (2014-11-15 03:11:46)
why does this need to go into the DB and not the configuration file?
Our first attempt was to do it in the configuration file, but we realized that vty doesn't have support for strings with spaces. Or did we miss something?
We decided that was easier to add it to the database than to extend vty to parse strings with " or other way to support spaces.
What is your stand on checking the configured string for the right amount of printf placeholders?
You are right, this is not great. After discussing it with ciaby we decided that might make more sense to do something like:
snprintf(sms_str, len, "%s IMSI: %s Token: %08X Ext: %s" auth_token_sms_text, subscr->imsi, token, subscr->extension);
So the auth_token_sms_text don't have any placeholders it's just the introductory text. What do you think?
--- openbsc/include/openbsc/db.h | 2 ++ openbsc/src/libmsc/db.c | 76 +++++++++++++++++++++++++++++++++++++++- openbsc/src/libmsc/token_auth.c | 18 +++++++--- openbsc/src/osmo-nitb/bsc_hack.c | 5 +++ 4 files changed, 95 insertions(+), 6 deletions(-)
diff --git a/openbsc/include/openbsc/db.h b/openbsc/include/openbsc/db.h index 6699a86..348a627 100644 --- a/openbsc/include/openbsc/db.h +++ b/openbsc/include/openbsc/db.h @@ -79,4 +79,6 @@ int db_store_counter(struct osmo_counter *ctr); struct rate_ctr_group; int db_store_rate_ctr_group(struct rate_ctr_group *ctrg);
+char * db_get_text(const char *key); + #endif /* _DB_H */ diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c index 656c661..bac854c 100644 --- a/openbsc/src/libmsc/db.c +++ b/openbsc/src/libmsc/db.c @@ -45,11 +45,13 @@ static char *db_basename = NULL; static char *db_dirname = NULL; static dbi_conn conn;
-#define SCHEMA_REVISION "4" +#define SCHEMA_REVISION "5"
enum { SCHEMA_META, INSERT_META, + SCHEMA_TEXT, + INSERT_TEXT, SCHEMA_SUBSCRIBER, SCHEMA_AUTH, SCHEMA_EQUIPMENT, @@ -73,6 +75,15 @@ static const char *create_stmts[] = { "(key, value) " "VALUES " "('revision', " SCHEMA_REVISION ")", + [SCHEMA_TEXT] = "CREATE TABLE IF NOT EXISTS Text (" + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + "key TEXT UNIQUE NOT NULL, " + "value TEXT NOT NULL" + ")", + [INSERT_TEXT] = "INSERT OR IGNORE INTO Text " + "(key, value) " + "VALUES " + "('auth_token_sms', 'Welcome to the GSM network.')", [SCHEMA_SUBSCRIBER] = "CREATE TABLE IF NOT EXISTS Subscriber (" "id INTEGER PRIMARY KEY AUTOINCREMENT, " "created TIMESTAMP NOT NULL, " @@ -367,6 +378,40 @@ rollback: return -EINVAL; }
+static int update_db_revision_4(void) +{ + dbi_result result; + + result = dbi_conn_query(conn, create_stmts[SCHEMA_TEXT]); + if (!result) { + LOGP(DDB, LOGL_ERROR, + "Failed to create Text table (upgrade from rev 4).\n"); + return -EINVAL; + } + dbi_result_free(result); + + result = dbi_conn_query(conn, create_stmts[INSERT_TEXT]); + if (!result) { + LOGP(DDB, LOGL_ERROR, + "Failed to inserting Text (upgrade from rev 4).\n"); + return -EINVAL; + } + dbi_result_free(result); + + result = dbi_conn_query(conn, + "UPDATE Meta " + "SET value = '5' " + "WHERE key = 'revision'"); + if (!result) { + LOGP(DDB, LOGL_ERROR, + "Failed to update DB schema revision (upgrade from rev 4).\n"); + return -EINVAL; + } + dbi_result_free(result); + + return 0; +} + static int check_db_revision(void) { dbi_result result; @@ -398,6 +443,12 @@ static int check_db_revision(void) dbi_result_free(result); return -EINVAL; } + } else if (!strcmp(rev_s, "4")) { + if (update_db_revision_4()) { + LOGP(DDB, LOGL_FATAL, "Failed to update database from schema revision '%s'.\n", rev_s); + dbi_result_free(result); + return -EINVAL; + } } else if (!strcmp(rev_s, SCHEMA_REVISION)) { /* everything is fine */ } else { @@ -498,6 +549,29 @@ int db_fini(void) return 0; }
+char * db_get_text(const char *key) { + dbi_result result; + const char * string; + char * text; + unsigned int len; + + result = dbi_conn_queryf(conn, + "SELECT value FROM Text WHERE key='%s'", key); + if (!result) + return NULL; + + if (!dbi_result_next_row(result)) { + dbi_result_free(result); + return NULL; + } + string = dbi_result_get_string(result, "value"); + text = talloc_strdup(NULL, string); + + dbi_result_free(result); + + return text; +} + struct gsm_subscriber *db_create_subscriber(const char *imsi) { dbi_result result; diff --git a/openbsc/src/libmsc/token_auth.c b/openbsc/src/libmsc/token_auth.c index 45b5a8e..80660dd 100644 --- a/openbsc/src/libmsc/token_auth.c +++ b/openbsc/src/libmsc/token_auth.c @@ -20,6 +20,7 @@ */
#include <stdio.h> +#include <stdlib.h> #include <osmocom/core/talloc.h> #include <openbsc/signal.h> #include <openbsc/gsm_data.h> @@ -29,23 +30,30 @@ #include <openbsc/chan_alloc.h> #include <openbsc/db.h>
-#define TOKEN_SMS_TEXT "HAR 2009 GSM. Register at http://har2009.gnumonks.org/ " \ - "Your IMSI is %s, auth token is %08X, phone no is %s." +extern char * auth_token_sms_text; + +#define TOKEN_SMS_FORMAT "%s IMSI: %s Token: %08X Ext: %s"
static char *build_sms_string(struct gsm_subscriber *subscr, uint32_t token) { char *sms_str; unsigned int len;
- len = strlen(subscr->imsi) + 8 + strlen(TOKEN_SMS_TEXT); + len = strlen(TOKEN_SMS_FORMAT) + strlen(subscr->imsi) + + strlen(auth_token_sms_text) + strlen(subscr->extension); sms_str = talloc_size(tall_bsc_ctx, len); if (!sms_str) return NULL;
- snprintf(sms_str, len, TOKEN_SMS_TEXT, subscr->imsi, token, - subscr->extension); + snprintf(sms_str, len, TOKEN_SMS_FORMAT, auth_token_sms_text, subscr->imsi, + token, subscr->extension); sms_str[len-1] = '\0';
+ if (strlen(sms_str) > 160) { + fprintf(stderr, "Token auth sms longer than 160 char: '%s'\n", sms_str); + exit(1); + } + return sms_str; }
diff --git a/openbsc/src/osmo-nitb/bsc_hack.c b/openbsc/src/osmo-nitb/bsc_hack.c index 031cb99..9d552c2 100644 --- a/openbsc/src/osmo-nitb/bsc_hack.c +++ b/openbsc/src/osmo-nitb/bsc_hack.c @@ -67,6 +67,9 @@ static int use_db_counter = 1; #define DB_SYNC_INTERVAL 60, 0 #define EXPIRE_INTERVAL 10, 0
+/* for token auth */ +char * auth_token_sms_text = ""; + static struct osmo_timer_list db_sync_timer;
static void create_pcap_file(char *file) @@ -322,6 +325,8 @@ int main(int argc, char **argv) } printf("DB: Database prepared.\n");
+ auth_token_sms_text = db_get_text("auth_token_sms"); + /* setup the timer */ db_sync_timer.cb = db_sync_timer_cb; db_sync_timer.data = NULL;
On Sat, Nov 15, 2014 at 02:03:31PM -0600, Ruben Pollan wrote:
Good morning,
Good Evening!
You are right, this is not great. After discussing it with ciaby we decided that might make more sense to do something like:
snprintf(sms_str, len, "%s IMSI: %s Token: %08X Ext: %s" auth_token_sms_text, subscr->imsi, token, subscr->extension);
So the auth_token_sms_text don't have any placeholders it's just the introductory text. What do you think?
Yes, it would be missing i18n.. but so does the entire OpenBSC codebase. I would really prefer to set this through the VTY than to put it into a database. Using ".TEXT" inside the VTY command string you can match more than just a single word. I think '%' is still not possible though.
holger