nss-shared-helper/db.c
changeset 0 262e1fb001a8
child 1 98d01e6fd2bd
equal deleted inserted replaced
-1:000000000000 0:262e1fb001a8
       
     1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       
     2 
       
     3 /* db.c - Helper funcs for shared NSS database
       
     4  *
       
     5  * Copyright (C) 2008 Hans Petter Jansson
       
     6  *               2008-2010 Wolfgang Rosenauer
       
     7  *
       
     8  * This library is free software; you can redistribute it and/or
       
     9  * modify it under the terms of the GNU Lesser General Public
       
    10  * License as published by the Free Software Foundation; either
       
    11  * version 2 of the License, or (at your option) any later version.
       
    12  *
       
    13  * This library is distributed in the hope that it will be useful,
       
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
       
    16  * Lesser General Public License for more details.
       
    17  *
       
    18  * You should have received a copy of the GNU Lesser General Public
       
    19  * License along with this library; if not, write to the
       
    20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    21  * Boston, MA 02111-1307, USA.
       
    22  *
       
    23  * Authors: Hans Petter Jansson <hpj@copyleft.no> 
       
    24  *          Wolfgang Rosenauer <wr@rosenauer.org> */
       
    25 
       
    26 #include <sys/types.h>
       
    27 #include <sys/stat.h>
       
    28 #include <unistd.h>
       
    29 #include <string.h>
       
    30 #include <stdlib.h>
       
    31 #include <stdio.h>
       
    32 #include <fcntl.h>
       
    33 
       
    34 #include <nspr.h>
       
    35 #include <nss.h>
       
    36 #include <pk11priv.h>
       
    37 #include <pk11pub.h>
       
    38 
       
    39 #include "nss-shared-helper.h"
       
    40 
       
    41 #define DEFAULT_RELATIVE_PATH ".pki/nssdb"
       
    42 #define DEFAULT_PATH          "/etc/pki/nssdb"
       
    43 
       
    44 typedef struct {
       
    45   enum {
       
    46     PW_NONE = 0,
       
    47     PW_FROMFILE = 1,
       
    48     PW_PLAINTEXT = 2,
       
    49     PW_EXTERNAL = 3
       
    50   } source;
       
    51   char *data;
       
    52 } secuPWData;
       
    53 
       
    54 char *
       
    55 nsshelp_get_user_db_path (void)
       
    56 {
       
    57   const char  *env;
       
    58   char        *path;
       
    59   struct stat  sbuf;
       
    60   int          result;
       
    61 
       
    62   env = getenv ("NSS_SHARED_DB_PATH");
       
    63   
       
    64   if (env && *env) {
       
    65     path = strdup (env);
       
    66   } else {
       
    67     /*
       
    68     env = getenv ("HOME");
       
    69     if (!env || !*env)
       
    70     {
       
    71       fprintf (stderr, "*** nss-shared-helper: Could not determine shared NSS DB path!\n");
       
    72       return NULL;
       
    73     }
       
    74 
       
    75     path = malloc (strlen (env) + 1 + strlen (DEFAULT_RELATIVE_PATH) + 1);
       
    76     strcpy (path, env);
       
    77     strcat (path, "/");
       
    78     strcat (path, DEFAULT_RELATIVE_PATH);
       
    79     */
       
    80     path = strdup(DEFAULT_PATH);
       
    81   }
       
    82 
       
    83   /* Create path if it doesn't exist */
       
    84 
       
    85   result = stat (path, &sbuf);
       
    86 
       
    87   if (result != 0)
       
    88   {
       
    89     const char *p0 = path;
       
    90     const char *p1;
       
    91 
       
    92     while (*p0 == '/')
       
    93       p0++;
       
    94 
       
    95     /* Try to create it with restrictive permissions */
       
    96 
       
    97     do
       
    98     {
       
    99       p1 = strchr (p0, '/');
       
   100 
       
   101       if (p1 == NULL)
       
   102         p1 = p0 + strlen (p0);
       
   103 
       
   104       if (p1 != p0)
       
   105       {
       
   106         char *path_part = strdup (path);
       
   107 
       
   108         *(path_part + (p1 - path)) = '\0';
       
   109         mkdir (path_part, 0700);
       
   110       }
       
   111 
       
   112       p0 = p1 + 1;
       
   113     }
       
   114     while (*p1 != '\0');
       
   115 
       
   116     result = stat (path, &sbuf);
       
   117   }
       
   118 
       
   119   if (result == 0 && S_ISDIR (sbuf.st_mode))
       
   120     return path;
       
   121 
       
   122   free (path);
       
   123   return NULL;
       
   124 }
       
   125 
       
   126 SECStatus
       
   127 nsshelp_open_db (const char *app_id, const char *old_path, PRUint32 flags)
       
   128 {
       
   129   char *new_path;
       
   130   char *sdb_path;
       
   131   struct stat sbuf;
       
   132   int result;
       
   133   SECStatus rv;
       
   134   PK11SlotInfo *slot;
       
   135   secuPWData pwdata = { PW_NONE, 0 };
       
   136 
       
   137   if (!getenv ("NSS_USE_SHARED_DB"))
       
   138   {
       
   139     fprintf (stderr, "*** nss-shared-helper: Shared database disabled (set NSS_USE_SHARED_DB to enable).\n");
       
   140 
       
   141     rv = NSS_Initialize (old_path,
       
   142                          "", "", "secmod.db",
       
   143                          flags);
       
   144     return rv;
       
   145   }
       
   146 
       
   147   new_path = nsshelp_get_user_db_path ();
       
   148   if (!new_path)
       
   149     return SECFailure;
       
   150 
       
   151   fprintf (stderr, "*** nss-shared-helper: Using shared location %s\n", new_path);
       
   152   sdb_path = PR_smprintf ("sql:%s", new_path);
       
   153 
       
   154   /* simple update (application does not care about the
       
   155    * underlying state machine). */
       
   156 
       
   157   /* STEP 1: Signal that update/merge may be needed  */
       
   158 
       
   159   rv = NSS_InitWithMerge (sdb_path,
       
   160                           "", "", "secmod.db",
       
   161                           old_path, "", "",
       
   162                           app_id, app_id /* prompt name */,
       
   163                           flags);
       
   164 
       
   165   if (rv == SECFailure)
       
   166   {
       
   167     /* Don't migrate anything */
       
   168 
       
   169     fprintf (stderr, "*** nss-shared-helper: NSS_InitWithMerge failed. Trying NSS_Initialize.\n");
       
   170 
       
   171     rv = NSS_Initialize (sdb_path,
       
   172                          "", "", "secmod.db",
       
   173                          flags);
       
   174     PR_smprintf_free (sdb_path);
       
   175 
       
   176     if (rv == SECFailure)
       
   177       fprintf (stderr, "*** nss-shared-helper: NSS_Initialize failed.\n");
       
   178 
       
   179     return rv;
       
   180   }
       
   181 
       
   182   slot = PK11_GetInternalKeySlot();
       
   183 
       
   184   /* Step 2: Determine if update/merge is needed. */
       
   185 
       
   186   if (PK11_IsRemovable(slot))
       
   187   {
       
   188     /* need to update/Merge the database */
       
   189 
       
   190     /* Step 3: Authenticate to the token */
       
   191 
       
   192     rv = PK11_Authenticate(slot, PR_FALSE, &pwdata);
       
   193     if (rv == SECSuccess)
       
   194     {
       
   195       /* just update the state machine */
       
   196 
       
   197       /* Step 4: */
       
   198       PK11_IsLoggedIn(slot, &pwdata);
       
   199       /* Step 5: */
       
   200       PK11_IsPresent(slot);
       
   201 
       
   202       /* Step 6: */
       
   203       rv = PK11_Authenticate(slot, PR_FALSE, &pwdata);
       
   204       if (rv != SECSuccess)
       
   205       {
       
   206         fprintf (stderr, "*** nss-shared-helper: Second auth call failed: %u.\n",
       
   207                  PORT_GetError ());
       
   208       }
       
   209     }
       
   210     else
       
   211     {
       
   212       fprintf (stderr, "*** nss-shared-helper: First auth call failed: %u.\n",
       
   213                PORT_GetError ());
       
   214     }
       
   215   }
       
   216 
       
   217   /* Step 7: NSS is initialized and (possibly) merged, start using it */
       
   218 
       
   219   PR_smprintf_free (sdb_path);
       
   220   return SECSuccess;
       
   221 }