From f36d6d05ccfc8faddf611a8ad74502a0c3276265 Mon Sep 17 00:00:00 2001 From: Nandini Rebello Date: Wed, 16 Jan 2019 12:07:17 +0530 Subject: [PATCH] sim: Sim PIN1 cache upon modem reset/crash Adding SIM PIN caching feature to oFono. oFono now caches the SIM PIN1 type against the ICCID throughout its lifetime in a link list and enters implicitly upon modem reset/crash. Note, that this behavior can violate 3GPP spec 21.111, section 5.3 - User Data stored in ME if that section is interpreted very strictly. However, our interpretation is that firmware resets are allowed, based on historic precedent. Helps in user experience by not barring out cellular services unless pin is entered manually. Handles cases of incorrect pin and sim pin changed externally. Clear cached PIN incase modem disabled manually and selectively when sim is removed. Seperate 'pin_cache_enter_cb' added without dbus calls to handle implict entering of cached pin. For now this behavior is applicable to all modems by default. In the future it may be needed to make this behavior opt in or otherwise configurable. --- src/ofono.h | 1 + src/sim.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) diff --git a/src/ofono.h b/src/ofono.h index 9107d81c..9cebdcef 100644 --- a/src/ofono.h +++ b/src/ofono.h @@ -418,6 +418,7 @@ unsigned char *__ofono_sim_session_get_aid( struct ofono_sim_aid_session *session); const char *__ofono_sim_get_impi(struct ofono_sim *sim); +void __ofono_sim_clear_cached_pins(struct ofono_sim *sim); #include diff --git a/src/sim.c b/src/sim.c index 886f2910..c01925e9 100644 --- a/src/sim.c +++ b/src/sim.c @@ -143,6 +143,11 @@ struct ofono_sim { bool wait_initialized : 1; }; +struct cached_pin { + char *id; + char *pin; +}; + struct msisdn_set_request { struct ofono_sim *sim; int pending; @@ -178,6 +183,8 @@ static void sim_own_numbers_update(struct ofono_sim *sim); static GSList *g_drivers = NULL; +static GSList *cached_pins = NULL; + static const char *sim_passwd_name(enum ofono_sim_password_type type) { return passwd_name[type]; @@ -475,6 +482,68 @@ done: return reply; } +static struct cached_pin *pin_cache_lookup(const char *iccid) +{ + struct cached_pin *c; + GSList *l; + + if (cached_pins == NULL) + return NULL; + + for (l = cached_pins; l; l = l->next) { + c = l->data; + + if (g_strcmp0(iccid, c->id) == 0) + return c; + } + + return NULL; +} + +static void pin_cache_update(const char *iccid, const char *pin) +{ + struct cached_pin *pin_cached = pin_cache_lookup(iccid); + struct cached_pin *cpins; + + if (pin_cached != NULL) { + g_free(pin_cached->pin); + pin_cached->pin = g_strdup(pin); + return; + } + + cpins = g_new0(struct cached_pin, 1); + + cpins->id = g_strdup(iccid); + cpins->pin = g_strdup(pin); + cached_pins = g_slist_prepend(cached_pins, cpins); +} + +static void pin_cache_remove(const char *iccid) +{ + struct cached_pin *pin_cached = pin_cache_lookup(iccid); + + if (pin_cached == NULL) + return; + + cached_pins = g_slist_remove(cached_pins, pin_cached); +} + +static void pin_cache_enter_cb(const struct ofono_error *error, void *data) +{ + struct ofono_sim *sim = data; + + if (error->type != OFONO_ERROR_TYPE_NO_ERROR) { + pin_cache_remove(sim->iccid); + + __ofono_sim_recheck_pin(sim); + + return; + } + + sim->wait_initialized = true; + DBG("Waiting for ofono_sim_initialized_notify"); +} + static void sim_pin_retries_query_cb(const struct ofono_error *error, int retries[OFONO_SIM_PASSWORD_INVALID], void *data) @@ -683,6 +752,11 @@ static void sim_locked_cb(struct ofono_sim *sim, gboolean locked) OFONO_SIM_MANAGER_INTERFACE, "LockedPins", DBUS_TYPE_STRING, &locked_pins); + + /* Cache pin only for SIM PIN type */ + if (g_strcmp0(typestr, "pin") == 0) + pin_cache_update(sim->iccid, pin); + g_strfreev(locked_pins); sim_pin_retries_check(sim); @@ -778,6 +852,14 @@ static DBusMessage *sim_unlock_pin(DBusConnection *conn, DBusMessage *msg, static void sim_change_pin_cb(const struct ofono_error *error, void *data) { struct ofono_sim *sim = data; + const char *typestr; + const char *old; + const char *new; + + dbus_message_get_args(sim->pending, NULL, DBUS_TYPE_STRING, &typestr, + DBUS_TYPE_STRING, &old, + DBUS_TYPE_STRING, &new, + DBUS_TYPE_INVALID); if (error->type != OFONO_ERROR_TYPE_NO_ERROR) { __ofono_dbus_pending_reply(&sim->pending, @@ -788,6 +870,10 @@ static void sim_change_pin_cb(const struct ofono_error *error, void *data) return; } + /* Cache pin only for SIM PIN type */ + if (g_strcmp0(typestr, "pin") == 0) + pin_cache_update(sim->iccid, new); + __ofono_dbus_pending_reply(&sim->pending, dbus_message_new_method_return(sim->pending)); @@ -839,8 +925,14 @@ static DBusMessage *sim_change_pin(DBusConnection *conn, DBusMessage *msg, static void sim_enter_pin_cb(const struct ofono_error *error, void *data) { struct ofono_sim *sim = data; + const char *typestr; + const char *pin; DBusMessage *reply; + dbus_message_get_args(sim->pending, NULL, DBUS_TYPE_STRING, &typestr, + DBUS_TYPE_STRING, &pin, + DBUS_TYPE_INVALID); + if (error->type != OFONO_ERROR_TYPE_NO_ERROR) reply = __ofono_error_failed(sim->pending); else @@ -852,6 +944,10 @@ static void sim_enter_pin_cb(const struct ofono_error *error, void *data) if (sim->initialized || error->type != OFONO_ERROR_TYPE_NO_ERROR) goto recheck; + /* Cache pin only for SIM PIN type */ + if (g_strcmp0(typestr, "pin") == 0) + pin_cache_update(sim->iccid, pin); + if (sim->pin_type == OFONO_SIM_PASSWORD_SIM_PIN || sim->pin_type == OFONO_SIM_PASSWORD_SIM_PUK) { sim->wait_initialized = true; @@ -2751,6 +2847,8 @@ void ofono_sim_inserted_notify(struct ofono_sim *sim, ofono_bool_t inserted) sim->pin_retries[OFONO_SIM_PASSWORD_SIM_PIN2] = -1; sim->pin_retries[OFONO_SIM_PASSWORD_SIM_PUK2] = -1; + pin_cache_remove(sim->iccid); + sim_free_state(sim); } } @@ -3024,6 +3122,7 @@ static void sim_pin_query_cb(const struct ofono_error *error, struct ofono_sim *sim = data; DBusConnection *conn = ofono_dbus_get_connection(); const char *path = __ofono_atom_get_path(sim->atom); + struct cached_pin *cpins = pin_cache_lookup(sim->iccid); const char *pin_name; char **locked_pins; gboolean lock_changed; @@ -3068,6 +3167,10 @@ static void sim_pin_query_cb(const struct ofono_error *error, &pin_name); } + if (g_strcmp0(pin_name, "pin") == 0 && cpins != NULL) + sim->driver->send_passwd(sim, cpins->pin, + pin_cache_enter_cb, sim); + switch (pin_type) { case OFONO_SIM_PASSWORD_NONE: case OFONO_SIM_PASSWORD_SIM_PIN2: @@ -3301,6 +3404,14 @@ void ofono_sim_register(struct ofono_sim *sim) __ofono_atom_register(sim->atom, sim_unregister); } +void __ofono_sim_clear_cached_pins(struct ofono_sim *sim) +{ + if (cached_pins == NULL) + return; + + pin_cache_remove(sim->iccid); +} + void ofono_sim_remove(struct ofono_sim *sim) { __ofono_atom_free(sim->atom);