Introduce certsvc_pkcs12_import_from_file_to_store_ret_list() 76/147976/3
authorPiotr Sawicki <p.sawicki2@partner.samsung.com>
Wed, 6 Sep 2017 07:22:36 +0000 (09:22 +0200)
committerPiotr Sawicki <p.sawicki2@partner.samsung.com>
Fri, 8 Sep 2017 06:50:35 +0000 (08:50 +0200)
This new function works in the same way as the
certsvc_pkcs12_import_from_file_to_store does, but additionally
it returns the list of imported certificates.

Change-Id: Id8af8229e7e5dc0eedc208ec940c1e1e5430ab8d

src/cert-svc/cpkcs12.h
src/vcore/api.cpp
src/vcore/pkcs12.cpp
src/vcore/pkcs12.h
tests/pkcs12/new_test_cases.cpp

index 101d2e3..5bd8c9f 100644 (file)
@@ -282,6 +282,39 @@ int certsvc_pkcs12_import_from_file_to_store(CertSvcInstance instance,
                CertSvcString password,
                CertSvcString alias);
 
+
+/**
+ * Import PKCS#12 bundle(with .pfx or .p12) or certificate(base64 form with .crt
+ * or .pem suffix) from file to specified store and return imported list of certificates.
+ * If password isn't needed, create CertSvcString @a password with null input on
+ * certsvc_string_new(). Refer certsvc_string_new() API description
+ *
+ * @param[in] instance   CertSvcInstance object
+ * @param[in] storeType  cert-svc store type to query
+ * @param[in] path       Path of the certificate which needs to be imported
+ * @param[in] password   Password if the file to import is password-protected which can be
+ *                       empty CertSvcString in case of not-password-protected
+ * @param[in] alias      Primary key for certificate bundle identification (can't be empty)
+ * @param[out] certList   cert list in store returned in linked list. Free by
+ *                        certsvc_pkcs12_free_certificate_list_loaded_from_store() after use
+ * @param[out] length     length of output @a certList
+ *
+ * @return #CERTSVC_SUCCESS on success, otherwise a zero or negative error value
+ *
+ * @see certsvc_instance_new()
+ * @see certsvc_instance_free()
+ * @see certsvc_string_new()
+ * @see certsvc_string_free()
+ * @see #CertStoreType
+ */
+int certsvc_pkcs12_import_from_file_to_store_ret_list(CertSvcInstance instance,
+               CertStoreType storeType,
+               CertSvcString path,
+               CertSvcString password,
+               CertSvcString alias,
+               CertSvcStoreCertList **certList,
+               size_t *length);
+
 /**
  * Delete the certificate with gname provided from cert-svc store.
  *
index 1059c72..58fc882 100644 (file)
@@ -891,10 +891,12 @@ err:
                CertStoreType storeType,
                CertSvcString path,
                CertSvcString pass,
-               CertSvcString pfxIdString)
+               CertSvcString pfxIdString,
+               CertSvcStoreCertList **certList,
+               size_t *length)
        {
                return pkcs12_import_from_file_to_store(storeType, path.privateHandler, pass.privateHandler,
-                                                                                               pfxIdString.privateHandler);
+                                                                                               pfxIdString.privateHandler, certList, length);
        }
 
        inline int pkcsGetAliasNameForCertInStore(CertStoreType storeType,
@@ -1726,7 +1728,35 @@ int certsvc_pkcs12_import_from_file_to_store(CertSvcInstance instance,
                        return CERTSVC_INVALID_STORE_TYPE;
                }
 
-               return impl(instance)->pkcsImportToStore(storeType, path, password, pfxIdString);
+               return impl(instance)->pkcsImportToStore(storeType, path, password, pfxIdString,
+                                                                                                NULL, NULL);
+       } catch (...) {
+               LogError("Exception occured from pkcsImportToStore");
+               return CERTSVC_FAIL;
+       }
+}
+
+int certsvc_pkcs12_import_from_file_to_store_ret_list(CertSvcInstance instance,
+               CertStoreType storeType,
+               CertSvcString path,
+               CertSvcString password,
+               CertSvcString pfxIdString,
+               CertSvcStoreCertList **certList,
+               size_t *length)
+{
+       try {
+               if (certList == NULL || length == NULL) {
+                       LogError("Wrong argument.");
+                       return CERTSVC_WRONG_ARGUMENT;
+               }
+
+               if (path.privateHandler == NULL || !impl(instance)->checkValidStoreType(storeType)) {
+                       LogError("Invalid input parameter.");
+                       return CERTSVC_INVALID_STORE_TYPE;
+               }
+
+               return impl(instance)->pkcsImportToStore(storeType, path, password, pfxIdString,
+                                                                                                certList, length);
        } catch (...) {
                LogError("Exception occured from pkcsImportToStore");
                return CERTSVC_FAIL;
index d2ec9d8..3e0cc70 100644 (file)
@@ -98,6 +98,73 @@ inline CertStoreType nextStore(CertStoreType type)
        }
 }
 
+CertSvcStoreCertList *createStoreListNode(const std::string &gname, const std::string &title,
+                                                                                 CertStoreType storeType)
+{
+       CertSvcStoreCertList *node = (CertSvcStoreCertList *)malloc(sizeof(CertSvcStoreCertList));
+
+       if (node == NULL)
+               return NULL;
+
+       node->gname = strdup(gname.c_str());
+       node->title = strdup(title.c_str());
+       node->status = ENABLED;
+       node->storeType = storeType;
+       node->next = NULL;
+
+       if (node->gname == NULL || node->title == NULL) {
+               free(node->gname);
+               free(node->title);
+               free(node);
+               return NULL;
+       }
+
+       return node;
+}
+
+void destroyStoreList(CertSvcStoreCertList **certList, size_t *length)
+{
+       if (certList == NULL || length == NULL) {
+               return;
+       }
+
+       CertSvcStoreCertList *list = *certList;
+
+       while (list) {
+               CertSvcStoreCertList *next = list->next;
+               free(list->gname);
+               free(list->title);
+               free(list);
+               list = next;
+       }
+
+       *length = 0;
+}
+
+void addStoreListNode(CertSvcStoreCertList **list, CertSvcStoreCertList *node)
+{
+       node->next = *list;
+       *list = node;
+}
+
+int appendStoreListNode(CertSvcStoreCertList **certList, size_t *length,
+                                                const std::string &gname, const std::string &alias,
+                                                CertStoreType storeType)
+{
+       if (certList == NULL || length == NULL)
+               return CERTSVC_SUCCESS;
+
+       CertSvcStoreCertList *node = createStoreListNode(gname, alias, storeType);
+       if (node == NULL) {
+               return CERTSVC_BAD_ALLOC;
+       }
+
+       addStoreListNode(certList, node);
+       (*length)++;
+
+       return CERTSVC_SUCCESS;
+}
+
 std::string generateGname(void)
 {
        int generator;
@@ -610,7 +677,9 @@ int insertToStore(CertStoreType storeTypes,
                                  const std::string &endCertName,
                                  const std::string &endCertBuffer,
                                  const std::vector<std::string> &certChainName,
-                                 const std::vector<std::string> &certChainBuffer)
+                                 const std::vector<std::string> &certChainBuffer,
+                                 CertSvcStoreCertList **certList,
+                                 size_t *length)
 {
        size_t ncerts = certChainName.size();
 
@@ -634,6 +703,12 @@ int insertToStore(CertStoreType storeTypes,
                        return result;
                }
 
+               int res = appendStoreListNode(certList, length, endCertName, alias, storeType);
+               if (res != CERTSVC_SUCCESS) {
+                       LogError("Failed to append store list node.");
+                       return result;
+               }
+
                for (size_t i = 0; i < ncerts; i++) {
                        if (i == ncerts - 1)
                                result = installChainCert(storeType, certChainBuffer[i], certChainName[i], endCertName,
@@ -646,6 +721,12 @@ int insertToStore(CertStoreType storeTypes,
                                LogError("Failed to install the ca certificates. result : " << result);
                                return result;
                        }
+
+                       int res = appendStoreListNode(certList, length, certChainName[i], alias, storeType);
+                       if (res != CERTSVC_SUCCESS) {
+                               LogError("Failed to append store list node.");
+                               return result;
+                       }
                }
        }
 
@@ -654,7 +735,7 @@ int insertToStore(CertStoreType storeTypes,
 }
 
 int insertToStorePEM(CertStoreType storeTypes, const std::string &path, const std::string &gname,
-                                        const std::string &alias)
+                                        const std::string &alias, CertSvcStoreCertList **certList, size_t *length)
 {
        std::string content = readFromFile(path);
 
@@ -683,6 +764,13 @@ int insertToStorePEM(CertStoreType storeTypes, const std::string &path, const st
                        return result;
                }
 
+               int res = appendStoreListNode(certList, length, gname, alias, storeType);
+               if (res != CERTSVC_SUCCESS) {
+                       rollbackStore(storeTypes, gname);
+                       LogError("Failed to append store list node.");
+                       return result;
+               }
+
                LogDebug("Success to install PEM/CRT to db store : " << storeType);
        }
 
@@ -696,7 +784,9 @@ int insertToStorePEM(CertStoreType storeTypes, const std::string &path, const st
 int pkcs12_import_from_file_to_store(CertStoreType storeTypes,
                                                                         const char *_path,
                                                                         const char *_password,
-                                                                        const char *_alias)
+                                                                        const char *_alias,
+                                                                        CertSvcStoreCertList **certList,
+                                                                        size_t *length)
 {
        int result = 0;
 
@@ -731,10 +821,12 @@ int pkcs12_import_from_file_to_store(CertStoreType storeTypes,
 
        if (strcasecmp(suffix.c_str(), ".pem") == 0 || strcasecmp(suffix.c_str(), ".crt") == 0) {
                std::string gnamePEM = generateGname();
-               result = insertToStorePEM(storeTypes, path, gnamePEM, alias);
+               result = insertToStorePEM(storeTypes, path, gnamePEM, alias, certList, length);
 
-               if (result != CERTSVC_SUCCESS)
+               if (result != CERTSVC_SUCCESS) {
+                       destroyStoreList(certList, length);
                        LogError("Failed to install PEM/CRT file to store. gname : " << gnamePEM << " result : " << result);
+               }
 
                return result;;
        }
@@ -806,10 +898,14 @@ int pkcs12_import_from_file_to_store(CertStoreType storeTypes,
                                                   endCertName,
                                                   endCertBuffer,
                                                   certChainName,
-                                                  certChainBuffer);
+                                                  certChainBuffer,
+                                                  certList,
+                                                  length);
 
-       if (result != CERTSVC_SUCCESS)
+       if (result != CERTSVC_SUCCESS) {
+               destroyStoreList(certList, length);
                rollbackStore(storeTypes, endCertName);
+       }
 
        LogDebug("Success to import pkcs12 to store");
        return result;
index 89c1809..54df9a5 100644 (file)
  * @param[in] path Path to file.
  * @param[in] password Password for opening the file.
  * @param[in] alias Logical name for certificate bundle identification (can't be empty).
+ * @param[out] certList     cert list in store returned in linked list. Free by
+ *                          certsvc_pkcs12_free_certificate_list_loaded_from_store()
+ *                          after use. Pass NULL if you don't want to return a list.
+ * @param[out] length       length of output @a certList. Pass NULL if you don't
+ *                                                      want to return a list.
  * @return CERTSVC_SUCCESS, CERTSVC_FAIL, CERTSVC_DUPLICATED_ALIAS, CERTSVC_IO_ERROR, CERTSVC_WRONG_ARGUMENT, CERTSVC_BAD_ALLOC.
  */
 int pkcs12_import_from_file_to_store(CertStoreType storeType, const char *path,
-                                                                        const char *password, const char *alias);
+                                                                        const char *password, const char *alias, CertSvcStoreCertList **certList,
+                                                                        size_t *length);
 
 /**
  * TO check if the p12/pfx file is protected by password or not.
index 69ac7b7..6004125 100644 (file)
@@ -952,3 +952,105 @@ RUNNER_TEST(CERTSVC_PKCS12_1028_certsvc_set_cert_to_disabled_and_get_status_for_
        FREE_INSTANCE
 }
 
+static void remove_certificates_from_store(CertSvcInstance &instance, CertStoreType storeType)
+{
+       int result;
+       size_t length = 0;
+       CertSvcStoreCertList *certList = NULL;
+       CertSvcStoreCertList *certListIter = NULL;
+
+       result = certsvc_pkcs12_get_certificate_list_from_store(instance, storeType, DISABLED, &certList,
+                                                                                                                       &length);
+       RUNNER_ASSERT_MSG(result == CERTSVC_SUCCESS, "Getting certificate list from system store failed");
+
+       certListIter = certList;
+
+       while (certListIter) {
+               CertSvcString Gname = wrapper_certsvc_string_new(certListIter->gname);
+
+               result = certsvc_pkcs12_delete_certificate_from_store(instance, storeType, Gname);
+
+               certsvc_string_free(Gname);
+               certListIter = certListIter->next;
+       }
+}
+
+size_t count_certificates_on_list(CertSvcStoreCertList *certList)
+{
+       size_t counter = 0;
+
+       while (certList) {
+               counter++;
+               certList = certList->next;
+       }
+
+       return counter;
+}
+
+RUNNER_TEST(CERTSVC_PKCS12_1029_install_certs_from_p12_file_using_wifi_store_ret_list)
+{
+       int result;
+       CertSvcStoreCertList *certList = NULL;
+       size_t length = 0;
+
+       CREATE_INSTANCE
+
+       remove_certificates_from_store(instance, WIFI_STORE);
+
+       CertSvcString Alias = wrapper_certsvc_string_new("P12-WifiUser-wifi-store");
+       CertSvcString Path = wrapper_certsvc_string_new(TestData::UserP12WithPassPath.c_str());
+       CertSvcString Pass = wrapper_certsvc_string_new(TestData::UserP12Pass.c_str());
+
+       result = certsvc_pkcs12_import_from_file_to_store_ret_list(instance, WIFI_STORE, Path, Pass, Alias,
+                                                                                                                          &certList, &length);
+       RUNNER_ASSERT_MSG(result == CERTSVC_SUCCESS, "Importing P12 file to WIFI store failed.");
+       RUNNER_ASSERT_MSG(length == 3, "There should be 3 imported certificates");
+       size_t count = count_certificates_on_list(certList);
+       RUNNER_ASSERT_MSG(length == count, "The length is different than number of elements on the list");
+
+       result = certsvc_pkcs12_free_certificate_list_loaded_from_store(instance, &certList);
+       RUNNER_ASSERT_MSG(result == CERTSVC_SUCCESS, "Freeing certificate list from system store failed");
+
+       remove_certificates_from_store(instance, WIFI_STORE);
+
+       certsvc_string_free(Alias);
+       certsvc_string_free(Path);
+       certsvc_string_free(Pass);
+
+       FREE_INSTANCE
+}
+
+RUNNER_TEST(CERTSVC_PKCS12_1030_install_certs_from_pem_file_using_wifi_store_ret_list)
+{
+       int result;
+       CertSvcStoreCertList *certList = NULL;
+       size_t length = 0;
+
+       CREATE_INSTANCE
+
+       remove_certificates_from_store(instance, WIFI_STORE);
+
+       CertSvcString PEMPath = wrapper_certsvc_string_new(TestData::ServerCertPemPath.c_str());
+       CertSvcString PEMPass = wrapper_certsvc_string_new(NULL);
+       // alias has been taken from PEM file
+       CertSvcString PEMAlias = wrapper_certsvc_string_new("PEM-WifiUser-wifi-store");
+
+       result = certsvc_pkcs12_import_from_file_to_store_ret_list(instance, WIFI_STORE, PEMPath, PEMPass, PEMAlias,
+                                                                                                                          &certList, &length);
+       RUNNER_ASSERT_MSG(result == CERTSVC_SUCCESS, "Importing PEM file to WIFI store failed.");
+       RUNNER_ASSERT_MSG(length == 1, "There should be 3 imported certificates");
+       size_t count = count_certificates_on_list(certList);
+       RUNNER_ASSERT_MSG(length == count, "The length is different than number of elements on the list");
+
+       result = certsvc_pkcs12_free_certificate_list_loaded_from_store(instance, &certList);
+       RUNNER_ASSERT_MSG(result == CERTSVC_SUCCESS, "Freeing certificate list from system store failed");
+
+       remove_certificates_from_store(instance, WIFI_STORE);
+
+       certsvc_string_free(PEMAlias);
+       certsvc_string_free(PEMPath);
+       certsvc_string_free(PEMPass);
+
+       FREE_INSTANCE
+}
+