Hello,

I would like to be able to provision SIM PINs like what we did for GPRS context. In my project, I want a configuration file where SIM PINs will be written. When a new SIM appears, Ofono should read this file to get SIM PIN if needed.


To be a bit more generic than that, I have written something based on provision plugins done for gprs context provisioning.

When Ofono (src/sim.c) discovers that a SIM needs a PIN code, it will call all SIM password provision plugins registered to try to get current SIM needed password. If it gets a password, it will try to enter it without waiting for end-user to call EnterPin method. Of course, this is tried only once to avoid blocking SIM cards.

I have also written a SIM password plugin based on a key-value file similar to what has been done in file-provision.c plugin. This is what I need in my project, others can write other plugins if needed.

Please find attached the patch with these modifications (all of them).

Let me know if you think this feature could be nice for upstream, I'll send a broken down version of the patch in this case (I assume, I should separate plugin implementation from introduction of this type of plugins in Ofono src directory).


Best Regards,


Christophe

>From 24bb0fe4af1b05251f05a8442361255f7cd9ef03 Mon Sep 17 00:00:00 2001
From: Christophe Ronco <c.ro...@kerlink.fr>
Date: Wed, 22 Feb 2017 14:20:32 +0100
Subject: [PATCH] add sim provisioning

---
 Makefile.am                    |   9 ++-
 include/sim-passwd-provision.h |  41 +++++++++++
 plugins/sim-file-provision.c   | 156 +++++++++++++++++++++++++++++++++++++++++
 src/ofono.h                    |   5 ++
 src/sim-password-provision.c   |  80 +++++++++++++++++++++
 src/sim.c                      |  35 +++++++++
 6 files changed, 324 insertions(+), 2 deletions(-)
 create mode 100644 include/sim-passwd-provision.h
 create mode 100644 plugins/sim-file-provision.c
 create mode 100644 src/sim-password-provision.c

diff --git a/Makefile.am b/Makefile.am
index d9f9b086..fab55226 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -22,7 +22,8 @@ pkginclude_HEADERS = include/log.h include/plugin.h include/history.h \
 			include/private-network.h include/cdma-netreg.h \
 			include/cdma-provision.h include/handsfree.h \
 			include/handsfree-audio.h include/siri.h \
-			include/netmon.h include/lte.h
+			include/netmon.h include/lte.h \
+			include/sim-passwd-provision.h
 
 nodist_pkginclude_HEADERS = include/version.h
 
@@ -559,6 +560,10 @@ builtin_sources += plugins/cdma-provision.c
 builtin_modules += file_provision
 builtin_sources += plugins/file-provision.c
 
+builtin_modules += sim_file_provision
+builtin_sources += plugins/sim-file-provision.c
+
+
 endif
 
 if MAINTAINER_MODE
@@ -621,7 +626,7 @@ src_ofonod_SOURCES = $(builtin_sources) $(gatchat_sources) src/ofono.ver \
 			src/cdma-provision.c src/handsfree.c \
 			src/handsfree-audio.c src/bluetooth.h \
 			src/hfp.h src/siri.c \
-			src/netmon.c src/lte.c
+			src/netmon.c src/lte.c src/sim-password-provision.c
 
 src_ofonod_LDADD = gdbus/libgdbus-internal.la $(builtin_libadd) \
 			@GLIB_LIBS@ @DBUS_LIBS@ -ldl
