summaryrefslogtreecommitdiffstats
path: root/openbsc/src/osmo-bsc_nat
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <holger@moiji-mobile.com>2015-06-08 18:33:28 +0200
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2015-07-01 08:16:41 +0200
commit694d98042f1adfad0e54f97d0e4c8787c5fccbac (patch)
tree93034ab4d9e3657b9148ce3f17dc342a13ffb923 /openbsc/src/osmo-bsc_nat
parente2ac6b77feecc5b7194a308bbd11e206c4a41fcb (diff)
nat: After we identified the bsc check the key
We are using the token to find the right bsc_config and then we can use the last_rand of the bsc_connection to calculate the expected result and try to compare it with a time constant(???) memcmp.
Diffstat (limited to 'openbsc/src/osmo-bsc_nat')
-rw-r--r--openbsc/src/osmo-bsc_nat/bsc_nat.c61
-rw-r--r--openbsc/src/osmo-bsc_nat/bsc_nat_vty.c32
2 files changed, 89 insertions, 4 deletions
diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat.c b/openbsc/src/osmo-bsc_nat/bsc_nat.c
index 983770925..581193e5a 100644
--- a/openbsc/src/osmo-bsc_nat/bsc_nat.c
+++ b/openbsc/src/osmo-bsc_nat/bsc_nat.c
@@ -51,6 +51,8 @@
#include <osmocom/ctrl/control_cmd.h>
#include <osmocom/ctrl/control_if.h>
+#include <osmocom/crypt/auth.h>
+
#include <osmocom/core/application.h>
#include <osmocom/core/talloc.h>
@@ -993,11 +995,57 @@ static void ipaccess_close_bsc(void *data)
bsc_close_connection(conn);
}
+/* Wishful thinking to generate a constant time compare */
+static int constant_time_cmp(const uint8_t *exp, const uint8_t *rel, const int count)
+{
+ int x = 0, i;
+
+ for (i = 0; i < count; ++i)
+ x |= exp[i] ^ rel[i];
+
+ return x != 0;
+}
+
+static int verify_key(struct bsc_connection *conn, struct bsc_config *conf, const uint8_t *key, const int keylen)
+{
+ struct osmo_auth_vector vec;
+
+ struct osmo_sub_auth_data auth = {
+ .type = OSMO_AUTH_TYPE_GSM,
+ .algo = OSMO_AUTH_ALG_MILENAGE,
+ };
+
+ /* expect a specific keylen */
+ if (keylen != 8) {
+ LOGP(DNAT, LOGL_ERROR, "Key length is wrong: %d for bsc nr %d\n",
+ keylen, conf->nr);
+ return 0;
+ }
+
+ memcpy(auth.u.umts.opc, conf->key, 16);
+ memcpy(auth.u.umts.k, conf->key, 16);
+ memset(auth.u.umts.amf, 0, 2);
+ auth.u.umts.sqn = 0;
+
+ memset(&vec, 0, sizeof(vec));
+ osmo_auth_gen_vec(&vec, &auth, conn->last_rand);
+
+ if (vec.res_len != 8) {
+ LOGP(DNAT, LOGL_ERROR, "Res length is wrong: %d for bsc nr %d\n",
+ keylen, conf->nr);
+ return 0;
+ }
+
+ return constant_time_cmp(vec.res, key, 8) == 0;
+}
+
static void ipaccess_auth_bsc(struct tlv_parsed *tvp, struct bsc_connection *bsc)
{
struct bsc_config *conf;
const char *token = (const char *) TLVP_VAL(tvp, IPAC_IDTAG_UNITNAME);
int len = TLVP_LEN(tvp, IPAC_IDTAG_UNITNAME);
+ const uint8_t *xres = TLVP_VAL(tvp, 0x24);
+ const int xlen = TLVP_LEN(tvp, 0x24);
if (bsc->cfg) {
LOGP(DNAT, LOGL_ERROR, "Reauth on fd %d bsc nr %d\n",
@@ -1033,6 +1081,15 @@ static void ipaccess_auth_bsc(struct tlv_parsed *tvp, struct bsc_connection *bsc
return;
}
+ /* We have set a key and expect it to be present */
+ if (conf->key_present && !verify_key(bsc, conf, xres, xlen - 1)) {
+ LOGP(DNAT, LOGL_ERROR,
+ "Wrong key for bsc nr %d fd: %d.\n", conf->nr,
+ bsc->write_queue.bfd.fd);
+ bsc_close_connection(bsc);
+ return;
+ }
+
rate_ctr_inc(&conf->stats.ctrg->ctr[BCFG_CTR_NET_RECONN]);
bsc->authenticated = 1;
bsc->cfg = conf;
@@ -1227,9 +1284,9 @@ exit:
if (msg->l2h[0] == IPAC_MSGT_ID_RESP && msgb_l2len(msg) > 2) {
struct tlv_parsed tvp;
int ret;
- ret = ipa_ccm_idtag_parse(&tvp,
+ ret = ipa_ccm_idtag_parse_off(&tvp,
(unsigned char *) msg->l2h + 2,
- msgb_l2len(msg) - 2);
+ msgb_l2len(msg) - 2, 0);
if (ret < 0) {
LOGP(DNAT, LOGL_ERROR, "ignoring IPA response "
"message with malformed TLVs\n");
diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c
index 821e5226a..981168cc1 100644
--- a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c
+++ b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c
@@ -1,6 +1,6 @@
/* OpenBSC NAT interface to quagga VTY */
-/* (C) 2010-2013 by Holger Hans Peter Freyther
- * (C) 2010-2013 by On-Waves
+/* (C) 2010-2015 by Holger Hans Peter Freyther
+ * (C) 2010-2015 by On-Waves
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
@@ -151,6 +151,8 @@ static void config_write_bsc_single(struct vty *vty, struct bsc_config *bsc)
{
vty_out(vty, " bsc %u%s", bsc->nr, VTY_NEWLINE);
vty_out(vty, " token %s%s", bsc->token, VTY_NEWLINE);
+ if (bsc->key_present)
+ vty_out(vty, " auth-key %s%s", osmo_hexdump(bsc->key, 16), VTY_NEWLINE);
dump_lac(vty, &bsc->lac_list);
if (bsc->description)
vty_out(vty, " description %s%s", bsc->description, VTY_NEWLINE);
@@ -814,6 +816,30 @@ DEFUN(cfg_bsc_token, cfg_bsc_token_cmd, "token TOKEN",
return CMD_SUCCESS;
}
+DEFUN(cfg_bsc_auth_key, cfg_bsc_auth_key_cmd,
+ "auth-key KEY",
+ "Authentication (secret) key configuration\n"
+ "Non null security key\n")
+{
+ struct bsc_config *conf = vty->index;
+
+ memset(conf->key, 0, sizeof(conf->key));
+ osmo_hexparse(argv[0], conf->key, sizeof(conf->key));
+ conf->key_present = 1;
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bsc_no_auth_key, cfg_bsc_no_auth_key_cmd,
+ "no auth-key",
+ NO_STR "Authentication (secret) key configuration\n")
+{
+ struct bsc_config *conf = vty->index;
+
+ memset(conf->key, 0, sizeof(conf->key));
+ conf->key_present = 0;
+ return CMD_SUCCESS;
+}
+
DEFUN(cfg_bsc_lac, cfg_bsc_lac_cmd, "location_area_code <0-65535>",
"Add the Location Area Code (LAC) of this BSC\n" "LAC\n")
{
@@ -1202,6 +1228,8 @@ int bsc_nat_vty_init(struct bsc_nat *nat)
install_node(&bsc_node, config_write_bsc);
vty_install_default(NAT_BSC_NODE);
install_element(NAT_BSC_NODE, &cfg_bsc_token_cmd);
+ install_element(NAT_BSC_NODE, &cfg_bsc_auth_key_cmd);
+ install_element(NAT_BSC_NODE, &cfg_bsc_no_auth_key_cmd);
install_element(NAT_BSC_NODE, &cfg_bsc_lac_cmd);
install_element(NAT_BSC_NODE, &cfg_bsc_no_lac_cmd);
install_element(NAT_BSC_NODE, &cfg_bsc_paging_cmd);