LCOV - code coverage report
Current view: top level - p11_child - p11_child_nss.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 199 312 63.8 %
Date: 2015-10-19 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /*
       2             :     SSSD
       3             : 
       4             :     Helper child to commmunicate with SmartCard via NSS
       5             : 
       6             :     Authors:
       7             :         Sumit Bose <sbose@redhat.com>
       8             : 
       9             :     Copyright (C) 2015 Red Hat
      10             : 
      11             :     This program is free software; you can redistribute it and/or modify
      12             :     it under the terms of the GNU General Public License as published by
      13             :     the Free Software Foundation; either version 3 of the License, or
      14             :     (at your option) any later version.
      15             : 
      16             :     This program is distributed in the hope that it will be useful,
      17             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      18             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19             :     GNU General Public License for more details.
      20             : 
      21             :     You should have received a copy of the GNU General Public License
      22             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      23             : */
      24             : 
      25             : #include <unistd.h>
      26             : #include <stdio.h>
      27             : #include <stdlib.h>
      28             : #include <string.h>
      29             : #include <popt.h>
      30             : 
      31             : #include "util/util.h"
      32             : 
      33             : #include <nss.h>
      34             : #include <base64.h>
      35             : #include <cryptohi.h>
      36             : #include <secmod.h>
      37             : #include <cert.h>
      38             : #include <keyhi.h>
      39             : #include <pk11pub.h>
      40             : #include <prerror.h>
      41             : 
      42             : #include "util/child_common.h"
      43             : #include "providers/dp_backend.h"
      44             : #include "util/crypto/sss_crypto.h"
      45             : 
      46             : enum op_mode {
      47             :     OP_NONE,
      48             :     OP_AUTH,
      49             :     OP_PREAUTH
      50             : };
      51             : 
      52             : enum pin_mode {
      53             :     PIN_NONE,
      54             :     PIN_STDIN,
      55             :     PIN_KEYPAD
      56             : };
      57             : 
      58           1 : static char *password_passthrough(PK11SlotInfo *slot, PRBool retry, void *arg)
      59             : {
      60             :   /* give up if 1) no password was supplied, or 2) the password has already
      61             :    * been rejected once by this token. */
      62           1 :   if (retry || (arg == NULL)) {
      63           0 :     return NULL;
      64             :   }
      65           1 :   return PL_strdup((char *)arg);
      66             : }
      67             : 
      68             : 
      69             : 
      70           8 : int do_work(TALLOC_CTX *mem_ctx, const char *nss_db, const char *slot_name_in,
      71             :             enum op_mode mode, const char *pin, char **cert,
      72             :             char **token_name_out)
      73             : {
      74             :     int ret;
      75             :     SECStatus rv;
      76             :     NSSInitContext *nss_ctx;
      77             :     SECMODModuleList *mod_list;
      78             :     SECMODModuleList *mod_list_item;
      79             :     const char *slot_name;
      80             :     const char *token_name;
      81           8 :     uint32_t flags = NSS_INIT_READONLY
      82             :                                    | NSS_INIT_FORCEOPEN
      83             :                                    | NSS_INIT_NOROOTINIT
      84             :                                    | NSS_INIT_OPTIMIZESPACE
      85             :                                    | NSS_INIT_PK11RELOAD;
      86           8 :     NSSInitParameters parameters = { 0 };
      87           8 :     parameters.length =  sizeof (parameters);
      88           8 :     PK11SlotInfo *slot = NULL;
      89             :     CK_SLOT_ID slot_id;
      90             :     SECMODModuleID module_id;
      91           8 :     CERTCertList *cert_list = NULL;
      92             :     CERTCertListNode *cert_list_node;
      93           8 :     const PK11DefaultArrayEntry friendly_attr = { "Publicly-readable certs",
      94             :                                                   SECMOD_FRIENDLY_FLAG,
      95             :                                                   CKM_INVALID_MECHANISM };
      96             :     CERTCertDBHandle *handle;
      97             :     unsigned char random_value[128];
      98             :     SECKEYPrivateKey *priv_key;
      99             :     SECOidTag algtag;
     100           8 :     SECItem signed_random_value = {0};
     101             :     SECKEYPublicKey *pub_key;
     102           8 :     CERTCertificate *found_cert = NULL;
     103           8 :     PK11SlotList *list = NULL;
     104             :     PK11SlotListElement *le;
     105             : 
     106             : 
     107           8 :     nss_ctx = NSS_InitContext(nss_db, "", "", SECMOD_DB, &parameters, flags);
     108           8 :     if (nss_ctx == NULL) {
     109           0 :         DEBUG(SSSDBG_OP_FAILURE, "NSS_InitContext failed [%d].\n",
     110             :                                  PR_GetError());
     111           0 :         return EIO;
     112             :     }
     113             : 
     114           8 :     PK11_SetPasswordFunc(password_passthrough);
     115             : 
     116           8 :     DEBUG(SSSDBG_TRACE_ALL, "Default Module List:\n");
     117           8 :     mod_list = SECMOD_GetDefaultModuleList();
     118          24 :     for (mod_list_item = mod_list; mod_list_item != NULL;
     119           8 :                                    mod_list_item = mod_list_item->next) {
     120           8 :         DEBUG(SSSDBG_TRACE_ALL, "common name: [%s].\n",
     121             :                                 mod_list_item->module->commonName);
     122           8 :         DEBUG(SSSDBG_TRACE_ALL, "dll name: [%s].\n",
     123             :                                 mod_list_item->module->dllName);
     124             :     }
     125             : 
     126           8 :     DEBUG(SSSDBG_TRACE_ALL, "Dead Module List:\n");
     127           8 :     mod_list = SECMOD_GetDeadModuleList();
     128          16 :     for (mod_list_item = mod_list; mod_list_item != NULL;
     129           0 :                                    mod_list_item = mod_list_item->next) {
     130           0 :         DEBUG(SSSDBG_TRACE_ALL, "common name: [%s].\n",
     131             :                                 mod_list_item->module->commonName);
     132           0 :         DEBUG(SSSDBG_TRACE_ALL, "dll name: [%s].\n",
     133             :                                 mod_list_item->module->dllName);
     134             :     }
     135             : 
     136           8 :     DEBUG(SSSDBG_TRACE_ALL, "DB Module List:\n");
     137           8 :     mod_list = SECMOD_GetDBModuleList();
     138          24 :     for (mod_list_item = mod_list; mod_list_item != NULL;
     139           8 :                                    mod_list_item = mod_list_item->next) {
     140           8 :         DEBUG(SSSDBG_TRACE_ALL, "common name: [%s].\n",
     141             :                                 mod_list_item->module->commonName);
     142           8 :         DEBUG(SSSDBG_TRACE_ALL, "dll name: [%s].\n",
     143             :                                 mod_list_item->module->dllName);
     144             :     }
     145             : 
     146           8 :     if (slot_name_in != NULL) {
     147           0 :         slot = PK11_FindSlotByName(slot_name_in);
     148           0 :         if (slot == NULL) {
     149           0 :             DEBUG(SSSDBG_OP_FAILURE, "PK11_FindSlotByName failed for [%s]: [%d].\n",
     150             :                                      slot_name_in, PR_GetError());
     151           0 :             return EIO;
     152             :         }
     153             :     } else {
     154             : 
     155           8 :         list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_TRUE,
     156             :                                  NULL);
     157           8 :         if (list == NULL) {
     158           0 :             DEBUG(SSSDBG_OP_FAILURE, "PK11_GetAllTokens failed.\n");
     159           0 :             return EIO;
     160             :         }
     161             : 
     162          24 :         for (le = list->head; le; le = le->next) {
     163             :             CK_SLOT_INFO slInfo;
     164             : 
     165          22 :             slInfo.flags = 0;
     166          22 :             rv = PK11_GetSlotInfo(le->slot, &slInfo);
     167          22 :             DEBUG(SSSDBG_TRACE_ALL,
     168             :                   "Description [%s] Manufacturer [%s] flags [%lu].\n",
     169             :                   slInfo.slotDescription, slInfo.manufacturerID, slInfo.flags);
     170          22 :             if (rv == SECSuccess && (slInfo.flags & CKF_REMOVABLE_DEVICE)) {
     171           6 :                 slot = PK11_ReferenceSlot(le->slot);
     172           6 :                 break;
     173             :            }
     174             :         }
     175           8 :         PK11_FreeSlotList(list);
     176           8 :         if (slot == NULL) {
     177           2 :             DEBUG(SSSDBG_OP_FAILURE, "No removable slots found.\n");
     178           2 :             return EIO;
     179             :         }
     180             :     }
     181             : 
     182             : 
     183           6 :     slot_id = PK11_GetSlotID(slot);
     184           6 :     module_id = PK11_GetModuleID(slot);
     185           6 :     slot_name = PK11_GetSlotName(slot);
     186           6 :     token_name = PK11_GetTokenName(slot);
     187           6 :     DEBUG(SSSDBG_TRACE_ALL, "Found [%s] in slot [%s][%d] of module [%d].\n",
     188             :           token_name, slot_name, (int) slot_id, (int) module_id);
     189             : 
     190           6 :     if (PK11_IsFriendly(slot)) {
     191           6 :         DEBUG(SSSDBG_TRACE_ALL, "Token is friendly.\n");
     192             :     } else {
     193           0 :         DEBUG(SSSDBG_TRACE_ALL,
     194             :               "Token is NOT friendly.\n");
     195           0 :         if (mode == OP_PREAUTH) {
     196           0 :             DEBUG(SSSDBG_TRACE_ALL, "Trying to switch to friendly to read certificate.\n");
     197           0 :             rv = PK11_UpdateSlotAttribute(slot, &friendly_attr, PR_TRUE);
     198           0 :             if (rv != SECSuccess) {
     199           0 :                 DEBUG(SSSDBG_OP_FAILURE,
     200             :                       "PK11_UpdateSlotAttribute failed, continue.\n");
     201             :             }
     202             :         }
     203             :     }
     204             : 
     205             :     /* TODO: check  PK11_ProtectedAuthenticationPath() and return the result */
     206           6 :     if (mode == OP_AUTH || PK11_NeedLogin(slot)) {
     207           6 :         DEBUG(SSSDBG_TRACE_ALL, "Login required.\n");
     208          12 :         if (pin != NULL) {
     209           1 :             rv = PK11_Authenticate(slot, PR_FALSE, discard_const(pin));
     210           1 :             if (rv !=  SECSuccess) {
     211           0 :                 DEBUG(SSSDBG_OP_FAILURE, "PK11_Authenticate failed: [%d].\n",
     212             :                                          PR_GetError());
     213           0 :                 return EIO;
     214             :             }
     215             :         } else {
     216           5 :             DEBUG(SSSDBG_CRIT_FAILURE,
     217             :                   "Login required but no pin available, continue.\n");
     218             :         }
     219             :     } else {
     220           0 :         DEBUG(SSSDBG_TRACE_ALL, "Login NOT required.\n");
     221             :     }
     222             : 
     223           6 :     cert_list = PK11_ListCertsInSlot(slot);
     224           6 :     if (cert_list == NULL) {
     225           0 :         DEBUG(SSSDBG_OP_FAILURE, "PK11_ListCertsInSlot failed: [%d].\n",
     226             :                                  PR_GetError());
     227           0 :         return EIO;
     228             :     }
     229             : 
     230          24 :     for (cert_list_node = CERT_LIST_HEAD(cert_list);
     231          18 :                 !CERT_LIST_END(cert_list_node, cert_list);
     232          12 :                 cert_list_node = CERT_LIST_NEXT(cert_list_node)) {
     233          12 :         if (cert_list_node->cert) {
     234          12 :             DEBUG(SSSDBG_TRACE_ALL, "found cert[%s][%s]\n",
     235             :                              cert_list_node->cert->nickname,
     236             :                              cert_list_node->cert->subjectName);
     237             :         } else {
     238           0 :             DEBUG(SSSDBG_TRACE_ALL, "--- empty cert list node ---\n");
     239             :         }
     240             :     }
     241             : 
     242           6 :     rv = CERT_FilterCertListByUsage(cert_list, certUsageSSLClient, PR_FALSE);
     243           6 :     if (rv != SECSuccess) {
     244           0 :         DEBUG(SSSDBG_OP_FAILURE, "CERT_FilterCertListByUsage failed: [%d].\n",
     245             :                                  PR_GetError());
     246           0 :         return EIO;
     247             :     }
     248             : 
     249           6 :     rv = CERT_FilterCertListForUserCerts(cert_list);
     250           6 :     if (rv != SECSuccess) {
     251           0 :         DEBUG(SSSDBG_OP_FAILURE, "CERT_FilterCertListForUserCerts failed: [%d].\n",
     252             :                                  PR_GetError());
     253           0 :         return EIO;
     254             :     }
     255             : 
     256             : 
     257           6 :     handle = CERT_GetDefaultCertDB();
     258           6 :     if (handle == NULL) {
     259           0 :         DEBUG(SSSDBG_OP_FAILURE, "CERT_GetDefaultCertDB failed: [%d].\n",
     260             :                                  PR_GetError());
     261           0 :         return EIO;
     262             :     }
     263             : 
     264             : 
     265           6 :     found_cert = NULL;
     266           6 :     DEBUG(SSSDBG_TRACE_ALL, "Filtered certificates:\n");
     267          18 :     for (cert_list_node = CERT_LIST_HEAD(cert_list);
     268          12 :                 !CERT_LIST_END(cert_list_node, cert_list);
     269           6 :                 cert_list_node = CERT_LIST_NEXT(cert_list_node)) {
     270           6 :         if (cert_list_node->cert) {
     271           6 :             DEBUG(SSSDBG_TRACE_ALL, "found cert[%s][%s]\n",
     272             :                              cert_list_node->cert->nickname,
     273             :                              cert_list_node->cert->subjectName);
     274             : 
     275           6 :             if (found_cert == NULL) {
     276           6 :                 found_cert = cert_list_node->cert;
     277             :             } else {
     278           0 :                 DEBUG(SSSDBG_TRACE_ALL, "More than one certificate found, " \
     279             :                                         "using just the first one.\n");
     280             :             }
     281             :         } else {
     282           0 :             DEBUG(SSSDBG_TRACE_ALL, "--- empty cert list node ---\n");
     283             :         }
     284             :     }
     285             : 
     286           6 :     if (found_cert == NULL) {
     287           0 :         DEBUG(SSSDBG_TRACE_ALL, "No certificate found.\n");
     288           0 :         *cert = NULL;
     289           0 :         *token_name_out = NULL;
     290           0 :         ret = EOK;
     291           0 :         goto done;
     292             :     }
     293             : 
     294           6 :     rv = CERT_VerifyCertificateNow(handle, found_cert, PR_TRUE,
     295             :                                    certificateUsageSSLClient, NULL, NULL);
     296           6 :     if (rv != SECSuccess) {
     297           0 :         DEBUG(SSSDBG_OP_FAILURE,
     298             :               "CERT_VerifyCertificateNow failed [%d].\n",
     299             :               PR_GetError());
     300           0 :         ret = EIO;
     301           0 :         goto done;
     302             :     }
     303             : 
     304           6 :     if (mode == OP_AUTH) {
     305           1 :         rv = PK11_GenerateRandom(random_value, sizeof(random_value));
     306           1 :         if (rv != SECSuccess) {
     307           0 :             DEBUG(SSSDBG_OP_FAILURE,
     308             :                   "PK11_GenerateRandom failed [%d].\n", PR_GetError());
     309           0 :             return EIO;
     310             :         }
     311             : 
     312           1 :         priv_key = PK11_FindPrivateKeyFromCert(slot, found_cert, NULL);
     313           1 :         if (priv_key == NULL) {
     314           0 :             DEBUG(SSSDBG_OP_FAILURE,
     315             :                   "PK11_FindPrivateKeyFromCert failed [%d]." \
     316             :                   "Maybe pin is missing.\n", PR_GetError());
     317           0 :             ret = EIO;
     318           0 :             goto done;
     319             :         }
     320             : 
     321           1 :         algtag = SEC_GetSignatureAlgorithmOidTag(priv_key->keyType,
     322             :                                                   SEC_OID_SHA1);
     323           1 :         if (algtag == SEC_OID_UNKNOWN) {
     324           0 :             SECKEY_DestroyPrivateKey(priv_key);
     325           0 :             DEBUG(SSSDBG_OP_FAILURE,
     326             :                   "SEC_GetSignatureAlgorithmOidTag failed [%d].",
     327             :                   PR_GetError());
     328           0 :             ret = EIO;
     329           0 :             goto done;
     330             :         }
     331             : 
     332           1 :         rv = SEC_SignData(&signed_random_value,
     333             :                           random_value, sizeof(random_value),
     334             :                           priv_key, algtag);
     335           1 :         SECKEY_DestroyPrivateKey(priv_key);
     336           1 :         if (rv != SECSuccess) {
     337           0 :             DEBUG(SSSDBG_OP_FAILURE, "SEC_SignData failed [%d].",
     338             :                                      PR_GetError());
     339           0 :             ret = EIO;
     340           0 :             goto done;
     341             :         }
     342             : 
     343           1 :         pub_key = CERT_ExtractPublicKey(found_cert);
     344           1 :         if (pub_key == NULL) {
     345           0 :             DEBUG(SSSDBG_OP_FAILURE,
     346             :                   "CERT_ExtractPublicKey failed [%d].", PR_GetError());
     347           0 :             ret = EIO;
     348           0 :             goto done;
     349             :         }
     350             : 
     351           1 :         rv = VFY_VerifyData(random_value, sizeof(random_value),
     352             :                             pub_key, &signed_random_value, algtag,
     353             :                             NULL);
     354           1 :         SECKEY_DestroyPublicKey(pub_key);
     355           1 :         if (rv != SECSuccess) {
     356           0 :             DEBUG(SSSDBG_OP_FAILURE, "VFY_VerifyData failed [%d].",
     357             :                                      PR_GetError());
     358           0 :             ret = EACCES;
     359           0 :             goto done;
     360             :         }
     361             : 
     362           1 :         DEBUG(SSSDBG_TRACE_ALL,
     363             :               "Certificate verified and validated.\n");
     364             :     }
     365             : 
     366           6 :     *cert = sss_base64_encode(mem_ctx, found_cert->derCert.data,
     367           6 :                                        found_cert->derCert.len);
     368           6 :     if (*cert == NULL) {
     369           0 :         DEBUG(SSSDBG_OP_FAILURE, "sss_base64_encode failed.\n");
     370           0 :         ret = ENOMEM;
     371           0 :         goto done;
     372             :     }
     373             : 
     374           6 :     *token_name_out = talloc_strdup(mem_ctx, token_name);
     375           6 :     if (*token_name_out == NULL) {
     376           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to copy slot name.\n");
     377           0 :         ret = ENOMEM;
     378           0 :         goto done;
     379             :     }
     380             : 
     381           6 :     ret = EOK;
     382             : 
     383             : done:
     384           6 :     if (slot != NULL) {
     385           6 :         PK11_FreeSlot(slot);
     386             :     }
     387             : 
     388           6 :     if (cert_list != NULL) {
     389           6 :         CERT_DestroyCertList(cert_list);
     390             :     }
     391             : 
     392           6 :     PORT_Free(signed_random_value.data);
     393             : 
     394           6 :     rv = NSS_ShutdownContext(nss_ctx);
     395           6 :     if (rv != SECSuccess) {
     396           0 :         DEBUG(SSSDBG_OP_FAILURE, "NSS_ShutdownContext failed [%d].\n",
     397             :                                  PR_GetError());
     398             :     }
     399             : 
     400           6 :     return ret;
     401             : }
     402             : 
     403           1 : static errno_t p11c_recv_data(TALLOC_CTX *mem_ctx, int fd, char **pin)
     404             : {
     405             :     uint8_t buf[IN_BUF_SIZE];
     406             :     ssize_t len;
     407             :     errno_t ret;
     408             :     char *str;
     409             : 
     410           1 :     errno = 0;
     411           1 :     len = sss_atomic_read_s(fd, buf, IN_BUF_SIZE);
     412           1 :     if (len == -1) {
     413           0 :         ret = errno;
     414           0 :         ret = (ret == 0) ? EINVAL: ret;
     415           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     416             :               "read failed [%d][%s].\n", ret, strerror(ret));
     417           0 :         return ret;
     418             :     }
     419             : 
     420           1 :     if (len == 0 || *buf == '\0') {
     421           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Missing PIN.\n");
     422           0 :         return EINVAL;
     423             :     }
     424             : 
     425           1 :     str = talloc_strndup(mem_ctx, (char *) buf, len);
     426           1 :     if (str == NULL) {
     427           0 :         DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
     428           0 :         return ENOMEM;
     429             :     }
     430             : 
     431           1 :     if (strlen(str) != len) {
     432           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     433             :               "Input contains additional data, only PIN expected.\n");
     434           0 :         talloc_free(str);
     435           0 :         return EINVAL;
     436             :     }
     437             : 
     438           1 :     *pin = str;
     439             : 
     440           1 :     return EOK;
     441             : }
     442             : 
     443           8 : int main(int argc, const char *argv[])
     444             : {
     445             :     int opt;
     446             :     poptContext pc;
     447           8 :     int debug_fd = -1;
     448             :     errno_t ret;
     449           8 :     TALLOC_CTX *main_ctx = NULL;
     450             :     char *cert;
     451           8 :     enum op_mode mode = OP_NONE;
     452           8 :     enum pin_mode pin_mode = PIN_NONE;
     453           8 :     char *pin = NULL;
     454           8 :     char *slot_name_in = NULL;
     455           8 :     char *token_name_out = NULL;
     456           8 :     char *nss_db = NULL;
     457             : 
     458          88 :     struct poptOption long_options[] = {
     459             :         POPT_AUTOHELP
     460             :         {"debug-level", 'd', POPT_ARG_INT, &debug_level, 0,
     461           8 :          _("Debug level"), NULL},
     462             :         {"debug-timestamps", 0, POPT_ARG_INT, &debug_timestamps, 0,
     463           8 :          _("Add debug timestamps"), NULL},
     464             :         {"debug-microseconds", 0, POPT_ARG_INT, &debug_microseconds, 0,
     465           8 :          _("Show timestamps with microseconds"), NULL},
     466             :         {"debug-fd", 0, POPT_ARG_INT, &debug_fd, 0,
     467           8 :          _("An open file descriptor for the debug logs"), NULL},
     468             :         {"debug-to-stderr", 0, POPT_ARG_NONE | POPT_ARGFLAG_DOC_HIDDEN,
     469             :          &debug_to_stderr, 0,
     470           8 :          _("Send the debug output to stderr directly."), NULL },
     471           8 :         {"auth", 0, POPT_ARG_NONE, NULL, 'a', _("Run in auth mode"), NULL},
     472           8 :         {"pre", 0, POPT_ARG_NONE, NULL, 'p', _("Run in pre-auth mode"), NULL},
     473           8 :         {"pin", 0, POPT_ARG_NONE, NULL, 'i', _("Expect PIN on stdin"), NULL},
     474           8 :         {"keypad", 0, POPT_ARG_NONE, NULL, 'k', _("Expect PIN on keypad"),
     475             :          NULL},
     476           8 :         {"nssdb", 0, POPT_ARG_STRING, &nss_db, 0, _("NSS DB to use"),
     477             :          NULL},
     478             :         POPT_TABLEEND
     479             :     };
     480             : 
     481             :     /* Set debug level to invalid value so we can decide if -d 0 was used. */
     482           8 :     debug_level = SSSDBG_INVALID;
     483             : 
     484             :     /*
     485             :      * This child runs as root (setuid(0)), so we need clear environment and
     486             :      * set permissions for security reasons.
     487             :      */
     488           8 :     clearenv();
     489           8 :     umask(SSS_DFL_UMASK);
     490             : 
     491           8 :     pc = poptGetContext(argv[0], argc, argv, long_options, 0);
     492           8 :     while ((opt = poptGetNextOpt(pc)) != -1) {
     493           9 :         switch(opt) {
     494             :         case 'a':
     495           1 :             if (mode != OP_NONE) {
     496           0 :                 fprintf(stderr,
     497             :                         "\n--auth and --pre are mutually exclusive and " \
     498             :                         "should be only used once.\n\n");
     499           0 :                 poptPrintUsage(pc, stderr, 0);
     500           0 :                 _exit(-1);
     501             :             }
     502           1 :             mode = OP_AUTH;
     503           1 :             break;
     504             :         case 'p':
     505           7 :             if (mode != OP_NONE) {
     506           0 :                 fprintf(stderr,
     507             :                         "\n--auth and --pre are mutually exclusive and " \
     508             :                         "should be only used once.\n\n");
     509           0 :                 poptPrintUsage(pc, stderr, 0);
     510           0 :                 _exit(-1);
     511             :             }
     512           7 :             mode = OP_PREAUTH;
     513           7 :             break;
     514             :         case 'i':
     515           1 :             if (pin_mode != PIN_NONE) {
     516           0 :                 fprintf(stderr, "\n--pin and --keypad are mutually exclusive " \
     517             :                                 "and should be only used once.\n\n");
     518           0 :                 poptPrintUsage(pc, stderr, 0);
     519           0 :                 _exit(-1);
     520             :             }
     521           1 :             pin_mode = PIN_STDIN;
     522           1 :             break;
     523             :         case 'k':
     524           0 :             if (pin_mode != PIN_NONE) {
     525           0 :                 fprintf(stderr, "\n--pin and --keypad are mutually exclusive " \
     526             :                                 "and should be only used once.\n\n");
     527           0 :                 poptPrintUsage(pc, stderr, 0);
     528           0 :                 _exit(-1);
     529             :             }
     530           0 :             pin_mode = PIN_KEYPAD;
     531           0 :             break;
     532             :         default:
     533           0 :             fprintf(stderr, "\nInvalid option %s: %s\n\n",
     534             :                   poptBadOption(pc, 0), poptStrerror(opt));
     535           0 :             poptPrintUsage(pc, stderr, 0);
     536           0 :             _exit(-1);
     537             :         }
     538             :     }
     539             : 
     540           8 :     if (nss_db == NULL) {
     541           0 :         fprintf(stderr, "\nMissing NSS DB --nssdb must be specified.\n\n");
     542           0 :         poptPrintUsage(pc, stderr, 0);
     543           0 :         _exit(-1);
     544             :     }
     545             : 
     546           8 :     if (mode == OP_NONE) {
     547           0 :         fprintf(stderr, "\nMissing operation mode, " \
     548             :                         "either --auth or --pre must be specified.\n\n");
     549           0 :         poptPrintUsage(pc, stderr, 0);
     550           0 :         _exit(-1);
     551           8 :     } else if (mode == OP_AUTH && pin_mode == PIN_NONE) {
     552           0 :         fprintf(stderr, "\nMissing pin mode for authentication, " \
     553             :                         "either --pin or --keypad must be specified.\n");
     554           0 :         poptPrintUsage(pc, stderr, 0);
     555           0 :         _exit(-1);
     556             :     }
     557             : 
     558           8 :     poptFreeContext(pc);
     559             : 
     560           8 :     DEBUG_INIT(debug_level);
     561             : 
     562           8 :     debug_prg_name = talloc_asprintf(NULL, "[sssd[p11_child[%d]]]", getpid());
     563           8 :     if (debug_prg_name == NULL) {
     564           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf failed.\n");
     565           0 :         goto fail;
     566             :     }
     567             : 
     568           8 :     if (debug_fd != -1) {
     569           0 :         ret = set_debug_file_from_fd(debug_fd);
     570           0 :         if (ret != EOK) {
     571           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "set_debug_file_from_fd failed.\n");
     572             :         }
     573             :     }
     574             : 
     575           8 :     DEBUG(SSSDBG_TRACE_FUNC, "p11_child started.\n");
     576             : 
     577           8 :     DEBUG(SSSDBG_TRACE_INTERNAL, "Running in [%s] mode.\n",
     578             :           mode == OP_AUTH ? "auth"
     579             :                           : (mode == OP_PREAUTH ? "pre-auth" : "unknown"));
     580             : 
     581           8 :     DEBUG(SSSDBG_TRACE_INTERNAL,
     582             :           "Running with effective IDs: [%"SPRIuid"][%"SPRIgid"].\n",
     583             :           geteuid(), getegid());
     584             : 
     585           8 :     if (getuid() != 0) {
     586           8 :         ret = setuid(0);
     587           8 :         if (ret == -1) {
     588           8 :             ret = errno;
     589           8 :             DEBUG(SSSDBG_CRIT_FAILURE,
     590             :                   "setuid failed: %d, p11_child might not work!\n", ret);
     591             :         }
     592             :     }
     593             : 
     594           8 :     if (getgid() != 0) {
     595           8 :         ret = setgid(0);
     596           8 :         if (ret == -1) {
     597           8 :             ret = errno;
     598           8 :             DEBUG(SSSDBG_CRIT_FAILURE,
     599             :                   "setgid failed: %d, p11_child might not work!\n", ret);
     600             :         }
     601             :     }
     602             : 
     603           8 :     DEBUG(SSSDBG_TRACE_INTERNAL,
     604             :           "Running with real IDs [%"SPRIuid"][%"SPRIgid"].\n",
     605             :           getuid(), getgid());
     606             : 
     607           8 :     main_ctx = talloc_new(NULL);
     608           8 :     if (main_ctx == NULL) {
     609           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new failed.\n");
     610           0 :         talloc_free(discard_const(debug_prg_name));
     611           0 :         goto fail;
     612             :     }
     613           8 :     talloc_steal(main_ctx, debug_prg_name);
     614             : 
     615             : 
     616           8 :     if (mode == OP_AUTH && pin_mode == PIN_STDIN) {
     617           1 :         ret = p11c_recv_data(main_ctx, STDIN_FILENO, &pin);
     618           1 :         if (ret != EOK) {
     619           0 :             DEBUG(SSSDBG_FATAL_FAILURE, "Failed to read pin.\n");
     620           0 :             goto fail;
     621             :         }
     622             :     }
     623             : 
     624           8 :     ret = do_work(main_ctx, nss_db, slot_name_in, mode, pin, &cert,
     625             :                   &token_name_out);
     626           8 :     if (ret != EOK) {
     627           2 :         DEBUG(SSSDBG_OP_FAILURE, "do_work failed.\n");
     628           2 :         goto fail;
     629             :     }
     630             : 
     631           6 :     if (cert != NULL) {
     632           6 :         fprintf(stdout, "%s\n", token_name_out);
     633           6 :         fprintf(stdout, "%s\n", cert);
     634             :     }
     635             : 
     636           6 :     talloc_free(main_ctx);
     637           6 :     return EXIT_SUCCESS;
     638             : fail:
     639           2 :     DEBUG(SSSDBG_CRIT_FAILURE, "p11_child failed!\n");
     640           2 :     close(STDOUT_FILENO);
     641           2 :     talloc_free(main_ctx);
     642           2 :     return EXIT_FAILURE;
     643             : }

Generated by: LCOV version 1.10