diff --git a/include/sim-passwd-provision.h b/include/sim-passwd-provision.h
new file mode 100644
index 00000000..62ceae31
--- /dev/null
+++ b/include/sim-passwd-provision.h
@@ -0,0 +1,41 @@
+/*
+ *
+ *  oFono - Open Telephony stack for Linux
+ *
+ *  Copyright (C) 2017  Kerlink SA.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ */
+
+#ifndef __OFONO_SIM_PASSWD_PROVISION_H
+#define __OFONO_SIM_PASSWD_PROVISION_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ofono_sim_passwd_provision_driver {
+	const char *name;
+	int priority;
+	int (*get_password)(const char *iccid,
+		enum ofono_sim_password_type password_type, char **pin);
+};
+
+int ofono_sim_password_provision_driver_register(
+		const struct ofono_sim_passwd_provision_driver *driver);
+void ofono_sim_password_provision_driver_unregister(
+		const struct ofono_sim_passwd_provision_driver *driver);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __OFONO_SIM_PASSWD_PROVISION_H */
diff --git a/plugins/sim-file-provision.c b/plugins/sim-file-provision.c
new file mode 100644
index 00000000..16e63d65
--- /dev/null
+++ b/plugins/sim-file-provision.c
@@ -0,0 +1,156 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2017  Kerlink SA.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <glib.h>
+
+#define OFONO_API_SUBJECT_TO_CHANGE
+#include <ofono/modem.h>
+#include <ofono/log.h>
+#include <ofono/plugin.h>
+#include <ofono/sim.h>
+#include <ofono/sim-passwd-provision.h>
+
+#define CONFIG_FILE STORAGEDIR "/provisioning"
+
+struct passwd_type_dict {
+	enum ofono_sim_password_type passwd_enum;
+	const char *passwd_string;
+};
+
+static const struct passwd_type_dict passwd_dictionary[] = {
+	{ OFONO_SIM_PASSWORD_SIM_PIN, "pin" },
+	{ OFONO_SIM_PASSWORD_SIM_PUK, "puk" },
+	{ OFONO_SIM_PASSWORD_PHSIM_PIN, "phone" },
+	{ OFONO_SIM_PASSWORD_PHFSIM_PIN, "firstphone" },
+	{ OFONO_SIM_PASSWORD_PHFSIM_PUK, "firstphonepuk" },
+	{ OFONO_SIM_PASSWORD_PHNET_PIN, "network" },
+	{ OFONO_SIM_PASSWORD_PHNET_PUK, "networkpuk" },
+	{ OFONO_SIM_PASSWORD_PHNETSUB_PIN, "netsub" },
+	{ OFONO_SIM_PASSWORD_PHNETSUB_PUK, "netsubpuk" },
+	{ OFONO_SIM_PASSWORD_PHSP_PIN, "service" },
+	{ OFONO_SIM_PASSWORD_PHSP_PUK, "servicepuk" },
+	{ OFONO_SIM_PASSWORD_PHCORP_PIN, "corp" },
+	{ OFONO_SIM_PASSWORD_PHCORP_PUK, "corppuk" }
+};
+
+static const char *get_passwd_type_name(
+				enum ofono_sim_password_type passwd_enum)
+{
+	int i;
+	int passwd_dict_size;
+
+	passwd_dict_size = sizeof(passwd_dictionary) /
+					sizeof(struct passwd_type_dict);
+
+	for (i = 0; i < passwd_dict_size; i++) {
+		if (passwd_enum == passwd_dictionary[i].passwd_enum)
+			return passwd_dictionary[i].passwd_string;
+	}
+
+	return NULL;
+}
+
+static int get_password(const char *iccid,
+				enum ofono_sim_password_type passwd_type,
+				char **password)
+{
+	int result = -ENOENT;
+	const char *passwd_type_name;
+	GKeyFile *key_file = NULL;
+	char *setting_group = NULL;
+	char *value = NULL;
+
+	passwd_type_name = get_passwd_type_name(passwd_type);
+
+	if (passwd_type_name == NULL) {
+		DBG("unknown type %d", (int)passwd_type);
+		goto end;
+	}
+
+	DBG("Finding password for iccid %s, password type %s",
+						iccid, passwd_type_name);
+	key_file = g_key_file_new();
+
+	if (!g_key_file_load_from_file(key_file, CONFIG_FILE, 0, NULL))
+		goto end;
+
+	setting_group = g_try_malloc(strlen("sim:") + strlen(iccid) + 1);
+	if (setting_group == NULL) {
+		result = -ENOMEM;
+		goto end;
+	}
+
+	/* try with iccid */
+	sprintf(setting_group, "sim:%s", iccid);
+	value = g_key_file_get_string(key_file, setting_group,
+						passwd_type_name, NULL);
+
+	if (value != NULL)
+		goto end;
+
+	/* try default passwd */
+	value = g_key_file_get_string(key_file, "sim",
+						passwd_type_name, NULL);
+
+end:
+	if (key_file != NULL)
+		g_key_file_free(key_file);
+
+	if (setting_group != NULL)
+		g_free(setting_group);
+
+	if (value != NULL) {
+		DBG("Found. Password:%s", value);
+		*password = value;
+		result = 0;
+	} else {
+		DBG("Not found. Result:%d", result);
+	}
+
+	return result;
+}
+
+static struct ofono_sim_passwd_provision_driver provision_driver = {
+	.name		= "PIN provisioning",
+	.priority	= OFONO_PLUGIN_PRIORITY_HIGH,
+	.get_password	= get_password,
+};
+
+static int sim_password_provision_init(void)
+{
+	return ofono_sim_password_provision_driver_register(
+						&provision_driver);
+}
+
+static void sim_password_provision_exit(void)
+{
+	ofono_sim_password_provision_driver_unregister(
+						&provision_driver);
+}
+
+OFONO_PLUGIN_DEFINE(sim_file_provision, "SIM File Provisioning Plugin",
+			VERSION, OFONO_PLUGIN_PRIORITY_HIGH,
+			sim_password_provision_init,
+			sim_password_provision_exit)
diff --git a/src/ofono.h b/src/ofono.h
index a797b7ff..d27fe989 100644
--- a/src/ofono.h
+++ b/src/ofono.h
@@ -506,6 +506,11 @@ void __ofono_gprs_provision_free_settings(
 				struct ofono_gprs_provision_data *settings,
 				int count);
 
