Skip to content

Commit

Permalink
pivy-agent: call SCardEstablishContext again on certain errors
Browse files Browse the repository at this point in the history
This allows the pivy-agent to continue running after a pcscd
restart or certain MacOS power mgmt operations.
  • Loading branch information
arekinath committed Jul 24, 2020
1 parent d120209 commit bb4aa9d
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 5 deletions.
22 changes: 20 additions & 2 deletions piv.c
Original file line number Diff line number Diff line change
Expand Up @@ -1096,7 +1096,16 @@ piv_enumerate(SCARDCONTEXT ctx, struct piv_token **tokens)
errf_t *err;

rv = SCardListReaders(ctx, NULL, NULL, &readersLen);
if (rv != SCARD_S_SUCCESS) {
switch (rv) {
case SCARD_S_SUCCESS:
break;
case SCARD_E_NO_SERVICE:
case SCARD_E_INVALID_HANDLE:
case SCARD_E_SERVICE_STOPPED:
return (errf("PCSCContextError",
pcscerrf("SCardListReaders", rv),
"PCSC context is not functional"));
default:
return (pcscerrf("SCardListReaders", rv));
}
readers = calloc(1, readersLen);
Expand Down Expand Up @@ -1215,7 +1224,16 @@ piv_find(SCARDCONTEXT ctx, const uint8_t *guid, size_t guidlen,
errf_t *err;

rv = SCardListReaders(ctx, NULL, NULL, &readersLen);
if (rv != SCARD_S_SUCCESS) {
switch (rv) {
case SCARD_S_SUCCESS:
break;
case SCARD_E_NO_SERVICE:
case SCARD_E_INVALID_HANDLE:
case SCARD_E_SERVICE_STOPPED:
return (errf("PCSCContextError",
pcscerrf("SCardListReaders", rv),
"PCSC context is not functional"));
default:
return (pcscerrf("SCardListReaders", rv));
}
readers = calloc(1, readersLen);
Expand Down
2 changes: 2 additions & 0 deletions piv.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,8 @@ errf_t *piv_enumerate(SCARDCONTEXT ctx, struct piv_token **tokens);
*
* Errors:
* - PCSCError: a PCSC call failed in a way that is not retryable
* - PCSCContextError: a PCSC call failed in a way that indicates the
* SCARDCONTEXT is no longer valid
* - DuplicateError: a GUID prefix was given and it is not unique on the system
* - NotFoundError: token matching the guid was not found
*/
Expand Down
25 changes: 22 additions & 3 deletions pivy-agent.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@
"(try ssh-add -X)")
#define flagserrf(val) \
errf("FlagsError", NULL, "unsupported flags value: %x", val)
#define pcscerrf(call, rv) \
errf("PCSCError", NULL, call " failed: %d (%s)", \
rv, pcsc_stringify_error(rv))

typedef enum confirm_mode {
C_NEVER,
Expand Down Expand Up @@ -418,6 +421,7 @@ agent_piv_open(void)
{
struct piv_slot *slot;
errf_t *err = NULL;
int rv;

if (txnopen) {
txntimeout = monotime() + 2000;
Expand All @@ -431,8 +435,22 @@ agent_piv_open(void)
if (ks != NULL)
piv_release(ks);

findagain:
err = piv_find(ctx, guid, guid_len, &ks);
if (err) {
if (err && errf_caused_by(err, "PCSCContextError")) {
ks = NULL;
bunyan_log(BNY_TRACE, "got context error, re-initing",
"error", BNY_ERF, err, NULL);
errf_free(err);
SCardReleaseContext(ctx);
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL,
NULL, &ctx);
if (rv != SCARD_S_SUCCESS) {
err = pcscerrf("SCardEstablishContext", rv);
return (err);
}
goto findagain;
} else if (err) {
ks = NULL;
err = errf("EnumerationError", err, "Failed to "
"find specified PIV token on the system");
Expand Down Expand Up @@ -2797,8 +2815,9 @@ main(int ac, char **av)

r = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &ctx);
if (r != SCARD_S_SUCCESS) {
bunyan_log(BNY_ERROR, "SCardEstablishContext failed",
"error", BNY_STRING, pcsc_stringify_error(r), NULL);
err = pcscerrf("SCardEstablishContext", r);
bunyan_log(BNY_ERROR, "error setting up PCSC lib context",
"error", BNY_ERF, err, NULL);
return (1);
}

Expand Down

0 comments on commit bb4aa9d

Please sign in to comment.