"Fossies" - the Fresh Open Source Software Archive

Member "opensc-0.22.0/src/tools/pkcs11-register.c" (10 Aug 2021, 9720 Bytes) of package /linux/privat/opensc-0.22.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "pkcs11-register.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 0.21.0_vs_0.22.0.

    1 /*
    2  * Copyright (C) 2019 Frank Morgner <frankmorgner@gmail.com>
    3  *
    4  * This file is part of OpenSC.
    5  *
    6  * This library is free software; you can redistribute it and/or
    7  * modify it under the terms of the GNU Lesser General Public
    8  * License as published by the Free Software Foundation; either
    9  * version 2.1 of the License, or (at your option) any later version.
   10  *
   11  * This library is distributed in the hope that it will be useful,
   12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   14  * Lesser General Public License for more details.
   15  *
   16  * You should have received a copy of the GNU Lesser General Public
   17  * License along with this library; if not, write to the Free Software
   18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   19  */
   20 #ifdef HAVE_CONFIG_H
   21 #include "config.h"
   22 #endif
   23 
   24 #include "fread_to_eof.h"
   25 #include "pkcs11-register-cmdline.h"
   26 #include <limits.h>
   27 #include <string.h>
   28 #include <stdlib.h>
   29 
   30 #ifdef _WIN32
   31 #include <windows.h>
   32 const char path_sep = '\\';
   33 #else
   34 const char path_sep = '/';
   35 #endif
   36 
   37 const char *default_pkcs11_provider = DEFAULT_PKCS11_PROVIDER;
   38 const char *default_onepin_pkcs11_provider = DEFAULT_ONEPIN_PKCS11_PROVIDER;
   39 
   40 int
   41 get_profiles_ini(const char *home, const char *basedir, char **profiles_ini)
   42 {
   43     size_t profiles_ini_len = 0;
   44     char profiles_ini_path[PATH_MAX];
   45     if (home && basedir
   46             && 0 <= snprintf(profiles_ini_path, sizeof profiles_ini_path,
   47                 "%s%c%s%c%s", home, path_sep, basedir, path_sep, "profiles.ini")
   48             && fread_to_eof(profiles_ini_path,
   49                 (unsigned char **) profiles_ini, &profiles_ini_len)) {
   50         char *p = realloc(*profiles_ini, profiles_ini_len+1);
   51         if (p) {
   52             p[profiles_ini_len] = '\0';
   53             *profiles_ini = p;
   54             return 1;
   55         }
   56     }
   57     return 0;
   58 }
   59 
   60 const char *
   61 get_next_profile_path(const char **profiles_ini, const char *home, const char *basedir)
   62 {
   63     static char profile_path[PATH_MAX];
   64 
   65     if (!home || !profiles_ini)
   66         return NULL;
   67 
   68     while (*profiles_ini) {
   69         const char *this_profile = strstr(*profiles_ini, "[");
   70         if (!this_profile) {
   71             return NULL;
   72         }
   73 
   74         const char *next_profile = strstr(this_profile + 1, "[");
   75         const char *is_relative = strstr(this_profile, "IsRelative=1");
   76         const char *path = strstr(this_profile, "Path=");
   77 
   78         /* advance profile_ini for the next iteration */
   79         if (next_profile) {
   80             *profiles_ini = next_profile;
   81             
   82             if (next_profile < path) {
   83                 /* path belongs to the next profile */
   84                 path = NULL;
   85             }
   86             if (next_profile < is_relative) {
   87                 /* IsRelative belongs to the next profile */
   88                 is_relative = NULL;
   89             }
   90         } else {
   91             *profiles_ini = NULL;
   92         }
   93 
   94         if (!path)
   95             continue;
   96 
   97         /* build the path to the profile */
   98         char *p = profile_path;
   99         size_t p_len = sizeof profile_path;
  100         if (is_relative) {
  101             size_t l = strlen(home) + sizeof path_sep + strlen(basedir) + sizeof path_sep;
  102             if (0 > snprintf(p, p_len, "%s%c%s%c", home, path_sep, basedir, path_sep))
  103                 continue;
  104             p_len -= l;
  105             p += l;
  106         }
  107         /* adjust format to respect the maximum length of profile_path */
  108         char format[32];
  109         if (0 > snprintf(format, sizeof(format), "Path=%%%ds", (int)(p_len-1))
  110                 || 1 != sscanf(path, format, p))
  111             continue;
  112 
  113         return profile_path;
  114     }
  115 
  116     return NULL;
  117 }
  118 
  119 void
  120 add_module_pkcs11_txt(const char *profile_dir,
  121         const char *module_path, const char *module_name, const char *exclude_module_path)
  122 {
  123     char pkcs11_txt_path[PATH_MAX];
  124     char *pkcs11_txt = NULL;
  125     size_t pkcs11_txt_len = 0;
  126     unsigned char *txt = NULL;
  127 
  128     if (!profile_dir
  129             || snprintf(pkcs11_txt_path, sizeof pkcs11_txt_path,
  130                 "%s%c%s", profile_dir, path_sep, "pkcs11.txt") < 0
  131             || !fread_to_eof(pkcs11_txt_path, &txt, &pkcs11_txt_len)) {
  132         goto err;
  133     }
  134     pkcs11_txt = (char *)txt;
  135     char *p = realloc(pkcs11_txt, pkcs11_txt_len+1);
  136     if (!p)
  137         goto err;
  138     p[pkcs11_txt_len] = '\0';
  139     pkcs11_txt = p;
  140 
  141     if (!strstr(pkcs11_txt, module_path)
  142             && (!exclude_module_path || !strstr(pkcs11_txt, exclude_module_path))) {
  143         /* module is not yet present */
  144         FILE *f = fopen(pkcs11_txt_path, "a");
  145         if (f) {
  146             if (fprintf(f,
  147                     "library=%s\n"
  148                     "name=%s\n"
  149                     "\n", module_path, module_name) >= 0) {
  150                 printf("Added %s to %s\n", module_name, pkcs11_txt_path);
  151             }
  152             fclose(f);
  153         }
  154     }
  155 err:
  156     free(pkcs11_txt);
  157 }
  158 
  159 struct location {
  160     const char *var;
  161     const char *dir;
  162 };
  163 
  164 void
  165 add_module_mozilla(const struct location *locations, size_t locations_len,
  166         const char *module_path, const char *module_name, const char *exclude_module_path)
  167 {
  168     size_t i;
  169 
  170     for (i = 0; i < locations_len; i++) {
  171         char *profiles_ini = NULL;
  172         const char *home = getenv(locations[i].var);
  173         if (!home)
  174             continue;
  175 
  176         if (get_profiles_ini(home, locations[i].dir, &profiles_ini)) {
  177             const char *p = profiles_ini;
  178 
  179             while (1) {
  180                 const char *profile_path = get_next_profile_path(&p, home, locations[i].dir);
  181                 if (!profile_path)
  182                     break;
  183                 add_module_pkcs11_txt(profile_path, module_path, module_name, exclude_module_path);
  184             }
  185         }
  186         free(profiles_ini);
  187     }
  188 }
  189 
  190 #include "pkcs11/pkcs11.h"
  191 #include "common/libpkcs11.h"
  192 
  193 const char *
  194 get_module_name(const char *module_path)
  195 {
  196     const char *name = NULL;
  197     CK_FUNCTION_LIST_PTR p11 = NULL;
  198     void *module = C_LoadModule(module_path, &p11);
  199     if (module) {
  200         CK_INFO info;
  201         if (CKR_OK == p11->C_Initialize(NULL)
  202                 && CKR_OK == p11->C_GetInfo(&info)) {
  203             static char module_name[32+sizeof " (255.255)"];
  204             int libraryDescription_len = 32;
  205 
  206             while (libraryDescription_len > 0
  207                     && info.libraryDescription[libraryDescription_len-1] == ' ')
  208                 libraryDescription_len--;
  209 
  210             snprintf(module_name, sizeof module_name,
  211                     "%.*s (%d.%d)",
  212                     libraryDescription_len, info.libraryDescription,
  213                     info.libraryVersion.major, info.libraryVersion.minor);
  214 
  215             name = module_name;
  216         }
  217         p11->C_Finalize(NULL);
  218         C_UnloadModule(module);
  219     }
  220     return name;
  221 }
  222 
  223 void
  224 add_module_firefox(const char *module_path, const char *module_name, const char *exclude_module_path)
  225 {
  226     struct location locations[] = {
  227 #if   defined(__APPLE__)
  228         {"HOME", "Library/Application Support/Firefox"},
  229         {"HOME", "Library/Mozilla/Firefox"},
  230 #elif defined(_WIN32)
  231         {"APPDATA", "Mozilla\\Firefox"},
  232 #else
  233         {"HOME", ".mozilla/firefox"},
  234 #endif
  235     };
  236 
  237     if (0 == strcmp(module_path, default_pkcs11_provider)) {
  238         module_path = default_onepin_pkcs11_provider;
  239         exclude_module_path = default_pkcs11_provider;
  240     }
  241 
  242     add_module_mozilla(locations, sizeof locations/sizeof *locations,
  243             module_path, module_name, exclude_module_path);
  244 }
  245 
  246 void
  247 add_module_thunderbird(const char *module_path, const char *module_name, const char *exclude_module_path)
  248 {
  249     struct location locations[] = {
  250 #if   defined(__APPLE__)
  251         {"HOME", "Library/Application Support/Thunderbird"},
  252         {"HOME", "Library/Mozilla/Thunderbird"},
  253 #elif defined(_WIN32)
  254         {"APPDATA", "Mozilla\\Thunderbird"},
  255 #else
  256         {"HOME", ".thunderbird"},
  257         {"HOME", ".mozilla-thunderbird"},
  258 #endif
  259     };
  260 
  261     add_module_mozilla(locations, sizeof locations/sizeof *locations,
  262             module_path, module_name, exclude_module_path);
  263 }
  264 
  265 void
  266 add_module_seamonkey(const char *module_path, const char *module_name, const char *exclude_module_path)
  267 {
  268     struct location locations[] = {
  269 #if   defined(__APPLE__)
  270         {"HOME", "Library/Application Support/SeaMonkey"},
  271         {"HOME", "Library/Mozilla/SeaMonkey"},
  272 #elif defined(_WIN32)
  273         {"APPDATA", "Mozilla\\SeaMonkey"},
  274 #else
  275         {"HOME", ".mozilla/seamonkey"},
  276 #endif
  277     };
  278 
  279     add_module_mozilla(locations, sizeof locations/sizeof *locations,
  280             module_path, module_name, exclude_module_path);
  281 }
  282 
  283 void
  284 add_module_chrome(const char *module_path, const char *module_name, const char *exclude_module_path)
  285 {
  286 #if defined(__APPLE__) || defined(_WIN32)
  287     /* OS specific framework will be used by Chrome instead of PKCS#11 */
  288 #else
  289     char profile_path[PATH_MAX];
  290     const char *home = getenv("HOME");
  291 
  292     if (0 == strcmp(module_path, default_pkcs11_provider)) {
  293         module_path = default_onepin_pkcs11_provider;
  294         exclude_module_path = default_pkcs11_provider;
  295     }
  296 
  297     if (home && 0 <= snprintf(profile_path, sizeof profile_path,
  298                 "%s%c%s", home, path_sep, ".pki/nssdb")) {
  299         add_module_pkcs11_txt(profile_path, module_path, module_name, exclude_module_path);
  300     }
  301 #endif
  302 }
  303 
  304 #define expand(path, expanded, len) \
  305     len = ExpandEnvironmentStringsA(path, \
  306             expanded, sizeof expanded); \
  307     if (0 < len && len < sizeof expanded) \
  308         path = expanded;
  309 
  310 int
  311 main(int argc, char **argv)
  312 {
  313     struct gengetopt_args_info cmdline;
  314     const char *exclude_module_path = NULL;
  315 
  316     if (cmdline_parser(argc, argv, &cmdline) != 0)
  317         return 1;
  318 
  319     const char *module_path = cmdline.module_arg;
  320     if (!cmdline.module_given) {
  321         module_path = default_pkcs11_provider;
  322         exclude_module_path = default_onepin_pkcs11_provider;
  323     }
  324 #ifdef _WIN32
  325     DWORD expanded_len;
  326     char module_path_expanded[PATH_MAX], default_expanded[PATH_MAX], onepin_expanded[PATH_MAX];
  327     expand(module_path, module_path_expanded, expanded_len);
  328     expand(default_pkcs11_provider, default_expanded, expanded_len);
  329     expand(default_onepin_pkcs11_provider, onepin_expanded, expanded_len);
  330 #endif
  331 
  332     const char *module_name = get_module_name(module_path);
  333     if (!module_name) {
  334         fprintf(stderr, "Could not load initialize %s\n", module_path);
  335         cmdline_parser_free (&cmdline);
  336         return 1;
  337     }
  338 
  339     if (!cmdline.skip_chrome_flag)
  340         add_module_chrome(module_path, module_name, exclude_module_path);
  341     if (!cmdline.skip_firefox_flag)
  342         add_module_firefox(module_path, module_name, exclude_module_path);
  343     if (!cmdline.skip_thunderbird_flag)
  344         add_module_thunderbird(module_path, module_name, exclude_module_path);
  345     if (!cmdline.skip_seamonkey_flag)
  346         add_module_seamonkey(module_path, module_name, exclude_module_path);
  347 
  348     cmdline_parser_free (&cmdline);
  349 
  350     return 0;
  351 }