diff options
author | Andrzej Zaborowski <andrew.zaborowski@intel.com> | 2009-09-17 22:43:22 +0200 |
---|---|---|
committer | Denis Kenzior <denkenz@gmail.com> | 2009-09-22 00:07:06 -0500 |
commit | ee02b14836d7e30b45ee6fd62da6a8135c94c9dd (patch) | |
tree | ebe561c1cb248e4a11643fdc09e61246520cda97 /src | |
parent | b1c8b291f5c8d1802b889756c01cc2f7f5288641 (diff) | |
download | ofono-ee02b14836d7e30b45ee6fd62da6a8135c94c9dd.tar.bz2 |
Do PIN authentication
This adds checking whether PIN is required during SIM initialisation and
delaying the sim ready notifications until after correct PIN is given.
Diffstat (limited to 'src')
-rw-r--r-- | src/sim.c | 286 | ||||
-rw-r--r-- | src/simutil.c | 36 | ||||
-rw-r--r-- | src/simutil.h | 3 |
3 files changed, 324 insertions, 1 deletions
@@ -55,6 +55,7 @@ static GSList *g_drivers = NULL; static gboolean sim_op_next(gpointer user_data); static gboolean sim_op_retrieve_next(gpointer user); static void sim_own_numbers_update(struct ofono_sim *sim); +static void sim_pin_check(struct ofono_sim *sim); struct sim_file_op { int id; @@ -77,6 +78,7 @@ struct ofono_sim { GSList *service_numbers; gboolean sdn_ready; gboolean ready; + int pin_type; char **language_prefs; GQueue *simop_q; gint simop_source; @@ -89,6 +91,7 @@ struct ofono_sim { const struct ofono_sim_driver *driver; void *driver_data; struct ofono_atom *atom; + DBusMessage *pending; }; struct msisdn_set_request { @@ -98,6 +101,12 @@ struct msisdn_set_request { DBusMessage *msg; }; +struct pin_enable_request { + struct ofono_sim *sim; + int type; + char *passwd; +}; + struct service_number { char *id; struct ofono_phone_number ph; @@ -167,6 +176,7 @@ static DBusMessage *sim_get_properties(DBusConnection *conn, DBusMessageIter dict; char **own_numbers; char **service_numbers; + const char *pin_name; reply = dbus_message_new_method_return(msg); if (!reply) @@ -206,6 +216,11 @@ static DBusMessage *sim_get_properties(DBusConnection *conn, DBUS_TYPE_STRING, &sim->language_prefs); + pin_name = sim_passwd_name(sim->pin_type); + ofono_dbus_dict_append(&dict, "PinRequired", + DBUS_TYPE_STRING, + (void *) &pin_name); + dbus_message_iter_close_container(&iter, &dict); return reply; @@ -354,10 +369,234 @@ error: return __ofono_error_invalid_args(msg); } +static void sim_enable_pin_cb(const struct ofono_error *error, void *data) +{ + struct ofono_sim *sim = data; + DBusMessage *reply; + + if (error->type != OFONO_ERROR_TYPE_NO_ERROR) + reply = __ofono_error_failed(sim->pending); + else + reply = dbus_message_new_method_return(sim->pending); + + __ofono_dbus_pending_reply(&sim->pending, reply); +} + +static void sim_change_pin_cb(const struct ofono_error *error, void *data) +{ + struct pin_enable_request *req = data; + struct ofono_sim *sim = req->sim; + + if (error->type != OFONO_ERROR_TYPE_NO_ERROR) { + __ofono_dbus_pending_reply(&sim->pending, + __ofono_error_failed(sim->pending)); + goto cleanup; + } + + if (!sim->driver->lock) { + __ofono_dbus_pending_reply(&sim->pending, + dbus_message_new_method_return(sim->pending)); + goto cleanup; + } + + sim->driver->lock(sim, req->type, 1, req->passwd, + sim_enable_pin_cb, sim); + +cleanup: + memset(req->passwd, 0, strlen(req->passwd)); + g_free(req->passwd); + g_free(req); +} + +static DBusMessage *sim_change_pin(DBusConnection *conn, DBusMessage *msg, + void *data) +{ + struct ofono_sim *sim = data; + struct pin_enable_request *req; + DBusMessageIter iter; + enum ofono_passwd_type type; + const char *typestr; + const char *old; + const char *new; + + if (sim->pending) + return __ofono_error_busy(msg); + + if (!dbus_message_iter_init(msg, &iter)) + return __ofono_error_invalid_args(msg); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) + return __ofono_error_invalid_args(msg); + + dbus_message_iter_get_basic(&iter, &typestr); + + type = sim_string_to_passwd(typestr); + if (type == OFONO_PASSWD_NONE) + return __ofono_error_invalid_format(msg); + + dbus_message_iter_next(&iter); + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) + return __ofono_error_invalid_args(msg); + + dbus_message_iter_get_basic(&iter, &old); + + if (!is_valid_pin(old)) + return __ofono_error_invalid_format(msg); + + dbus_message_iter_next(&iter); + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) + return __ofono_error_invalid_args(msg); + + dbus_message_iter_get_basic(&iter, &new); + + if (new[0] != '\0' && strcmp(new, old)) { + if (!sim->driver->change_passwd) + return __ofono_error_not_implemented(msg); + + if (!is_valid_pin(new)) + return __ofono_error_invalid_format(msg); + + req = g_new0(struct pin_enable_request, 1); + + req->sim = sim; + req->type = type; + req->passwd = g_strdup(new); + + sim->pending = dbus_message_ref(msg); + + sim->driver->change_passwd(sim, type, old, new, + sim_change_pin_cb, req); + } else { + if (!sim->driver->lock) + return __ofono_error_not_implemented(msg); + + sim->pending = dbus_message_ref(msg); + sim->driver->lock(sim, type, new[0] != '\0', + old, sim_enable_pin_cb, sim); + } + + return NULL; +} + +static void sim_enter_pin_cb(const struct ofono_error *error, void *data) +{ + struct ofono_sim *sim = data; + DBusMessage *reply; + + if (error->type != OFONO_ERROR_TYPE_NO_ERROR) + reply = __ofono_error_failed(sim->pending); + else + reply = dbus_message_new_method_return(sim->pending); + + __ofono_dbus_pending_reply(&sim->pending, reply); + + sim_pin_check(sim); +} + +static DBusMessage *sim_enter_pin(DBusConnection *conn, DBusMessage *msg, + void *data) +{ + struct ofono_sim *sim = data; + DBusMessageIter iter; + const char *typestr; + int type; + const char *pin; + + if (!sim->driver->send_passwd) + return __ofono_error_not_implemented(msg); + + if (sim->pending) + return __ofono_error_busy(msg); + + if (!dbus_message_iter_init(msg, &iter)) + return __ofono_error_invalid_args(msg); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) + return __ofono_error_invalid_args(msg); + + dbus_message_iter_get_basic(&iter, &typestr); + + type = sim_string_to_passwd(typestr); + if (type == OFONO_PASSWD_NONE || type != sim->pin_type) + return __ofono_error_invalid_format(msg); + + dbus_message_iter_next(&iter); + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) + return __ofono_error_invalid_args(msg); + + dbus_message_iter_get_basic(&iter, &pin); + + if (!is_valid_pin(pin)) + return __ofono_error_invalid_format(msg); + + sim->pending = dbus_message_ref(msg); + sim->driver->send_passwd(sim, pin, sim_enter_pin_cb, sim); + + return NULL; +} + +static DBusMessage *sim_reset_pin(DBusConnection *conn, DBusMessage *msg, + void *data) +{ + struct ofono_sim *sim = data; + DBusMessageIter iter; + const char *typestr; + int type; + const char *puk; + const char *pin; + + if (!sim->driver->reset_passwd) + return __ofono_error_not_implemented(msg); + + if (sim->pending) + return __ofono_error_busy(msg); + + if (!dbus_message_iter_init(msg, &iter)) + return __ofono_error_invalid_args(msg); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) + return __ofono_error_invalid_args(msg); + + dbus_message_iter_get_basic(&iter, &typestr); + + type = sim_string_to_passwd(typestr); + if (type == OFONO_PASSWD_NONE || type != sim->pin_type) + return __ofono_error_invalid_format(msg); + + dbus_message_iter_next(&iter); + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) + return __ofono_error_invalid_args(msg); + + dbus_message_iter_get_basic(&iter, &puk); + + if (!is_valid_pin(puk)) + return __ofono_error_invalid_format(msg); + + dbus_message_iter_next(&iter); + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) + return __ofono_error_invalid_args(msg); + + dbus_message_iter_get_basic(&iter, &pin); + + if (!is_valid_pin(pin)) + return __ofono_error_invalid_format(msg); + + sim->pending = dbus_message_ref(msg); + sim->driver->reset_passwd(sim, puk, pin, sim_enter_pin_cb, sim); + + return NULL; +} + static GDBusMethodTable sim_methods[] = { { "GetProperties", "", "a{sv}", sim_get_properties }, { "SetProperty", "sv", "", sim_set_property, G_DBUS_METHOD_FLAG_ASYNC }, + { "ChangePin", "sss", "", sim_change_pin, + G_DBUS_METHOD_FLAG_ASYNC }, + { "EnterPin", "ss", "", sim_enter_pin, + G_DBUS_METHOD_FLAG_ASYNC }, + { "ResetPin", "sss", "", sim_reset_pin, + G_DBUS_METHOD_FLAG_ASYNC }, { } }; @@ -613,6 +852,51 @@ static void sim_retrieve_imsi(struct ofono_sim *sim) sim->driver->read_imsi(sim, sim_imsi_cb, sim); } +static void sim_pin_check_done(struct ofono_sim *sim) +{ + sim_retrieve_imsi(sim); +} + +static void sim_pin_query_cb(const struct ofono_error *error, int pin_type, + void *data) +{ + struct ofono_sim *sim = data; + DBusConnection *conn = ofono_dbus_get_connection(); + const char *path = __ofono_atom_get_path(sim->atom); + const char *pin_name; + + if (error->type != OFONO_ERROR_TYPE_NO_ERROR) { + ofono_error("Querying PIN authentication state failed"); + + goto checkdone; + } + + if (sim->pin_type != pin_type) { + sim->pin_type = pin_type; + pin_name = sim_passwd_name(pin_type); + + ofono_dbus_signal_property_changed(conn, path, + SIM_MANAGER_INTERFACE, + "PinRequired", + DBUS_TYPE_STRING, + &pin_name); + } + +checkdone: + if (pin_type == OFONO_PASSWD_NONE) + sim_pin_check_done(sim); +} + +static void sim_pin_check(struct ofono_sim *sim) +{ + if (!sim->driver->query_passwd_state) { + sim_pin_check_done(sim); + return; + } + + sim->driver->query_passwd_state(sim, sim_pin_query_cb, sim); +} + static void sim_efli_read_cb(int ok, enum ofono_sim_file_structure structure, int length, int record, @@ -1465,7 +1749,7 @@ void ofono_sim_register(struct ofono_sim *sim) * in the EFust */ sim_retrieve_efli_and_efpl(sim); - sim_retrieve_imsi(sim); + sim_pin_check(sim); } void ofono_sim_remove(struct ofono_sim *sim) diff --git a/src/simutil.c b/src/simutil.c index b80e014d..e1b0f2aa 100644 --- a/src/simutil.c +++ b/src/simutil.c @@ -488,3 +488,39 @@ void sim_adn_build(unsigned char *data, int length, /* Ext1 unused */ *data++ = 0xff; } + +static const char *const passwd_name[] = { + [OFONO_PASSWD_NONE] = "none", + [OFONO_PASSWD_SIM_PIN] = "pin", + [OFONO_PASSWD_SIM_PUK] = "puk", + [OFONO_PASSWD_PHSIM_PIN] = "phone", + [OFONO_PASSWD_PHFSIM_PIN] = "firstphone", + [OFONO_PASSWD_PHFSIM_PUK] = "firstphonepuk", + [OFONO_PASSWD_SIM_PIN2] = "pin2", + [OFONO_PASSWD_SIM_PUK2] = "puk2", + [OFONO_PASSWD_PHNET_PIN] = "network", + [OFONO_PASSWD_PHNET_PUK] = "networkpuk", + [OFONO_PASSWD_PHNETSUB_PIN] = "netsub", + [OFONO_PASSWD_PHNETSUB_PUK] = "netsubpuk", + [OFONO_PASSWD_PHSP_PIN] = "service", + [OFONO_PASSWD_PHSP_PUK] = "servicepuk", + [OFONO_PASSWD_PHCORP_PIN] = "corp", + [OFONO_PASSWD_PHCORP_PUK] = "corppuk", +}; + +const char *sim_passwd_name(enum ofono_passwd_type type) +{ + return passwd_name[type]; +} + +enum ofono_passwd_type sim_string_to_passwd(const char *name) +{ + int len = sizeof(passwd_name) / sizeof(*passwd_name); + int i; + + for (i = 0; i < len; i++) + if (!strcmp(passwd_name[i], name)) + return i; + + return OFONO_PASSWD_NONE; +} diff --git a/src/simutil.h b/src/simutil.h index 2cd3b738..df84416f 100644 --- a/src/simutil.h +++ b/src/simutil.h @@ -93,3 +93,6 @@ gboolean sim_adn_parse(const unsigned char *data, int length, void sim_adn_build(unsigned char *data, int length, const struct ofono_phone_number *ph, const char *identifier); + +const char *sim_passwd_name(enum ofono_passwd_type type); +enum ofono_passwd_type sim_string_to_passwd(const char *name); |