diff --git a/src/objects.c b/src/objects.c index 89878ffc..8b523a43 100644 --- a/src/objects.c +++ b/src/objects.c @@ -40,6 +40,8 @@ struct p11prov_obj { CK_BBOOL cka_copyable; CK_BBOOL cka_token; + P11PROV_URI *refresh_uri; + union { struct p11prov_key key; struct p11prov_crt crt; @@ -1031,6 +1033,9 @@ CK_RV p11prov_obj_find(P11PROV_CTX *provctx, P11PROV_SESSION *session, /* unknown object or other recoverable error to ignore */ continue; } else if (ret == CKR_OK) { + /* keep a copy of the URI for refreshes as it may contain + * things like a PIN necessary to log in */ + obj->refresh_uri = p11prov_copy_uri(uri); ret = cb(cb_ctx, obj); } if (ret != CKR_OK) { @@ -1116,13 +1121,88 @@ static P11PROV_OBJ *find_associated_obj(P11PROV_CTX *provctx, P11PROV_OBJ *obj, static void p11prov_obj_refresh(P11PROV_OBJ *obj) { + int login_behavior; + bool login = false; + CK_SLOT_ID slotid = CK_UNAVAILABLE_INFORMATION; + P11PROV_SESSION *session = NULL; + CK_SESSION_HANDLE sess = CK_INVALID_HANDLE; + CK_ATTRIBUTE template[3] = { 0 }; + CK_ATTRIBUTE *attr; + int anum; + CK_OBJECT_HANDLE handle; + CK_ULONG objcount = 0; P11PROV_OBJ *tmp = NULL; - tmp = find_associated_obj(obj->ctx, obj, obj->class); - if (!tmp) { - /* nothing we can do, invalid handle it is */ + CK_RV ret; + + P11PROV_debug("Refresh object %p", obj); + + if (obj->class == CKO_PRIVATE_KEY) { + login = true; + } + login_behavior = p11prov_ctx_login_behavior(obj->ctx); + if (login_behavior == PUBKEY_LOGIN_ALWAYS) { + login = true; + } + + slotid = p11prov_obj_get_slotid(obj); + + ret = p11prov_get_session(obj->ctx, &slotid, NULL, obj->refresh_uri, + CK_UNAVAILABLE_INFORMATION, NULL, NULL, login, + false, &session); + + if (ret != CKR_OK) { + P11PROV_debug("Failed to get session to refresh object %p", obj); return; } + sess = p11prov_session_handle(session); + + anum = 0; + CKATTR_ASSIGN(template[anum], CKA_CLASS, &(obj->class), sizeof(obj->class)); + anum++; + /* use CKA_ID if available */ + attr = p11prov_obj_get_attr(obj, CKA_ID); + if (attr) { + template[anum] = *attr; + anum++; + } + /* use Label if available */ + attr = p11prov_obj_get_attr(obj, CKA_LABEL); + if (attr) { + template[anum] = *attr; + anum++; + } + + ret = p11prov_FindObjectsInit(obj->ctx, sess, template, anum); + if (ret != CKR_OK) { + goto done; + } + + /* we expect a single entry */ + ret = p11prov_FindObjects(obj->ctx, sess, &handle, 1, &objcount); + + /* Finalizing is not fatal so ignore result */ + p11prov_FindObjectsFinal(obj->ctx, sess); + + if (ret != CKR_OK || objcount == 0) { + P11PROV_raise(obj->ctx, ret, + "Failed to find refresh object %p (count=%ld)", obj, + objcount); + goto done; + } + if (objcount != 1) { + P11PROV_raise(obj->ctx, ret, + "Too many objects found on refresh (count=%ld)", + objcount); + goto done; + } + + ret = p11prov_obj_from_handle(obj->ctx, session, handle, &tmp); + if (ret != CKR_OK) { + P11PROV_raise(obj->ctx, ret, "Failed to get object from handle"); + goto done; + } + /* move over all the object data, then free the tmp */ obj->handle = tmp->handle; obj->cached = tmp->cached; @@ -1144,6 +1224,9 @@ static void p11prov_obj_refresh(P11PROV_OBJ *obj) * cause use-after-free issues */ p11prov_obj_free(tmp); obj->raf = false; + +done: + p11prov_return_session(session); } #define SECRET_KEY_ATTRS 2 diff --git a/src/util.c b/src/util.c index 644333d0..c1f12769 100644 --- a/src/util.c +++ b/src/util.c @@ -320,6 +320,15 @@ static int get_pin_file(P11PROV_CTX *ctx, const char *str, size_t len, return ret; } +#define COPY_STRUCT_MEMBER(dst, src, _name) \ + if ((src)->_name) { \ + (dst)->_name = strdup((src)->_name); \ + if (!(dst)->_name) { \ + p11prov_uri_free((dst)); \ + return NULL; \ + } \ + } + static void p11prov_uri_free_int(P11PROV_URI *uri) { OPENSSL_free(uri->library_manufacturer); @@ -795,16 +804,33 @@ CK_OBJECT_CLASS p11prov_uri_get_class(P11PROV_URI *uri) return uri->type; } +void p11prov_uri_set_class(P11PROV_URI *uri, CK_OBJECT_CLASS class) +{ + uri->type = class; +} + CK_ATTRIBUTE p11prov_uri_get_id(P11PROV_URI *uri) { return uri->id; } +void p11prov_uri_set_id(P11PROV_URI *uri, CK_ATTRIBUTE *id) +{ + OPENSSL_free(uri->id.pValue); + p11prov_copy_attr(&uri->id, id); +} + CK_ATTRIBUTE p11prov_uri_get_label(P11PROV_URI *uri) { return uri->object; } +void p11prov_uri_set_label(P11PROV_URI *uri, CK_ATTRIBUTE *label) +{ + OPENSSL_free(uri->object.pValue); + p11prov_copy_attr(&uri->object, label); +} + char *p11prov_uri_get_serial(P11PROV_URI *uri) { return uri->serial; @@ -815,6 +841,55 @@ char *p11prov_uri_get_pin(P11PROV_URI *uri) return uri->pin; } +CK_SLOT_ID p11prov_uri_get_slot_id(P11PROV_URI *uri) +{ + return uri->slot_id; +} + +void p11prov_uri_set_slot_id(P11PROV_URI *uri, CK_SLOT_ID slot_id) +{ + uri->slot_id = slot_id; +} + +P11PROV_URI *p11prov_copy_uri(P11PROV_URI *uri) +{ + P11PROV_URI *cu; + CK_RV rv; + + cu = OPENSSL_zalloc(sizeof(P11PROV_URI)); + if (!cu) { + return NULL; + } + + COPY_STRUCT_MEMBER(cu, uri, library_manufacturer) + COPY_STRUCT_MEMBER(cu, uri, library_description) + COPY_STRUCT_MEMBER(cu, uri, token) + COPY_STRUCT_MEMBER(cu, uri, manufacturer) + COPY_STRUCT_MEMBER(cu, uri, model) + COPY_STRUCT_MEMBER(cu, uri, serial) + COPY_STRUCT_MEMBER(cu, uri, slot_description) + COPY_STRUCT_MEMBER(cu, uri, slot_manufacturer) + COPY_STRUCT_MEMBER(cu, uri, pin) + + rv = p11prov_copy_attr(&cu->id, &uri->id); + if (rv != CKR_OK) { + p11prov_uri_free(cu); + return NULL; + } + + rv = p11prov_copy_attr(&cu->object, &uri->object); + if (rv != CKR_OK) { + p11prov_uri_free(cu); + return NULL; + } + + cu->library_version = uri->library_version; + cu->slot_id = uri->slot_id; + cu->type = uri->type; + + return cu; +} + CK_RV p11prov_uri_match_token(P11PROV_URI *uri, CK_SLOT_ID slot_id, CK_SLOT_INFO *slot, CK_TOKEN_INFO *token) { diff --git a/src/util.h b/src/util.h index 8443747a..f316c61a 100644 --- a/src/util.h +++ b/src/util.h @@ -57,10 +57,16 @@ P11PROV_URI *p11prov_parse_uri(P11PROV_CTX *ctx, const char *uri); char *p11prov_key_to_uri(P11PROV_CTX *ctx, P11PROV_OBJ *key); void p11prov_uri_free(P11PROV_URI *parsed_uri); CK_OBJECT_CLASS p11prov_uri_get_class(P11PROV_URI *uri); +void p11prov_uri_set_class(P11PROV_URI *uri, CK_OBJECT_CLASS class); CK_ATTRIBUTE p11prov_uri_get_id(P11PROV_URI *uri); +void p11prov_uri_set_id(P11PROV_URI *uri, CK_ATTRIBUTE *id); CK_ATTRIBUTE p11prov_uri_get_label(P11PROV_URI *uri); +void p11prov_uri_set_label(P11PROV_URI *uri, CK_ATTRIBUTE *label); char *p11prov_uri_get_serial(P11PROV_URI *uri); char *p11prov_uri_get_pin(P11PROV_URI *uri); +CK_SLOT_ID p11prov_uri_get_slot_id(P11PROV_URI *uri); +void p11prov_uri_set_slot_id(P11PROV_URI *uri, CK_SLOT_ID slot_id); +P11PROV_URI *p11prov_copy_uri(P11PROV_URI *uri); CK_RV p11prov_uri_match_token(P11PROV_URI *uri, CK_SLOT_ID slot_id, CK_SLOT_INFO *slot, CK_TOKEN_INFO *token); int p11prov_get_pin(P11PROV_CTX *ctx, const char *in, char **out);