mirror of git://git.sysmocom.de/ofono
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.
This commit is contained in:
parent
b1c8b291f5
commit
ee02b14836
|
@ -398,6 +398,242 @@ error:
|
|||
CALLBACK_WITH_FAILURE(cb, NULL, data);
|
||||
}
|
||||
|
||||
static struct {
|
||||
enum ofono_passwd_type type;
|
||||
const char *name;
|
||||
} const at_sim_name[] = {
|
||||
{ OFONO_PASSWD_SIM_PIN, "SIM PIN" },
|
||||
{ OFONO_PASSWD_SIM_PUK, "SIM PUK" },
|
||||
{ OFONO_PASSWD_PHSIM_PIN, "PH-SIM PIN" },
|
||||
{ OFONO_PASSWD_PHFSIM_PIN, "PH-FSIM PIN" },
|
||||
{ OFONO_PASSWD_PHFSIM_PUK, "PH-FSIM PUK" },
|
||||
{ OFONO_PASSWD_SIM_PIN2, "SIM PIN2" },
|
||||
{ OFONO_PASSWD_SIM_PUK2, "SIM PUK2" },
|
||||
{ OFONO_PASSWD_PHNET_PIN, "PH-NET PIN" },
|
||||
{ OFONO_PASSWD_PHNET_PUK, "PH-NET PUK" },
|
||||
{ OFONO_PASSWD_PHNETSUB_PIN, "PH-NETSUB PIN" },
|
||||
{ OFONO_PASSWD_PHNETSUB_PUK, "PH-NETSUB PUK" },
|
||||
{ OFONO_PASSWD_PHSP_PIN, "PH-SP PIN" },
|
||||
{ OFONO_PASSWD_PHSP_PUK, "PH-SP PUK" },
|
||||
{ OFONO_PASSWD_PHCORP_PIN, "PH-CORP PIN" },
|
||||
{ OFONO_PASSWD_PHCORP_PUK, "PH-CORP PUK" },
|
||||
};
|
||||
|
||||
static void at_cpin_cb(gboolean ok, GAtResult *result, gpointer user_data)
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
GAtResultIter iter;
|
||||
ofono_sim_passwd_cb_t cb = cbd->cb;
|
||||
struct ofono_error error;
|
||||
const char *pin_required;
|
||||
int pin_type;
|
||||
int i;
|
||||
int len = sizeof(at_sim_name) / sizeof(*at_sim_name);
|
||||
|
||||
dump_response("at_cpin_cb", ok, result);
|
||||
decode_at_error(&error, g_at_result_final_response(result));
|
||||
|
||||
if (!ok) {
|
||||
cb(&error, -1, cbd->data);
|
||||
return;
|
||||
}
|
||||
|
||||
g_at_result_iter_init(&iter, result);
|
||||
|
||||
if (!g_at_result_iter_next(&iter, "+CPIN:")) {
|
||||
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
|
||||
return;
|
||||
}
|
||||
|
||||
g_at_result_iter_next_unquoted_string(&iter, &pin_required);
|
||||
|
||||
pin_type = -1;
|
||||
if (!strcmp(pin_required, "READY"))
|
||||
pin_type = OFONO_PASSWD_NONE;
|
||||
else
|
||||
for (i = 0; i < len; i++)
|
||||
if (!strcmp(pin_required, at_sim_name[i].name)) {
|
||||
pin_type = at_sim_name[i].type;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pin_type == -1) {
|
||||
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
|
||||
return;
|
||||
}
|
||||
|
||||
ofono_debug("crsm_pin_cb: %s", pin_required);
|
||||
|
||||
cb(&error, pin_type, cbd->data);
|
||||
}
|
||||
|
||||
static void at_pin_query(struct ofono_sim *sim, ofono_sim_passwd_cb_t cb,
|
||||
void *data)
|
||||
{
|
||||
GAtChat *chat = ofono_sim_get_data(sim);
|
||||
struct cb_data *cbd = cb_data_new(cb, data);
|
||||
|
||||
if (!cbd)
|
||||
goto error;
|
||||
|
||||
if (g_at_chat_send(chat, "AT+CPIN?", NULL,
|
||||
at_cpin_cb, cbd, g_free) > 0)
|
||||
return;
|
||||
|
||||
error:
|
||||
if (cbd)
|
||||
g_free(cbd);
|
||||
|
||||
CALLBACK_WITH_FAILURE(cb, -1, data);
|
||||
}
|
||||
|
||||
static void at_lock_unlock_cb(gboolean ok, GAtResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
ofono_sim_lock_unlock_cb_t cb = cbd->cb;
|
||||
struct ofono_error error;
|
||||
|
||||
dump_response("at_lock_unlock_cb", ok, result);
|
||||
decode_at_error(&error, g_at_result_final_response(result));
|
||||
|
||||
cb(&error, cbd->data);
|
||||
}
|
||||
|
||||
static void at_pin_send(struct ofono_sim *sim, const char *passwd,
|
||||
ofono_sim_lock_unlock_cb_t cb, void *data)
|
||||
{
|
||||
GAtChat *chat = ofono_sim_get_data(sim);
|
||||
struct cb_data *cbd = cb_data_new(cb, data);
|
||||
char buf[64];
|
||||
int ret;
|
||||
|
||||
if (!cbd)
|
||||
goto error;
|
||||
|
||||
snprintf(buf, sizeof(buf), "AT+CPIN=\"%s\"", passwd);
|
||||
|
||||
ret = g_at_chat_send(chat, buf, NULL, at_lock_unlock_cb, cbd, g_free);
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
if (ret > 0)
|
||||
return;
|
||||
|
||||
error:
|
||||
if (cbd)
|
||||
g_free(cbd);
|
||||
|
||||
CALLBACK_WITH_FAILURE(cb, data);
|
||||
}
|
||||
|
||||
static void at_pin_send_puk(struct ofono_sim *sim, const char *puk,
|
||||
const char *passwd,
|
||||
ofono_sim_lock_unlock_cb_t cb, void *data)
|
||||
{
|
||||
GAtChat *chat = ofono_sim_get_data(sim);
|
||||
struct cb_data *cbd = cb_data_new(cb, data);
|
||||
char buf[64];
|
||||
int ret;
|
||||
|
||||
if (!cbd)
|
||||
goto error;
|
||||
|
||||
snprintf(buf, sizeof(buf), "AT+CPIN=\"%s\",\"%s\"", puk, passwd);
|
||||
|
||||
ret = g_at_chat_send(chat, buf, NULL, at_lock_unlock_cb, cbd, g_free);
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
if (ret > 0)
|
||||
return;
|
||||
|
||||
error:
|
||||
if (cbd)
|
||||
g_free(cbd);
|
||||
|
||||
CALLBACK_WITH_FAILURE(cb, data);
|
||||
}
|
||||
|
||||
static const char *const at_clck_cpwd_fac[] = {
|
||||
[OFONO_PASSWD_SIM_PIN] = "SC",
|
||||
[OFONO_PASSWD_SIM_PIN2] = "P2",
|
||||
[OFONO_PASSWD_PHSIM_PIN] = "PS",
|
||||
[OFONO_PASSWD_PHFSIM_PIN] = "PF",
|
||||
[OFONO_PASSWD_PHNET_PIN] = "PN",
|
||||
[OFONO_PASSWD_PHNETSUB_PIN] = "PU",
|
||||
[OFONO_PASSWD_PHSP_PIN] = "PP",
|
||||
[OFONO_PASSWD_PHCORP_PIN] = "PC",
|
||||
};
|
||||
|
||||
static void at_pin_enable(struct ofono_sim *sim, int passwd_type, int enable,
|
||||
const char *passwd,
|
||||
ofono_sim_lock_unlock_cb_t cb, void *data)
|
||||
{
|
||||
GAtChat *chat = ofono_sim_get_data(sim);
|
||||
struct cb_data *cbd = cb_data_new(cb, data);
|
||||
char buf[64];
|
||||
int ret;
|
||||
int len = sizeof(at_clck_cpwd_fac) / sizeof(*at_clck_cpwd_fac);
|
||||
|
||||
if (!cbd)
|
||||
goto error;
|
||||
|
||||
if (passwd_type < 0 || passwd_type >= len ||
|
||||
!at_clck_cpwd_fac[passwd_type])
|
||||
goto error;
|
||||
|
||||
snprintf(buf, sizeof(buf), "AT+CLCK=\"%s\",%i,\"%s\"",
|
||||
at_clck_cpwd_fac[passwd_type], enable ? 1 : 0, passwd);
|
||||
|
||||
ret = g_at_chat_send(chat, buf, NULL, at_lock_unlock_cb, cbd, g_free);
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
if (ret > 0)
|
||||
return;
|
||||
|
||||
error:
|
||||
if (cbd)
|
||||
g_free(cbd);
|
||||
|
||||
CALLBACK_WITH_FAILURE(cb, data);
|
||||
}
|
||||
|
||||
static void at_change_passwd(struct ofono_sim *sim, int passwd_type,
|
||||
const char *old, const char *new,
|
||||
ofono_sim_lock_unlock_cb_t cb, void *data)
|
||||
{
|
||||
GAtChat *chat = ofono_sim_get_data(sim);
|
||||
struct cb_data *cbd = cb_data_new(cb, data);
|
||||
char buf[64];
|
||||
int ret;
|
||||
int len = sizeof(at_clck_cpwd_fac) / sizeof(*at_clck_cpwd_fac);
|
||||
|
||||
if (!cbd)
|
||||
goto error;
|
||||
|
||||
if (passwd_type < 0 || passwd_type >= len ||
|
||||
!at_clck_cpwd_fac[passwd_type])
|
||||
goto error;
|
||||
|
||||
snprintf(buf, sizeof(buf), "AT+CPWD=\"%s\",\"%s\",\"%s\"",
|
||||
at_clck_cpwd_fac[passwd_type], old, new);
|
||||
|
||||
ret = g_at_chat_send(chat, buf, NULL, at_lock_unlock_cb, cbd, g_free);
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
if (ret > 0)
|
||||
return;
|
||||
|
||||
error:
|
||||
if (cbd)
|
||||
g_free(cbd);
|
||||
|
||||
CALLBACK_WITH_FAILURE(cb, data);
|
||||
}
|
||||
|
||||
static gboolean at_sim_register(gpointer user)
|
||||
{
|
||||
struct ofono_sim *sim = user;
|
||||
|
@ -434,6 +670,11 @@ static struct ofono_sim_driver driver = {
|
|||
.write_file_linear = at_sim_update_record,
|
||||
.write_file_cyclic = at_sim_update_cyclic,
|
||||
.read_imsi = at_read_imsi,
|
||||
.query_passwd_state = at_pin_query,
|
||||
.send_passwd = at_pin_send,
|
||||
.reset_passwd = at_pin_send_puk,
|
||||
.lock = at_pin_enable,
|
||||
.change_passwd = at_change_passwd,
|
||||
};
|
||||
|
||||
void at_sim_init()
|
||||
|
|
|
@ -64,6 +64,12 @@ typedef void (*ofono_sim_file_read_cb_t)(int ok,
|
|||
|
||||
typedef void (*ofono_sim_file_write_cb_t)(int ok, void *userdata);
|
||||
|
||||
typedef void (*ofono_sim_passwd_cb_t)(const struct ofono_error *error,
|
||||
int passwd_type, void *data);
|
||||
|
||||
typedef void (*ofono_sim_lock_unlock_cb_t)(const struct ofono_error *error,
|
||||
void *data);
|
||||
|
||||
struct ofono_sim_driver {
|
||||
const char *name;
|
||||
int (*probe)(struct ofono_sim *sim, unsigned int vendor, void *data);
|
||||
|
@ -90,6 +96,19 @@ struct ofono_sim_driver {
|
|||
ofono_sim_write_cb_t cb, void *data);
|
||||
void (*read_imsi)(struct ofono_sim *sim,
|
||||
ofono_sim_imsi_cb_t cb, void *data);
|
||||
void (*query_passwd_state)(struct ofono_sim *sim,
|
||||
ofono_sim_passwd_cb_t cb, void *data);
|
||||
void (*send_passwd)(struct ofono_sim *sim, const char *passwd,
|
||||
ofono_sim_lock_unlock_cb_t cb, void *data);
|
||||
void (*reset_passwd)(struct ofono_sim *sim, const char *puk,
|
||||
const char *passwd,
|
||||
ofono_sim_lock_unlock_cb_t cb, void *data);
|
||||
void (*change_passwd)(struct ofono_sim *sim, int passwd_type,
|
||||
const char *old, const char *new,
|
||||
ofono_sim_lock_unlock_cb_t cb, void *data);
|
||||
void (*lock)(struct ofono_sim *sim, int passwd_type, int enable,
|
||||
const char *passwd,
|
||||
ofono_sim_lock_unlock_cb_t cb, void *data);
|
||||
};
|
||||
|
||||
int ofono_sim_driver_register(const struct ofono_sim_driver *d);
|
||||
|
|
|
@ -91,6 +91,26 @@ struct ofono_call {
|
|||
int clip_validity;
|
||||
};
|
||||
|
||||
enum ofono_passwd_type {
|
||||
OFONO_PASSWD_NONE = 0,
|
||||
|
||||
OFONO_PASSWD_SIM_PIN,
|
||||
OFONO_PASSWD_SIM_PUK,
|
||||
OFONO_PASSWD_PHSIM_PIN,
|
||||
OFONO_PASSWD_PHFSIM_PIN,
|
||||
OFONO_PASSWD_PHFSIM_PUK,
|
||||
OFONO_PASSWD_SIM_PIN2,
|
||||
OFONO_PASSWD_SIM_PUK2,
|
||||
OFONO_PASSWD_PHNET_PIN,
|
||||
OFONO_PASSWD_PHNET_PUK,
|
||||
OFONO_PASSWD_PHNETSUB_PIN,
|
||||
OFONO_PASSWD_PHNETSUB_PUK,
|
||||
OFONO_PASSWD_PHSP_PIN,
|
||||
OFONO_PASSWD_PHSP_PUK,
|
||||
OFONO_PASSWD_PHCORP_PIN,
|
||||
OFONO_PASSWD_PHCORP_PUK,
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
286
src/sim.c
286
src/sim.c
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue