sgsn: Add a subscriber based authentication phase
This implements the MAP way of subscriber validation when the MS tries to perform an Attach Request: 1. perform authentication (optionally invoke the sendAuthInfo procedure), starts the Auth & Ciph procedure 2. perform update location 3. insert subscriber data 4. finish the update location 5. Attach Accept / Attach Reject The authentication triplets are used and eventually updated if all of them have been used. This is currently accessible via the VTY interface by the following commands: - update-subscriber imsi IMSI update-auth-info - update-subscriber imsi IMSI update-location-result (ok|ERR-CAUSE) Sponsored-by: On-Waves ehf
This commit is contained in:
parent
7921ab1593
commit
98a95ac17f
|
@ -296,16 +296,25 @@ struct gsm_auth_tuple *sgsn_auth_get_tuple(struct sgsn_mm_ctx *mmctx,
|
|||
/*
|
||||
* GPRS subscriber data
|
||||
*/
|
||||
#define GPRS_SUBSCRIBER_UPDATE_PENDING (1 << 16)
|
||||
#define GPRS_SUBSCRIBER_CANCELLED (1 << 17)
|
||||
#define GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING (1 << 16)
|
||||
#define GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING (1 << 17)
|
||||
#define GPRS_SUBSCRIBER_CANCELLED (1 << 18)
|
||||
|
||||
#define GPRS_SUBSCRIBER_UPDATE_PENDING_MASK ( \
|
||||
GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING | \
|
||||
GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING \
|
||||
)
|
||||
|
||||
void gprs_subscr_init(struct sgsn_instance *sgi);
|
||||
int gprs_subscr_request_update(struct sgsn_mm_ctx *mmctx);
|
||||
int gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx);
|
||||
int gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx);
|
||||
void gprs_subscr_delete(struct gsm_subscriber *subscr);
|
||||
struct gsm_subscriber *gprs_subscr_get_or_create(const char *imsi);
|
||||
struct gsm_subscriber *gprs_subscr_get_or_create_by_mmctx( struct sgsn_mm_ctx *mmctx);
|
||||
struct gsm_subscriber *gprs_subscr_get_by_imsi(const char *imsi);
|
||||
void gprs_subscr_put_and_cancel(struct gsm_subscriber *subscr);
|
||||
void gprs_subscr_update(struct gsm_subscriber *subscr);
|
||||
void gprs_subscr_update_auth_info(struct gsm_subscriber *subscr);
|
||||
|
||||
/* Called on subscriber data updates */
|
||||
void sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx,
|
||||
|
|
|
@ -92,9 +92,18 @@ void gprs_subscr_put_and_cancel(struct gsm_subscriber *subscr)
|
|||
gprs_subscr_delete(subscr);
|
||||
}
|
||||
|
||||
int gprs_subscr_query(struct gsm_subscriber *subscr)
|
||||
int gprs_subscr_query_auth_info(struct gsm_subscriber *subscr)
|
||||
{
|
||||
/* TODO: Implement remote query to MSC, ... */
|
||||
/* TODO: Implement remote query to HLR, ... */
|
||||
|
||||
LOGMMCTXP(LOGL_INFO, subscr->sgsn_data->mm,
|
||||
"subscriber auth info is not available (remote query NYI)\n");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
int gprs_subscr_location_update(struct gsm_subscriber *subscr)
|
||||
{
|
||||
/* TODO: Implement remote query to HLR, ... */
|
||||
|
||||
LOGMMCTXP(LOGL_INFO, subscr->sgsn_data->mm,
|
||||
"subscriber data is not available (remote query NYI)\n");
|
||||
|
@ -105,56 +114,80 @@ void gprs_subscr_update(struct gsm_subscriber *subscr)
|
|||
{
|
||||
LOGMMCTXP(LOGL_DEBUG, subscr->sgsn_data->mm, "Updating subscriber data\n");
|
||||
|
||||
subscr->flags &= ~GPRS_SUBSCRIBER_UPDATE_PENDING;
|
||||
subscr->flags &= ~GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING;
|
||||
subscr->flags &= ~GSM_SUBSCRIBER_FIRST_CONTACT;
|
||||
|
||||
sgsn_update_subscriber_data(subscr->sgsn_data->mm, subscr);
|
||||
}
|
||||
|
||||
int gprs_subscr_request_update(struct sgsn_mm_ctx *mmctx)
|
||||
void gprs_subscr_update_auth_info(struct gsm_subscriber *subscr)
|
||||
{
|
||||
LOGMMCTXP(LOGL_DEBUG, subscr->sgsn_data->mm,
|
||||
"Updating subscriber authentication info\n");
|
||||
|
||||
subscr->flags &= ~GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING;
|
||||
subscr->flags &= ~GSM_SUBSCRIBER_FIRST_CONTACT;
|
||||
|
||||
sgsn_update_subscriber_data(subscr->sgsn_data->mm, subscr);
|
||||
}
|
||||
|
||||
struct gsm_subscriber *gprs_subscr_get_or_create_by_mmctx(struct sgsn_mm_ctx *mmctx)
|
||||
{
|
||||
struct gsm_subscriber *subscr = NULL;
|
||||
int need_update = 0;
|
||||
int rc;
|
||||
|
||||
LOGMMCTXP(LOGL_DEBUG, mmctx, "Requesting subscriber data update\n");
|
||||
if (mmctx->subscr)
|
||||
return subscr_get(mmctx->subscr);
|
||||
|
||||
if (mmctx->subscr) {
|
||||
subscr = subscr_get(mmctx->subscr);
|
||||
} else if (mmctx->imsi[0]) {
|
||||
if (mmctx->imsi[0])
|
||||
subscr = gprs_subscr_get_by_imsi(mmctx->imsi);
|
||||
need_update = 1;
|
||||
}
|
||||
|
||||
if (!subscr) {
|
||||
subscr = gprs_subscr_get_or_create(mmctx->imsi);
|
||||
subscr->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
|
||||
need_update = 1;
|
||||
}
|
||||
|
||||
if (strcpy(subscr->equipment.imei, mmctx->imei) != 0) {
|
||||
strncpy(subscr->equipment.imei, mmctx->imei, GSM_IMEI_LENGTH-1);
|
||||
subscr->equipment.imei[GSM_IMEI_LENGTH-1] = 0;
|
||||
need_update = 1;
|
||||
}
|
||||
|
||||
if (subscr->lac != mmctx->ra.lac) {
|
||||
if (subscr->lac != mmctx->ra.lac)
|
||||
subscr->lac = mmctx->ra.lac;
|
||||
need_update = 1;
|
||||
}
|
||||
|
||||
if (need_update) {
|
||||
subscr->flags |= GPRS_SUBSCRIBER_UPDATE_PENDING;
|
||||
if (!mmctx->subscr) {
|
||||
subscr->sgsn_data->mm = mmctx;
|
||||
mmctx->subscr = subscr_get(subscr);
|
||||
}
|
||||
subscr->sgsn_data->mm = mmctx;
|
||||
mmctx->subscr = subscr_get(subscr);
|
||||
|
||||
rc = gprs_subscr_query(subscr);
|
||||
subscr_put(subscr);
|
||||
return rc;
|
||||
}
|
||||
gprs_subscr_update(subscr);
|
||||
subscr_put(subscr);
|
||||
return 0;
|
||||
return subscr;
|
||||
}
|
||||
|
||||
int gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx)
|
||||
{
|
||||
struct gsm_subscriber *subscr = NULL;
|
||||
int rc;
|
||||
|
||||
LOGMMCTXP(LOGL_DEBUG, mmctx, "Requesting subscriber data update\n");
|
||||
|
||||
subscr = gprs_subscr_get_or_create_by_mmctx(mmctx);
|
||||
|
||||
subscr->flags |= GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING;
|
||||
|
||||
rc = gprs_subscr_location_update(subscr);
|
||||
subscr_put(subscr);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx)
|
||||
{
|
||||
struct gsm_subscriber *subscr = NULL;
|
||||
int rc;
|
||||
|
||||
LOGMMCTXP(LOGL_DEBUG, mmctx, "Requesting subscriber authentication info\n");
|
||||
|
||||
subscr = gprs_subscr_get_or_create_by_mmctx(mmctx);
|
||||
|
||||
subscr->flags |= GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING;
|
||||
|
||||
rc = gprs_subscr_query_auth_info(subscr);
|
||||
subscr_put(subscr);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include <openbsc/gprs_sgsn.h>
|
||||
#include <openbsc/gprs_gmm.h>
|
||||
#include <openbsc/gsm_subscriber.h>
|
||||
|
||||
#include <openbsc/gsm_04_08_gprs.h>
|
||||
#include <openbsc/debug.h>
|
||||
|
||||
const struct value_string auth_state_names[] = {
|
||||
|
@ -107,11 +107,12 @@ enum sgsn_auth_state sgsn_auth_state(struct sgsn_mm_ctx *mmctx)
|
|||
if (!mmctx->subscr)
|
||||
return mmctx->auth_state;
|
||||
|
||||
if (mmctx->subscr->flags & GPRS_SUBSCRIBER_UPDATE_PENDING)
|
||||
if (mmctx->subscr->flags & GPRS_SUBSCRIBER_UPDATE_PENDING_MASK)
|
||||
return mmctx->auth_state;
|
||||
|
||||
if (mmctx->subscr->sgsn_data->authenticate &&
|
||||
!mmctx->is_authenticated)
|
||||
(!mmctx->is_authenticated ||
|
||||
mmctx->subscr->sgsn_data->auth_triplets_updated))
|
||||
return SGSN_AUTH_AUTHENTICATE;
|
||||
|
||||
if (mmctx->subscr->authorized)
|
||||
|
@ -141,20 +142,60 @@ enum sgsn_auth_state sgsn_auth_state(struct sgsn_mm_ctx *mmctx)
|
|||
return SGSN_AUTH_REJECTED;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is directly called by e.g. the GMM layer. It returns either
|
||||
* after calling sgsn_auth_update directly or after triggering an asynchronous
|
||||
* procedure which will call sgsn_auth_update later on.
|
||||
*/
|
||||
int sgsn_auth_request(struct sgsn_mm_ctx *mmctx)
|
||||
{
|
||||
struct gsm_subscriber *subscr;
|
||||
struct gsm_auth_tuple *at;
|
||||
int need_update_location;
|
||||
int rc;
|
||||
|
||||
LOGMMCTXP(LOGL_DEBUG, mmctx, "Requesting authorization\n");
|
||||
|
||||
if (sgsn->cfg.auth_policy == SGSN_AUTH_POLICY_REMOTE && !mmctx->subscr) {
|
||||
if (gprs_subscr_request_update(mmctx) >= 0) {
|
||||
if (sgsn->cfg.auth_policy != SGSN_AUTH_POLICY_REMOTE) {
|
||||
sgsn_auth_update(mmctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
need_update_location =
|
||||
mmctx->subscr == NULL ||
|
||||
mmctx->pending_req == GSM48_MT_GMM_ATTACH_REQ;
|
||||
|
||||
/* This has the side effect of registering the subscr with the mmctx */
|
||||
subscr = gprs_subscr_get_or_create_by_mmctx(mmctx);
|
||||
subscr_put(subscr);
|
||||
|
||||
OSMO_ASSERT(mmctx->subscr != NULL);
|
||||
|
||||
if (mmctx->subscr->sgsn_data->authenticate && !mmctx->is_authenticated) {
|
||||
/* Find next tuple */
|
||||
at = sgsn_auth_get_tuple(mmctx, mmctx->auth_triplet.key_seq);
|
||||
|
||||
if (!at) {
|
||||
/* No valid tuple found, request fresh ones */
|
||||
mmctx->auth_triplet.key_seq = GSM_KEY_SEQ_INVAL;
|
||||
LOGMMCTXP(LOGL_INFO, mmctx,
|
||||
"Missing information, requesting subscriber data\n");
|
||||
return 0;
|
||||
"Requesting authentication tuples\n");
|
||||
rc = gprs_subscr_request_auth_info(mmctx);
|
||||
if (rc >= 0)
|
||||
return 0;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
mmctx->auth_triplet = *at;
|
||||
} else if (need_update_location) {
|
||||
LOGMMCTXP(LOGL_INFO, mmctx,
|
||||
"Missing information, requesting subscriber data\n");
|
||||
if (gprs_subscr_request_update_location(mmctx) >= 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
sgsn_auth_update(mmctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -162,6 +203,7 @@ void sgsn_auth_update(struct sgsn_mm_ctx *mmctx)
|
|||
{
|
||||
enum sgsn_auth_state auth_state;
|
||||
struct gsm_subscriber *subscr = mmctx->subscr;
|
||||
struct gsm_auth_tuple *at;
|
||||
|
||||
auth_state = sgsn_auth_state(mmctx);
|
||||
|
||||
|
@ -170,13 +212,27 @@ void sgsn_auth_update(struct sgsn_mm_ctx *mmctx)
|
|||
get_value_string(sgsn_auth_state_names, auth_state));
|
||||
|
||||
if (auth_state == SGSN_AUTH_UNKNOWN && subscr &&
|
||||
!(subscr->flags & GPRS_SUBSCRIBER_UPDATE_PENDING)) {
|
||||
/* Reject requests if gprs_subscr_request_update fails */
|
||||
!(subscr->flags & GPRS_SUBSCRIBER_UPDATE_PENDING_MASK)) {
|
||||
/* Reject requests if gprs_subscr_request_update_location fails */
|
||||
LOGMMCTXP(LOGL_ERROR, mmctx,
|
||||
"Missing information, authorization not possible\n");
|
||||
auth_state = SGSN_AUTH_REJECTED;
|
||||
}
|
||||
|
||||
if (auth_state == SGSN_AUTH_AUTHENTICATE &&
|
||||
mmctx->auth_triplet.key_seq == GSM_KEY_SEQ_INVAL) {
|
||||
/* The current tuple is not valid, but we are possibly called
|
||||
* because new auth tuples have been received */
|
||||
at = sgsn_auth_get_tuple(mmctx, mmctx->auth_triplet.key_seq);
|
||||
if (!at) {
|
||||
LOGMMCTXP(LOGL_ERROR, mmctx,
|
||||
"Missing auth tuples, authorization not possible\n");
|
||||
auth_state = SGSN_AUTH_REJECTED;
|
||||
} else {
|
||||
mmctx->auth_triplet = *at;
|
||||
}
|
||||
}
|
||||
|
||||
if (mmctx->auth_state == auth_state)
|
||||
return;
|
||||
|
||||
|
@ -188,6 +244,9 @@ void sgsn_auth_update(struct sgsn_mm_ctx *mmctx)
|
|||
|
||||
switch (auth_state) {
|
||||
case SGSN_AUTH_AUTHENTICATE:
|
||||
if (subscr)
|
||||
subscr->sgsn_data->auth_triplets_updated = 0;
|
||||
|
||||
gsm0408_gprs_authenticate(mmctx);
|
||||
break;
|
||||
case SGSN_AUTH_ACCEPTED:
|
||||
|
|
|
@ -428,13 +428,15 @@ static void subscr_dump_full_vty(struct vty *vty, struct gsm_subscriber *subscr,
|
|||
}
|
||||
|
||||
if (subscr->flags)
|
||||
vty_out(vty, " Flags: %s%s%s%s",
|
||||
vty_out(vty, " Flags: %s%s%s%s%s",
|
||||
subscr->flags & GSM_SUBSCRIBER_FIRST_CONTACT ?
|
||||
"FIRST_CONTACT " : "",
|
||||
subscr->flags & GPRS_SUBSCRIBER_CANCELLED ?
|
||||
"CANCELLED " : "",
|
||||
subscr->flags & GPRS_SUBSCRIBER_UPDATE_PENDING ?
|
||||
"UPDATE_PENDING " : "",
|
||||
subscr->flags & GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING ?
|
||||
"UPDATE_LOCATION_PENDING " : "",
|
||||
subscr->flags & GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING ?
|
||||
"AUTH_INFO_PENDING " : "",
|
||||
VTY_NEWLINE);
|
||||
|
||||
vty_out(vty, " Use count: %u%s", subscr->use_count, VTY_NEWLINE);
|
||||
|
@ -587,6 +589,68 @@ DEFUN(update_subscr_commit, update_subscr_commit_cmd,
|
|||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
#define UL_ERR_STR "system-failure|data-missing|unexpected-data-value|" \
|
||||
"unknown-subscriber|roaming-not-allowed"
|
||||
|
||||
#define UL_ERR_HELP \
|
||||
"Force error code SystemFailure\n" \
|
||||
"Force error code DataMissing\n" \
|
||||
"Force error code UnexpectedDataValue\n" \
|
||||
"Force error code UnknownSubscriber\n" \
|
||||
"Force error code RoamingNotAllowed\n"
|
||||
|
||||
DEFUN(update_subscr_update_location_result, update_subscr_update_location_result_cmd,
|
||||
UPDATE_SUBSCR_STR "update-location-result (ok|" UL_ERR_STR ")",
|
||||
UPDATE_SUBSCR_HELP
|
||||
"Complete the update location procedure\n"
|
||||
"The update location request succeeded\n"
|
||||
UL_ERR_HELP)
|
||||
{
|
||||
const char *imsi = argv[0];
|
||||
const char *ret_code_str = argv[1];
|
||||
|
||||
struct gsm_subscriber *subscr;
|
||||
|
||||
subscr = gprs_subscr_get_by_imsi(imsi);
|
||||
if (!subscr) {
|
||||
vty_out(vty, "%% unable to get subscriber record for %s\n", imsi);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
if (strcmp(ret_code_str, "ok") == 0)
|
||||
subscr->authorized = 1;
|
||||
else
|
||||
subscr->authorized = 0;
|
||||
|
||||
gprs_subscr_update(subscr);
|
||||
|
||||
subscr_put(subscr);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(update_subscr_update_auth_info, update_subscr_update_auth_info_cmd,
|
||||
UPDATE_SUBSCR_STR "update-auth-info",
|
||||
UPDATE_SUBSCR_HELP
|
||||
"Complete the send authentication info procedure\n")
|
||||
{
|
||||
const char *imsi = argv[0];
|
||||
|
||||
struct gsm_subscriber *subscr;
|
||||
|
||||
subscr = gprs_subscr_get_by_imsi(imsi);
|
||||
if (!subscr) {
|
||||
vty_out(vty, "%% unable to get subscriber record for %s\n", imsi);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
gprs_subscr_update_auth_info(subscr);
|
||||
|
||||
subscr_put(subscr);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int sgsn_vty_init(void)
|
||||
{
|
||||
install_element_ve(&show_sgsn_cmd);
|
||||
|
@ -600,6 +664,8 @@ int sgsn_vty_init(void)
|
|||
install_element(ENABLE_NODE, &update_subscr_insert_auth_triplet_cmd);
|
||||
install_element(ENABLE_NODE, &update_subscr_cancel_cmd);
|
||||
install_element(ENABLE_NODE, &update_subscr_commit_cmd);
|
||||
install_element(ENABLE_NODE, &update_subscr_update_location_result_cmd);
|
||||
install_element(ENABLE_NODE, &update_subscr_update_auth_info_cmd);
|
||||
|
||||
install_element(CONFIG_NODE, &cfg_sgsn_cmd);
|
||||
install_node(&sgsn_node, config_write_sgsn);
|
||||
|
|
|
@ -8,7 +8,8 @@ noinst_PROGRAMS = sgsn_test
|
|||
sgsn_test_SOURCES = sgsn_test.c
|
||||
sgsn_test_LDFLAGS = \
|
||||
-Wl,--wrap=sgsn_update_subscriber_data \
|
||||
-Wl,--wrap=gprs_subscr_request_update
|
||||
-Wl,--wrap=gprs_subscr_request_update_location \
|
||||
-Wl,--wrap=gprs_subscr_request_auth_info
|
||||
|
||||
sgsn_test_LDADD = \
|
||||
$(top_builddir)/src/gprs/gprs_llc_parse.o \
|
||||
|
|
|
@ -67,13 +67,22 @@ void __wrap_sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx,
|
|||
(*update_subscriber_data_cb)(mmctx, subscr);
|
||||
}
|
||||
|
||||
/* override, requires '-Wl,--wrap=gprs_subscr_request_update' */
|
||||
int __real_gprs_subscr_request_update(struct sgsn_mm_ctx *mmctx);
|
||||
int (*subscr_request_update_cb)(struct sgsn_mm_ctx *mmctx) =
|
||||
&__real_gprs_subscr_request_update;
|
||||
/* override, requires '-Wl,--wrap=gprs_subscr_request_update_location' */
|
||||
int __real_gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx);
|
||||
int (*subscr_request_update_location_cb)(struct sgsn_mm_ctx *mmctx) =
|
||||
&__real_gprs_subscr_request_update_location;
|
||||
|
||||
int __wrap_gprs_subscr_request_update(struct sgsn_mm_ctx *mmctx) {
|
||||
return (*subscr_request_update_cb)(mmctx);
|
||||
int __wrap_gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx) {
|
||||
return (*subscr_request_update_location_cb)(mmctx);
|
||||
};
|
||||
|
||||
/* override, requires '-Wl,--wrap=gprs_subscr_request_auth_info' */
|
||||
int __real_gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx);
|
||||
int (*subscr_request_auth_info_cb)(struct sgsn_mm_ctx *mmctx) =
|
||||
&__real_gprs_subscr_request_auth_info;
|
||||
|
||||
int __wrap_gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx) {
|
||||
return (*subscr_request_auth_info_cb)(mmctx);
|
||||
};
|
||||
|
||||
static int count(struct llist_head *head)
|
||||
|
@ -525,6 +534,12 @@ static void test_gmm_attach(void)
|
|||
0x54
|
||||
};
|
||||
|
||||
/* DTAP - Authentication and Ciphering Resp */
|
||||
static const unsigned char auth_ciph_resp[] = {
|
||||
0x08, 0x13, 0x00, 0x22, 0x51, 0xe5, 0x51, 0xe5, 0x23, 0x09,
|
||||
0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x01
|
||||
};
|
||||
|
||||
/* DTAP - Attach Complete */
|
||||
static const unsigned char attach_compl[] = {
|
||||
0x08, 0x03
|
||||
|
@ -584,6 +599,19 @@ static void test_gmm_attach(void)
|
|||
|
||||
OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
|
||||
|
||||
if (ctx->auth_state == SGSN_AUTH_AUTHENTICATE) {
|
||||
/* we expect an auth & ciph request */
|
||||
OSMO_ASSERT(sgsn_tx_counter == 1);
|
||||
|
||||
/* inject the auth & ciph response */
|
||||
send_0408_message(ctx->llme, foreign_tlli,
|
||||
auth_ciph_resp, ARRAY_SIZE(auth_ciph_resp));
|
||||
|
||||
/* check that the MM context has not been removed due to a
|
||||
* failed authorization */
|
||||
OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
|
||||
}
|
||||
|
||||
/* we expect an attach accept/reject */
|
||||
OSMO_ASSERT(sgsn_tx_counter == 1);
|
||||
|
||||
|
@ -622,9 +650,9 @@ static void test_gmm_attach_acl(void)
|
|||
sgsn->cfg.auth_policy = saved_auth_policy;
|
||||
}
|
||||
|
||||
int my_subscr_request_update(struct sgsn_mm_ctx *mmctx) {
|
||||
int my_subscr_request_update_location(struct sgsn_mm_ctx *mmctx) {
|
||||
int rc;
|
||||
rc = __real_gprs_subscr_request_update(mmctx);
|
||||
rc = __real_gprs_subscr_request_update_location(mmctx);
|
||||
if (rc == -ENOTSUP) {
|
||||
OSMO_ASSERT(mmctx->subscr);
|
||||
gprs_subscr_update(mmctx->subscr);
|
||||
|
@ -632,13 +660,19 @@ int my_subscr_request_update(struct sgsn_mm_ctx *mmctx) {
|
|||
return rc;
|
||||
};
|
||||
|
||||
int my_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx) {
|
||||
gprs_subscr_update(mmctx->subscr);
|
||||
return 0;
|
||||
};
|
||||
|
||||
static void test_gmm_attach_subscr(void)
|
||||
{
|
||||
const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
|
||||
struct gsm_subscriber *subscr;
|
||||
|
||||
sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
|
||||
subscr_request_update_cb = my_subscr_request_update;
|
||||
subscr_request_update_location_cb = my_subscr_request_update_location;
|
||||
subscr_request_auth_info_cb = my_subscr_request_auth_info;
|
||||
|
||||
subscr = gprs_subscr_get_or_create("123456789012345");
|
||||
subscr->authorized = 1;
|
||||
|
@ -652,37 +686,18 @@ static void test_gmm_attach_subscr(void)
|
|||
gprs_subscr_delete(subscr);
|
||||
|
||||
sgsn->cfg.auth_policy = saved_auth_policy;
|
||||
subscr_request_update_cb = __real_gprs_subscr_request_update;
|
||||
subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
|
||||
subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
|
||||
}
|
||||
|
||||
int my_subscr_request_update_fake_auth(struct sgsn_mm_ctx *mmctx) {
|
||||
int rc;
|
||||
rc = __real_gprs_subscr_request_update(mmctx);
|
||||
if (rc == -ENOTSUP) {
|
||||
struct gsm_subscriber *subscr;
|
||||
int old_sgsn_tx_counter = sgsn_tx_counter;
|
||||
int my_subscr_request_auth_info_fake_auth(struct sgsn_mm_ctx *mmctx)
|
||||
{
|
||||
/* Fake an authentication */
|
||||
OSMO_ASSERT(mmctx->subscr);
|
||||
mmctx->is_authenticated = 1;
|
||||
gprs_subscr_update_auth_info(mmctx->subscr);
|
||||
|
||||
OSMO_ASSERT(mmctx->subscr);
|
||||
/* Prevent subscr from being deleted */
|
||||
subscr = subscr_get(mmctx->subscr);
|
||||
|
||||
/* Start authentication procedure */
|
||||
gprs_subscr_update(subscr);
|
||||
|
||||
/* This will cause a GPRS AUTH AND CIPHERING REQ (cksn broken) */
|
||||
OSMO_ASSERT(old_sgsn_tx_counter == sgsn_tx_counter - 1);
|
||||
|
||||
/* Restore sgsn_tx_counter to keep test_gmm_attach happy */
|
||||
sgsn_tx_counter = old_sgsn_tx_counter;
|
||||
|
||||
/* Fake an authentication */
|
||||
OSMO_ASSERT(subscr->sgsn_data->mm);
|
||||
subscr->sgsn_data->mm->is_authenticated = 1;
|
||||
gprs_subscr_update(subscr);
|
||||
|
||||
subscr_put(subscr);
|
||||
}
|
||||
return rc;
|
||||
return 0;
|
||||
};
|
||||
|
||||
static void test_gmm_attach_subscr_fake_auth(void)
|
||||
|
@ -691,7 +706,8 @@ static void test_gmm_attach_subscr_fake_auth(void)
|
|||
struct gsm_subscriber *subscr;
|
||||
|
||||
sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
|
||||
subscr_request_update_cb = my_subscr_request_update_fake_auth;
|
||||
subscr_request_update_location_cb = my_subscr_request_update_location;
|
||||
subscr_request_auth_info_cb = my_subscr_request_auth_info_fake_auth;
|
||||
|
||||
subscr = gprs_subscr_get_or_create("123456789012345");
|
||||
subscr->authorized = 1;
|
||||
|
@ -706,7 +722,50 @@ static void test_gmm_attach_subscr_fake_auth(void)
|
|||
gprs_subscr_delete(subscr);
|
||||
|
||||
sgsn->cfg.auth_policy = saved_auth_policy;
|
||||
subscr_request_update_cb = __real_gprs_subscr_request_update;
|
||||
subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
|
||||
subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
|
||||
}
|
||||
|
||||
int my_subscr_request_auth_info_real_auth(struct sgsn_mm_ctx *mmctx)
|
||||
{
|
||||
struct gsm_auth_tuple at = {
|
||||
.sres = {0x51, 0xe5, 0x51, 0xe5},
|
||||
.key_seq = 0
|
||||
};
|
||||
|
||||
/* Fake an authentication */
|
||||
OSMO_ASSERT(mmctx->subscr);
|
||||
mmctx->subscr->sgsn_data->auth_triplets[0] = at;
|
||||
|
||||
gprs_subscr_update_auth_info(mmctx->subscr);
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
static void test_gmm_attach_subscr_real_auth(void)
|
||||
{
|
||||
const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
|
||||
struct gsm_subscriber *subscr;
|
||||
|
||||
sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
|
||||
subscr_request_update_location_cb = my_subscr_request_update_location;
|
||||
subscr_request_auth_info_cb = my_subscr_request_auth_info_real_auth;
|
||||
|
||||
subscr = gprs_subscr_get_or_create("123456789012345");
|
||||
subscr->authorized = 1;
|
||||
subscr->sgsn_data->authenticate = 1;
|
||||
subscr_put(subscr);
|
||||
|
||||
printf("Auth policy 'remote', triplet based auth: ");
|
||||
test_gmm_attach();
|
||||
|
||||
subscr = gprs_subscr_get_by_imsi("123456789012345");
|
||||
OSMO_ASSERT(subscr != NULL);
|
||||
gprs_subscr_delete(subscr);
|
||||
|
||||
sgsn->cfg.auth_policy = saved_auth_policy;
|
||||
subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
|
||||
subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1232,6 +1291,7 @@ int main(int argc, char **argv)
|
|||
test_gmm_attach_acl();
|
||||
test_gmm_attach_subscr();
|
||||
test_gmm_attach_subscr_fake_auth();
|
||||
test_gmm_attach_subscr_real_auth();
|
||||
test_gmm_reject();
|
||||
test_gmm_cancel();
|
||||
test_gmm_ptmsi_allocation();
|
||||
|
|
|
@ -9,6 +9,7 @@ Testing GMM Status (no MMCTX)
|
|||
Auth policy 'closed': Testing GMM attach
|
||||
Auth policy 'remote': Testing GMM attach
|
||||
Auth policy 'remote', auth faked: Testing GMM attach
|
||||
Auth policy 'remote', triplet based auth: Testing GMM attach
|
||||
Testing GMM reject
|
||||
- Attach Request (invalid MI length)
|
||||
- Attach Request (invalid MI type)
|
||||
|
|
Loading…
Reference in New Issue