+#include <ofono/sim-passwd-provision.h>
+ofono_bool_t __ofono_sim_provision_get_password(const char *iccid,
+				enum ofono_sim_password_type password_type,
+				char **password);
+
 #include <ofono/emulator.h>
 
 enum ofono_emulator_slc_condition {
diff --git a/src/sim-password-provision.c b/src/sim-password-provision.c
new file mode 100644
index 00000000..cd295b1e
--- /dev/null
+++ b/src/sim-password-provision.c
@@ -0,0 +1,80 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 201  Kerlink SA.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include "ofono.h"
+
+static GSList *g_drivers = NULL;
+
+ofono_bool_t __ofono_sim_provision_get_password(const char *iccid,
+				enum ofono_sim_password_type password_type,
+				char **password)
+{
+	GSList *d;
+
+	if (iccid == NULL || strlen(iccid) == 0)
+		return FALSE;
+
+	for (d = g_drivers; d != NULL; d = d->next) {
+		const struct ofono_sim_passwd_provision_driver *driver =
+									d->data;
+
+		if (driver->get_password == NULL)
+			continue;
+
+		DBG("Calling sim password provisioning plugin '%s'",
+								driver->name);
+
+		if (driver->get_password(iccid, password_type, password) < 0)
+			continue;
+
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+static gint compare_priority(gconstpointer a, gconstpointer b)
+{
+	const struct ofono_sim_passwd_provision_driver *plugin1 = a;
+	const struct ofono_sim_passwd_provision_driver *plugin2 = b;
+
+	return plugin2->priority - plugin1->priority;
+}
+
+int ofono_sim_password_provision_driver_register(
+		const struct ofono_sim_passwd_provision_driver *driver)
+{
+	DBG("driver: %p name: %s", driver, driver->name);
+
+	g_drivers = g_slist_insert_sorted(g_drivers, (void *) driver,
+							compare_priority);
+	return 0;
+}
+
+void ofono_sim_password_provision_driver_unregister(
+		const struct ofono_sim_passwd_provision_driver *driver)
+{
+	DBG("driver: %p name: %s", driver, driver->name);
+
+	g_drivers = g_slist_remove(g_drivers, driver);
+}
diff --git a/src/sim.c b/src/sim.c
index ac5b6fde..7cb61991 100644
--- a/src/sim.c
+++ b/src/sim.c
@@ -61,6 +61,7 @@ struct ofono_sim {
 
 	enum ofono_sim_password_type pin_type;
 	gboolean locked_pins[OFONO_SIM_PASSWORD_SIM_PUK]; /* Number of PINs */
+	gboolean tried_provisionned_pins;
 
 	int pin_retries[OFONO_SIM_PASSWORD_INVALID];
 
@@ -2828,6 +2829,38 @@ ofono_bool_t ofono_sim_remove_spn_watch(struct ofono_sim *sim, unsigned int *id)
 	return ret;
 }
 
+static void sim_auto_enter_pin_cb(const struct ofono_error *error,
+								void *data)
+{
+	struct ofono_sim *sim = data;
+
+	__ofono_sim_recheck_pin(sim);
+}
+
+static void provision_password(struct ofono_sim *sim)
+{
+	char *password;
+
+	if (__ofono_sim_provision_get_password(sim->iccid, sim->pin_type,
+							&password) == FALSE) {
+		DBG("SIM password provisioning failed");
+		return;
+	}
+
+	/* try to enter password */
+	if (password_is_pin(sim->pin_type) == FALSE)
+		goto end;
+
+	if (!__ofono_is_valid_sim_pin(password, sim->pin_type))
+		goto end;
+
+	sim->tried_provisionned_pins = TRUE;
+	sim->driver->send_passwd(sim, password, sim_auto_enter_pin_cb, sim);
+
+end:
+	g_free(password);
+}
+
 static void sim_pin_query_cb(const struct ofono_error *error,
 				enum ofono_sim_password_type pin_type,
 				void *data)
@@ -2908,6 +2941,8 @@ static void sim_pin_query_cb(const struct ofono_error *error,
 		sim_initialize_after_pin(sim);
 		break;
 	default:
+		if (!sim->tried_provisionned_pins)
+			provision_password(sim);
 		break;
 	}
 }
-- 
2.11.0

_______________________________________________
ofono mailing list
ofono@ofono.org
https://lists.ofono.org/mailman/listinfo/ofono

Reply via email to