From 2797211645d452446cb7b329ee9d3d3a923f8520 Mon Sep 17 00:00:00 2001 From: laforge Date: Sat, 10 Mar 2007 02:22:04 +0000 Subject: * properly implement PIN/PUK handling throughout gsmd/libgsmd/util git-svn-id: http://svn.openmoko.org/trunk/src/target/gsm@1314 99fdad57-331a-0410-800a-d7fa5415bdb3 --- include/gsmd/usock.h | 7 +++++ include/libgsmd/libgsmd.h | 4 ++- include/libgsmd/pin.h | 8 +++++ src/gsmd/usock.c | 46 +++++++++++++++++++++++++--- src/gsmd/vendor_ti.c | 5 +++ src/libgsmd/Makefile.am | 2 +- src/libgsmd/libgsmd.c | 20 +----------- src/libgsmd/libgsmd_pin.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++ src/util/pin.c | 31 ++++++++++++++----- 9 files changed, 168 insertions(+), 33 deletions(-) create mode 100644 include/libgsmd/pin.h create mode 100644 src/libgsmd/libgsmd_pin.c diff --git a/include/gsmd/usock.h b/include/gsmd/usock.h index 530eed7..cb5e0b9 100644 --- a/include/gsmd/usock.h +++ b/include/gsmd/usock.h @@ -86,6 +86,13 @@ struct gsmd_voicemail { struct gsmd_addr addr; } __attribute__ ((packed)); +#define GSMD_PIN_MAXLEN 8 +struct gsmd_pin { + enum gsmd_pin_type type; + char pin[GSMD_PIN_MAXLEN+1]; + char newpin[GSMD_PIN_MAXLEN+1]; +} __attribute__ ((packed)); + struct gsmd_evt_auxdata { union { struct { diff --git a/include/libgsmd/libgsmd.h b/include/libgsmd/libgsmd.h index a89f4b6..8c34c6a 100644 --- a/include/libgsmd/libgsmd.h +++ b/include/libgsmd/libgsmd.h @@ -63,5 +63,7 @@ extern int lgsm_passthrough_send(struct lgsm_handle *lh, const char *tx); extern int lgsm_passthrough(struct lgsm_handle *lh, const char *tx, char *rx, unsigned int *rx_len); extern int lgsm_subscriptions(struct lgsm_handle *lh, u_int32_t subscriptions); -extern int lgsm_pin(struct lgsm_handle *lh, char *pin); +extern struct gsmd_msg_hdr *lgsm_gmh_fill(int type, int subtype, int payload_len); +extern int lgsm_send(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh); + #endif diff --git a/include/libgsmd/pin.h b/include/libgsmd/pin.h new file mode 100644 index 0000000..304455f --- /dev/null +++ b/include/libgsmd/pin.h @@ -0,0 +1,8 @@ +#ifndef _LGSM_PIN_H +#define _LGSM_PIN_H + +extern const char *lgsm_pin_name(enum gsmd_pin_type ptype); + +extern int lgsm_pin(struct lgsm_handle *lh, unsigned int type, char *pin, char *newpin); + +#endif diff --git a/src/gsmd/usock.c b/src/gsmd/usock.c index 0337b5e..31292e8 100644 --- a/src/gsmd/usock.c +++ b/src/gsmd/usock.c @@ -38,6 +38,7 @@ #include #include #include +#include static void *__ucmd_ctx, *__gu_ctx; @@ -173,13 +174,37 @@ static int null_cmd_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp) return 0; } +/* PIN command callback. Gets called for response to AT+CPIN cmcd */ +static int pin_cmd_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp) +{ + gsmd_log(GSMD_DEBUG, "pin cmd cb\n"); + + /* We need to verify if there is some error */ + switch (cmd->ret) { + case 0: + break; + case GSM0707_CME_INCORRECT_PASSWORD: + /* prompt for pin again */ + break; + default: + /* something went wrong */ + break; + } + return 0; +} + static int usock_rcv_pin(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, int len) { - u_int8_t *pin = (u_int8_t *)gph + sizeof(*gph); - int pin_len = len - sizeof(*gph); + struct gsmd_pin *gp = (struct gsmd_pin *) ((void *)gph + sizeof(*gph)); struct gsmd_atcmd *cmd; + if (gph->len < sizeof(*gp) || len < sizeof(*gp)+sizeof(*gph)) + return -EINVAL; + + gsmd_log(GSMD_DEBUG, "pin type=%u, pin='%s', newpin='%s'\n", + gp->type, gp->pin, gp->newpin); + switch (gph->msg_subtype) { case GSMD_PIN_INPUT: /* FIXME */ @@ -190,12 +215,23 @@ static int usock_rcv_pin(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, return -EINVAL; } - cmd = atcmd_fill("AT+CPIN=\"", 9+1+1+strlen(pin), - &null_cmd_cb, gu, 0); + cmd = atcmd_fill("AT+CPIN=\"", 9+GSMD_PIN_MAXLEN+3+GSMD_PIN_MAXLEN+2, + &pin_cmd_cb, gu, 0); if (!cmd) return -ENOMEM; - strcat(cmd->buf, pin); + strcat(cmd->buf, gp->pin); + + switch (gp->type) { + case GSMD_PIN_SIM_PUK: + case GSMD_PIN_SIM_PUK2: + strcat(cmd->buf, "\",\""); + strcat(cmd->buf, gp->newpin); + break; + default: + break; + } + strcat(cmd->buf, "\""); return atcmd_submit(gu->gsmd, cmd); diff --git a/src/gsmd/vendor_ti.c b/src/gsmd/vendor_ti.c index 53c0365..6617edf 100644 --- a/src/gsmd/vendor_ti.c +++ b/src/gsmd/vendor_ti.c @@ -235,6 +235,11 @@ static const struct gsmd_unsolicit ticalypso_unsolicit[] = { /* %CGEV: reports GPRS network events */ }; +static int cpi_detect_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp) +{ + +} + static int ticalypso_detect(struct gsmd *g) { /* FIXME: do actual detection of vendor if we have multiple vendors */ diff --git a/src/libgsmd/Makefile.am b/src/libgsmd/Makefile.am index a1ee710..5ea36f1 100644 --- a/src/libgsmd/Makefile.am +++ b/src/libgsmd/Makefile.am @@ -5,6 +5,6 @@ AM_CFLAGS = -std=gnu99 lib_LTLIBRARIES = libgsmd.la libgsmd_la_LDFLAGS = -Wc,-nostartfiles -version-info $(LIBVERSION) -libgsmd_la_SOURCES = libgsmd.c libgsmd_input.c libgsmd_voicecall.c libgsmd_passthrough.c libgsmd_event.c libgsmd_phone.c libgsmd_network.c +libgsmd_la_SOURCES = libgsmd.c libgsmd_input.c libgsmd_voicecall.c libgsmd_passthrough.c libgsmd_event.c libgsmd_phone.c libgsmd_network.c libgsmd_pin.c noinst_HEADERS = lgsm_internals.h diff --git a/src/libgsmd/libgsmd.c b/src/libgsmd/libgsmd.c index 59f04ed..11760b4 100644 --- a/src/libgsmd/libgsmd.c +++ b/src/libgsmd/libgsmd.c @@ -197,7 +197,7 @@ struct gsmd_msg_hdr *lgsm_gmh_fill(int type, int subtype, int payload_len) if (!gmh) return NULL; - memset(gmh, 0, sizeof(*gmh)); + memset(gmh, 0, sizeof(*gmh)+payload_len); gmh->version = GSMD_PROTO_VERSION; gmh->msg_type = type; @@ -207,21 +207,3 @@ struct gsmd_msg_hdr *lgsm_gmh_fill(int type, int subtype, int payload_len) return gmh; } - -int lgsm_pin(struct lgsm_handle *lh, char *pin) -{ - int rc; - struct gsmd_msg_hdr *gmh; - - gmh = lgsm_gmh_fill(GSMD_MSG_PIN, GSMD_PIN_INPUT, strlen(pin)+1); - if (!gmh) - return -ENOMEM; - - gmh->data[0] = '\0'; - strcat(gmh->data, pin); - - rc = lgsm_send(lh, gmh); - free(gmh); - - return rc; -} diff --git a/src/libgsmd/libgsmd_pin.c b/src/libgsmd/libgsmd_pin.c new file mode 100644 index 0000000..e645dd5 --- /dev/null +++ b/src/libgsmd/libgsmd_pin.c @@ -0,0 +1,78 @@ +#include +#include +#include + +#include +#include +#include + +static const char *pin_type_names[__NUM_GSMD_PIN] = { + [GSMD_PIN_NONE] = "NONE", + [GSMD_PIN_SIM_PIN] = "SIM PIN", + [GSMD_PIN_SIM_PUK] = "SIM PUK", + [GSMD_PIN_PH_SIM_PIN] = "Phone-to-SIM PIN", + [GSMD_PIN_PH_FSIM_PIN] = "Phone-to-very-first SIM PIN", + [GSMD_PIN_PH_FSIM_PUK] = "Phone-to-very-first SIM PUK", + [GSMD_PIN_SIM_PIN2] = "SIM PIN2", + [GSMD_PIN_SIM_PUK2] = "SIM PUK2", + [GSMD_PIN_PH_NET_PIN] = "Network personalization PIN", + [GSMD_PIN_PH_NET_PUK] = "Network personalizaiton PUK", + [GSMD_PIN_PH_NETSUB_PIN]= "Network subset personalisation PIN", + [GSMD_PIN_PH_NETSUB_PUK]= "Network subset personalisation PUK", + [GSMD_PIN_PH_SP_PIN] = "Service provider personalisation PIN", + [GSMD_PIN_PH_SP_PUK] = "Service provider personalisation PUK", + [GSMD_PIN_PH_CORP_PIN] = "Corporate personalisation PIN", + [GSMD_PIN_PH_CORP_PUK] = "Corporate personalisation PUK", +}; + +const char *lgsm_pin_name(enum gsmd_pin_type ptype) +{ + if (ptype >= __NUM_GSMD_PIN) + return "unknown"; + + return pin_type_names[ptype]; +} + +int lgsm_pin(struct lgsm_handle *lh, unsigned int type, char *pin, char *newpin) +{ + int rc; + struct { + struct gsmd_msg_hdr gmh; + struct gsmd_pin gp; + } __attribute__ ((packed)) *gm; + + if (strlen(pin) > GSMD_PIN_MAXLEN || + (newpin && strlen(newpin) > GSMD_PIN_MAXLEN) || + type >= __NUM_GSMD_PIN) + return -EINVAL; + + gm = (void *) lgsm_gmh_fill(GSMD_MSG_PIN, GSMD_PIN_INPUT, + sizeof(struct gsmd_pin)); + if (!gm) + return -ENOMEM; + + gm->gp.type = type; + + gm->gp.pin[0] = '\0'; + strcat(gm->gp.pin, pin); + + switch (type) { + case GSMD_PIN_SIM_PUK: + case GSMD_PIN_SIM_PUK2: + /* GSM 07.07 explicitly states that only those two PUK types + * require a new pin to be specified! Don't know if this is a + * bug or a feature. */ + if (!newpin) + return -EINVAL; + gm->gp.newpin[0] = '\0'; + strcat(gm->gp.newpin, newpin); + break; + default: + break; + } + printf("sending pin='%s', newpin='%s'\n", gm->gp.pin, gm->gp.newpin); + rc = lgsm_send(lh, &gm->gmh); + free(gm); + + return rc; +} diff --git a/src/util/pin.c b/src/util/pin.c index 7bfd8da..fdd0099 100644 --- a/src/util/pin.c +++ b/src/util/pin.c @@ -25,29 +25,46 @@ #include #include +#include -#define PIN_SIZE 32 +#define PIN_SIZE 8 static char *pin; static char pinbuf[PIN_SIZE+1]; +static char pinbuf2[PIN_SIZE+1]; static int pin_handler(struct lgsm_handle *lh, int evt, struct gsmd_evt_auxdata *aux) { int rc; + int type = aux->u.pin.type; + char *newpin = NULL; - printf("EVENT: PIN request (type=%u) ", aux->u.pin.type); + printf("EVENT: PIN request (type='%s') ", lgsm_pin_name(aux->u.pin.type)); /* FIXME: read pin from STDIN and send it back via lgsm_pin */ - if (aux->u.pin.type == 1 && pin) { + if (type == 1 && pin) { printf("Auto-responding with pin `%s'\n", pin); - lgsm_pin(lh, pin); + lgsm_pin(lh, type, pin, NULL); } else { do { - printf("Please enter PIN: "); - rc = fscanf(stdin, "%32s", &pinbuf); + printf("Please enter %s: ", lgsm_pin_name(type)); + rc = fscanf(stdin, "%8s", &pinbuf); } while (rc < 1); - return lgsm_pin(lh, pinbuf); + switch (type) { + case GSMD_PIN_SIM_PUK: + case GSMD_PIN_SIM_PUK2: + do { + printf("Please enter new PIN: "); + rc = fscanf(stdin, "%8s", &pinbuf2); + newpin = pinbuf2; + } while (rc < 1); + break; + default: + break; + } + + return lgsm_pin(lh, type, pinbuf, newpin); } return 0; -- cgit v1.2.3