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, ¶meters, 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 : }
|