<p>laforge <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/osmo-remsim/+/20811">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Jenkins Builder: Verified
  laforge: Looks good to me, approved

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">bankd: regex matching of reader names<br><br>So far, bankd did a 1:1 string match of the CSV file line against<br>the reader name.  As pcsc-lite reader names unfortunately tend to<br>change at times, we introduce matching by regular expressions in<br>this patch.<br><br>Change-Id: I58b71f9562e152e7ed21b55d7b876bba481b01f8<br>---<br>M doc/manuals/chapters/remsim-bankd.adoc<br>M src/bankd/bankd_pcsc.c<br>2 files changed, 115 insertions(+), 13 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/doc/manuals/chapters/remsim-bankd.adoc b/doc/manuals/chapters/remsim-bankd.adoc</span><br><span>index e76afd5..87dafa1 100644</span><br><span>--- a/doc/manuals/chapters/remsim-bankd.adoc</span><br><span>+++ b/doc/manuals/chapters/remsim-bankd.adoc</span><br><span>@@ -108,6 +108,9 @@</span><br><span> </span><br><span> This CSV file specifies the mapping between the string names of the PCSC</span><br><span> readers and the RSPRO bandk/slot numbers.  The format is as follows:</span><br><span style="color: hsl(120, 100%, 40%);">+* first column: bankd number</span><br><span style="color: hsl(120, 100%, 40%);">+* second column: slot number within bankd</span><br><span style="color: hsl(120, 100%, 40%);">+* third column: extended POSIX regular expression matching the slot</span><br><span> </span><br><span> .Example: CSV file mapping bankd slots 0..4 to an ACS ACR33U-A1 reader slots</span><br><span> ----</span><br><span>@@ -128,4 +131,24 @@</span><br><span> ----</span><br><span> </span><br><span> In this example, there's only a single PC/SC reader available, and it has a string of</span><br><span style="color: hsl(0, 100%, 40%);">-"Alcor Micro AU9560 00 00" which needs to be copy-pasted into the CSV file.</span><br><span style="color: hsl(120, 100%, 40%);">+"Alcor Micro AU9560 00 00" which needs to be used in the CSV file.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+NOTE:: If the reader name contains any special characters, they might need to be escaped according</span><br><span style="color: hsl(120, 100%, 40%);">+to the extended POSIX regular expression syntax. See `man 7 regex` for a reference.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+.Example: CSV file mapping bankd slots 0..7 to a sysmoOCTSIM:</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+"1","0","sysmocom sysmoOCTSIM \[CCID\] \(ab19180f3335355320202034463a15ff\) [0-9]{2} 00"</span><br><span style="color: hsl(120, 100%, 40%);">+"1","1","sysmocom sysmoOCTSIM \[CCID\] \(ab19180f3335355320202034463a15ff\) [0-9]{2} 01"</span><br><span style="color: hsl(120, 100%, 40%);">+"1","2","sysmocom sysmoOCTSIM \[CCID\] \(ab19180f3335355320202034463a15ff\) [0-9]{2} 02"</span><br><span style="color: hsl(120, 100%, 40%);">+"1","3","sysmocom sysmoOCTSIM \[CCID\] \(ab19180f3335355320202034463a15ff\) [0-9]{2} 03"</span><br><span style="color: hsl(120, 100%, 40%);">+"1","4","sysmocom sysmoOCTSIM \[CCID\] \(ab19180f3335355320202034463a15ff\) [0-9]{2} 04"</span><br><span style="color: hsl(120, 100%, 40%);">+"1","5","sysmocom sysmoOCTSIM \[CCID\] \(ab19180f3335355320202034463a15ff\) [0-9]{2} 05"</span><br><span style="color: hsl(120, 100%, 40%);">+"1","6","sysmocom sysmoOCTSIM \[CCID\] \(ab19180f3335355320202034463a15ff\) [0-9]{2} 06"</span><br><span style="color: hsl(120, 100%, 40%);">+"1","7","sysmocom sysmoOCTSIM \[CCID\] \(ab19180f3335355320202034463a15ff\) [0-9]{2} 07"</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+In the above example, the +\[CCID\]+ and the +\(serialnumber\)+ both had to be escaped.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+The +[0-9]\{2\}+ construct exists to perform wildcard matching, no matter which particular two-digit number</span><br><span style="color: hsl(120, 100%, 40%);">+pcscd decides to use.</span><br><span>diff --git a/src/bankd/bankd_pcsc.c b/src/bankd/bankd_pcsc.c</span><br><span>index f6e3683..e0b349c 100644</span><br><span>--- a/src/bankd/bankd_pcsc.c</span><br><span>+++ b/src/bankd/bankd_pcsc.c</span><br><span>@@ -1,4 +1,4 @@</span><br><span style="color: hsl(0, 100%, 40%);">-/* (C) 2018-2019 by Harald Welte <laforge@gnumonks.org></span><br><span style="color: hsl(120, 100%, 40%);">+/* (C) 2018-2020 by Harald Welte <laforge@gnumonks.org></span><br><span>  *</span><br><span>  * All Rights Reserved</span><br><span>  *</span><br><span>@@ -26,6 +26,8 @@</span><br><span> #include <osmocom/core/utils.h></span><br><span> </span><br><span> #include <csv.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <regex.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <errno.h></span><br><span> </span><br><span> #include "bankd.h"</span><br><span> </span><br><span>@@ -34,9 +36,19 @@</span><br><span>    /* RSPRO bank slot number */</span><br><span>         struct bank_slot slot;</span><br><span>       /* String name of the reader in PC/SC world */</span><br><span style="color: hsl(0, 100%, 40%);">-  const char *name;</span><br><span style="color: hsl(120, 100%, 40%);">+     const char *name_regex;</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* return a talloc-allocated string containing human-readable POSIX regex error */</span><br><span style="color: hsl(120, 100%, 40%);">+static char *get_regerror(void *ctx, int errcode, regex_t *compiled)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        size_t len = regerror(errcode, compiled, NULL, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+    char *buffer = talloc_size(ctx, len);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(buffer);</span><br><span style="color: hsl(120, 100%, 40%);">+  regerror(errcode, compiled, buffer, len);</span><br><span style="color: hsl(120, 100%, 40%);">+     return buffer;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> enum parser_state_name {</span><br><span>      ST_NONE,</span><br><span>     ST_BANK_NR,</span><br><span>@@ -76,7 +88,7 @@</span><br><span>              break;</span><br><span>       case ST_PCSC_NAME:</span><br><span>           OSMO_ASSERT(ps->cur);</span><br><span style="color: hsl(0, 100%, 40%);">-                ps->cur->name = talloc_strdup(ps->cur, field);</span><br><span style="color: hsl(120, 100%, 40%);">+               ps->cur->name_regex = talloc_strdup(ps->cur, field);</span><br><span>                break;</span><br><span>       default:</span><br><span>             OSMO_ASSERT(0);</span><br><span>@@ -87,9 +99,23 @@</span><br><span> {</span><br><span>    struct parser_state *ps = data;</span><br><span>      struct pcsc_slot_name *sn = ps->cur;</span><br><span style="color: hsl(120, 100%, 40%);">+       regex_t compiled_name;</span><br><span style="color: hsl(120, 100%, 40%);">+        int rc;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     printf("PC/SC slot name: %u/%u -> '%s'\n", sn->slot.bank_id, sn->slot.slot_nr, sn->name);</span><br><span style="color: hsl(0, 100%, 40%);">- llist_add_tail(&sn->list, &ps->bankd->pcsc_slot_names);</span><br><span style="color: hsl(120, 100%, 40%);">+      printf("PC/SC slot name: %u/%u -> regex '%s'\n", sn->slot.bank_id, sn->slot.slot_nr, sn->name_regex);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ memset(&compiled_name, 0, sizeof(compiled_name));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       rc = regcomp(&compiled_name, sn->name_regex, REG_EXTENDED);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (rc != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                char *errmsg = get_regerror(sn, rc, &compiled_name);</span><br><span style="color: hsl(120, 100%, 40%);">+              fprintf(stderr, "Error compiling regex '%s': %s - Ignoring\n", sn->name_regex, errmsg);</span><br><span style="color: hsl(120, 100%, 40%);">+          talloc_free(errmsg);</span><br><span style="color: hsl(120, 100%, 40%);">+          talloc_free(sn);</span><br><span style="color: hsl(120, 100%, 40%);">+      } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              llist_add_tail(&sn->list, &ps->bankd->pcsc_slot_names);</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+     regfree(&compiled_name);</span><br><span> </span><br><span>     ps->state = ST_BANK_NR;</span><br><span>   ps->cur = NULL;</span><br><span>@@ -134,7 +160,7 @@</span><br><span> </span><br><span>         llist_for_each_entry(cur, &bankd->pcsc_slot_names, list) {</span><br><span>            if (bank_slot_equals(&cur->slot, slot))</span><br><span style="color: hsl(0, 100%, 40%);">-                  return cur->name;</span><br><span style="color: hsl(120, 100%, 40%);">+                  return cur->name_regex;</span><br><span>   }</span><br><span>    return NULL;</span><br><span> }</span><br><span>@@ -144,9 +170,12 @@</span><br><span> #include <winscard.h></span><br><span> #include <pcsclite.h></span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#define LOGW_PCSC_ERROR(w, rv, text) \</span><br><span style="color: hsl(120, 100%, 40%);">+    LOGW((w), text ": %s (0x%lX)\n", pcsc_stringify_error(rv), rv)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #define PCSC_ERROR(w, rv, text) \</span><br><span> if (rv != SCARD_S_SUCCESS) { \</span><br><span style="color: hsl(0, 100%, 40%);">-       LOGW((w), text ": %s (0x%lX)\n", pcsc_stringify_error(rv), rv); \</span><br><span style="color: hsl(120, 100%, 40%);">+   LOGW_PCSC_ERROR(w, rv, text); \</span><br><span>      goto end; \</span><br><span> } else { \</span><br><span>         LOGW((w), ": OK\n"); \</span><br><span>@@ -170,6 +199,57 @@</span><br><span>         return rc;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int pcsc_connect_slot_regex(struct bankd_worker *worker)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     DWORD dwReaders = SCARD_AUTOALLOCATE;</span><br><span style="color: hsl(120, 100%, 40%);">+ LPSTR mszReaders = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+      regex_t compiled_name;</span><br><span style="color: hsl(120, 100%, 40%);">+        int result = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+      LONG rc;</span><br><span style="color: hsl(120, 100%, 40%);">+      char *p;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    LOGW(worker, "Attempting to find card/slot using regex '%s'\n", worker->reader.name);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  rc = regcomp(&compiled_name, worker->reader.name, REG_EXTENDED);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (rc != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                LOGW(worker, "Error compiling RegEx over name '%s'\n", worker->reader.name);</span><br><span style="color: hsl(120, 100%, 40%);">+             return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   rc = SCardListReaders(worker->reader.pcsc.hContext, NULL, (LPSTR)&mszReaders, &dwReaders);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc != SCARD_S_SUCCESS) {</span><br><span style="color: hsl(120, 100%, 40%);">+          LOGW_PCSC_ERROR(worker, rc, "SCardListReaders");</span><br><span style="color: hsl(120, 100%, 40%);">+            goto out_regfree;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   p = mszReaders;</span><br><span style="color: hsl(120, 100%, 40%);">+       while (*p) {</span><br><span style="color: hsl(120, 100%, 40%);">+          DWORD dwActiveProtocol;</span><br><span style="color: hsl(120, 100%, 40%);">+               int r = regexec(&compiled_name, p, 0, NULL, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+           if (r == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 LOGW(worker, "Attempting to open card/slot '%s'\n", p);</span><br><span style="color: hsl(120, 100%, 40%);">+                     rc = SCardConnect(worker->reader.pcsc.hContext, p, SCARD_SHARE_SHARED,</span><br><span style="color: hsl(120, 100%, 40%);">+                                       SCARD_PROTOCOL_T0, &worker->reader.pcsc.hCard,</span><br><span style="color: hsl(120, 100%, 40%);">+                                         &dwActiveProtocol);</span><br><span style="color: hsl(120, 100%, 40%);">+                     if (rc == SCARD_S_SUCCESS)</span><br><span style="color: hsl(120, 100%, 40%);">+                            result = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                   else</span><br><span style="color: hsl(120, 100%, 40%);">+                          LOGW_PCSC_ERROR(worker, rc, "SCardConnect");</span><br><span style="color: hsl(120, 100%, 40%);">+                        break;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+             p += strlen(p) + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   SCardFreeMemory(worker->reader.pcsc.hContext, mszReaders);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+out_regfree:</span><br><span style="color: hsl(120, 100%, 40%);">+ regfree(&compiled_name);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        return result;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static int pcsc_open_card(struct bankd_worker *worker)</span><br><span> {</span><br><span>         long rc;</span><br><span>@@ -182,14 +262,13 @@</span><br><span>     }</span><br><span> </span><br><span>        if (!worker->reader.pcsc.hCard) {</span><br><span style="color: hsl(0, 100%, 40%);">-            LOGW(worker, "Attempting to open card/slot '%s'\n", worker->reader.name);</span><br><span style="color: hsl(0, 100%, 40%);">-          DWORD dwActiveProtocol;</span><br><span style="color: hsl(0, 100%, 40%);">-         rc = SCardConnect(worker->reader.pcsc.hContext, worker->reader.name, SCARD_SHARE_SHARED,</span><br><span style="color: hsl(0, 100%, 40%);">-                            SCARD_PROTOCOL_T0, &worker->reader.pcsc.hCard, &dwActiveProtocol);</span><br><span style="color: hsl(0, 100%, 40%);">-         PCSC_ERROR(worker, rc, "SCardConnect")</span><br><span style="color: hsl(120, 100%, 40%);">+              rc = pcsc_connect_slot_regex(worker);</span><br><span style="color: hsl(120, 100%, 40%);">+         if (rc != 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                  goto end;</span><br><span>    }</span><br><span> </span><br><span>        rc = pcsc_get_atr(worker);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> end:</span><br><span>         return rc;</span><br><span> }</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-remsim/+/20811">change 20811</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/osmo-remsim/+/20811"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-remsim </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I58b71f9562e152e7ed21b55d7b876bba481b01f8 </div>
<div style="display:none"> Gerrit-Change-Number: 20811 </div>
<div style="display:none"> Gerrit-PatchSet: 2 </div>
<div style="display:none"> Gerrit-Owner: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>