diff options
author | Hans Rosenfeld <hans.rosenfeld@joyent.com> | 2020-01-12 01:01:41 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-01-12 01:01:41 +0100 |
commit | b44b91e41531b86f9807aecf62d96cad6f2f06cd (patch) | |
tree | 1fe4c2409126f74cddb013d220c824367d9dc788 /usr/src/lib | |
parent | 8b175886ef45935e972cf1df20218f2de66d49b1 (diff) | |
download | illumos-joyent-b44b91e41531b86f9807aecf62d96cad6f2f06cd.tar.gz |
OS-7196 Need native CCID driver
Contributed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: John Levon <john.levon@joyent.com>
Approved by: Jason King <jbk@joyent.com>
Diffstat (limited to 'usr/src/lib')
-rw-r--r-- | usr/src/lib/Makefile | 2 | ||||
-rw-r--r-- | usr/src/lib/cfgadm_plugins/Makefile | 5 | ||||
-rw-r--r-- | usr/src/lib/cfgadm_plugins/ccid/Makefile | 67 | ||||
-rw-r--r-- | usr/src/lib/cfgadm_plugins/ccid/Makefile.com | 67 | ||||
-rw-r--r-- | usr/src/lib/cfgadm_plugins/ccid/amd64/Makefile | 21 | ||||
-rw-r--r-- | usr/src/lib/cfgadm_plugins/ccid/common/cfga_ccid.c | 421 | ||||
-rw-r--r-- | usr/src/lib/cfgadm_plugins/ccid/common/mapfile-vers | 42 | ||||
-rw-r--r-- | usr/src/lib/cfgadm_plugins/ccid/i386/Makefile | 20 | ||||
-rw-r--r-- | usr/src/lib/libcmdutils/common/nicenum.c | 14 | ||||
-rw-r--r-- | usr/src/lib/libcmdutils/libcmdutils.h | 3 | ||||
-rw-r--r-- | usr/src/lib/libpcsc/Makefile | 43 | ||||
-rw-r--r-- | usr/src/lib/libpcsc/Makefile.com | 32 | ||||
-rw-r--r-- | usr/src/lib/libpcsc/amd64/Makefile | 19 | ||||
-rw-r--r-- | usr/src/lib/libpcsc/common/libpcsc.c | 615 | ||||
-rw-r--r-- | usr/src/lib/libpcsc/common/mapfile-vers | 50 | ||||
-rw-r--r-- | usr/src/lib/libpcsc/common/winscard.h | 144 | ||||
-rw-r--r-- | usr/src/lib/libpcsc/common/wintypes.h | 50 | ||||
-rw-r--r-- | usr/src/lib/libpcsc/i386/Makefile | 18 |
18 files changed, 1627 insertions, 6 deletions
diff --git a/usr/src/lib/Makefile b/usr/src/lib/Makefile index cb326e5e45..1363c5cc1b 100644 --- a/usr/src/lib/Makefile +++ b/usr/src/lib/Makefile @@ -181,6 +181,7 @@ SUBDIRS += \ libofmt \ libpam \ libpcidb \ + libpcsc \ libpctx \ libpicl \ libpicltree \ @@ -448,6 +449,7 @@ HDRSUBDIRS= \ libofmt \ libpam \ libpcidb \ + libpcsc \ libpctx \ libpicl \ libpicltree \ diff --git a/usr/src/lib/cfgadm_plugins/Makefile b/usr/src/lib/cfgadm_plugins/Makefile index 00d258b20a..8fa7f73df7 100644 --- a/usr/src/lib/cfgadm_plugins/Makefile +++ b/usr/src/lib/cfgadm_plugins/Makefile @@ -20,13 +20,14 @@ # # # Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2019 Joyent, Inc. # # lib/cfgadm_plugins/Makefile # include $(SRC)/Makefile.master -COMMON_SUBDIRS= scsi pci usb ib fp shp sbd +COMMON_SUBDIRS= scsi pci usb ib fp shp sbd ccid sparc_SUBDIRS= ac sysctrl i386_SUBDIRS= sata @@ -37,7 +38,7 @@ ALL_SUBDIRS= $(COMMON_SUBDIRS) $(sparc_SUBDIRS) $(i386_SUBDIRS) MSGSUBDIRS= $(ALL_SUBDIRS) -all:= TARGET= all +all:= TARGET= all install:= TARGET= install clean:= TARGET= clean clobber:= TARGET= clobber diff --git a/usr/src/lib/cfgadm_plugins/ccid/Makefile b/usr/src/lib/cfgadm_plugins/ccid/Makefile new file mode 100644 index 0000000000..7d4af31c7d --- /dev/null +++ b/usr/src/lib/cfgadm_plugins/ccid/Makefile @@ -0,0 +1,67 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# Copyright 2019, Joyent, Inc. +# + +include ../../Makefile.lib + +$(INTEL_BLD)SUBDIRS = $(MACH) $(BUILD64) $(MACH64) + +all := TARGET= all +clean := TARGET= clean +clobber := TARGET= clobber +delete := TARGET= delete +install := TARGET= install +_msg := TARGET= _msg +package := TARGET= package + +SED= sed +GREP= grep + +.KEEP_STATE: + +all clean delete install package: $(SUBDIRS) +clobber: $(SUBDIRS) + $(RM) $(POFILE) $(POFILES) + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +# +# We don't build any gettext libraries here +# +_msg: + +$(POFILE): $(POFILES) + $(RM) $@ + $(CAT) $(POFILES) > $@ + +$(POFILES): + $(RM) messages.po + $(XGETTEXT) $(XGETFLAGS) `$(GREP) -l gettext */*.[ch]` + $(SED) -e '/^# msg/d' -e '/^domain/d' messages.po > $@ + $(RM) messages.po + +FRC: diff --git a/usr/src/lib/cfgadm_plugins/ccid/Makefile.com b/usr/src/lib/cfgadm_plugins/ccid/Makefile.com new file mode 100644 index 0000000000..30a2ce1527 --- /dev/null +++ b/usr/src/lib/cfgadm_plugins/ccid/Makefile.com @@ -0,0 +1,67 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# Copyright 2019, Joyent, Inc. +# + +LIBRARY= ccid.a +VERS= .1 + +OBJECTS= cfga_ccid.o + +# include library definitions +include ../../../Makefile.lib + +SRCDIR = ../common +ROOTLIBDIR= $(ROOT)/usr/lib/cfgadm +ROOTLIBDIR64= $(ROOTLIBDIR)/$(MACH64) + +LIBS= $(DYNLIB) + +CFLAGS += $(CCVERBOSE) +CFLAGS64 += $(CCVERBOSE) + +LDLIBS += -lc + +.KEEP_STATE: + +all: $(LIBS) + +# Install rules + +$(ROOTLIBDIR)/%: % $(ROOTLIBDIR) + $(INS.file) + +$(ROOTLIBDIR64)/%: % $(ROOTLIBDIR64) + $(INS.file) + +$(ROOTLIBDIR) $(ROOTLIBDIR64): + $(INS.dir) + +# include library targets +include ../../../Makefile.targ + +objs/%.o pics/%.o: ../common/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) diff --git a/usr/src/lib/cfgadm_plugins/ccid/amd64/Makefile b/usr/src/lib/cfgadm_plugins/ccid/amd64/Makefile new file mode 100644 index 0000000000..f2eb3c97a2 --- /dev/null +++ b/usr/src/lib/cfgadm_plugins/ccid/amd64/Makefile @@ -0,0 +1,21 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2019, Joyent, Inc. +# + +include ../Makefile.com +include ../../../Makefile.lib.64 + +.KEEP_STATE: + +install: all $(ROOTLIBS64) $(ROOTLINKS64) diff --git a/usr/src/lib/cfgadm_plugins/ccid/common/cfga_ccid.c b/usr/src/lib/cfgadm_plugins/ccid/common/cfga_ccid.c new file mode 100644 index 0000000000..4ce28c2aec --- /dev/null +++ b/usr/src/lib/cfgadm_plugins/ccid/common/cfga_ccid.c @@ -0,0 +1,421 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2019, Joyent, Inc. + */ + +/* + * CCID cfgadm plugin + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdio.h> +#include <stdarg.h> +#include <errno.h> +#include <string.h> +#include <strings.h> +#include <stdlib.h> + +#include <sys/usb/clients/ccid/uccid.h> + +#define CFGA_PLUGIN_LIB +#include <config_admin.h> + +int cfga_version = CFGA_HSL_V2; + +static cfga_err_t +cfga_ccid_error(cfga_err_t err, char **errp, const char *fmt, ...) +{ + va_list ap; + + if (errp == NULL) + return (err); + + /* + * Try to format a string. However because we have to return allocated + * memory, if this fails, then we have no error. + */ + va_start(ap, fmt); + (void) vasprintf(errp, fmt, ap); + va_end(ap); + + return (err); +} + +cfga_err_t +cfga_ccid_modify(uccid_cmd_icc_modify_t *modify, const char *ap, + struct cfga_confirm *confp, struct cfga_msg *msgp, char **errp, + boolean_t force) +{ + int fd; + uccid_cmd_status_t ucs; + uccid_cmd_txn_begin_t begin; + boolean_t held = B_FALSE; + + /* + * Check ap is valid by doing a status request. + */ + if ((fd = open(ap, O_RDWR)) < 0) { + return (cfga_ccid_error(CFGA_LIB_ERROR, errp, + "failed to open %s: %s", ap, strerror(errno))); + } + + bzero(&ucs, sizeof (ucs)); + ucs.ucs_version = UCCID_CURRENT_VERSION; + + if (ioctl(fd, UCCID_CMD_STATUS, &ucs) != 0) { + int e = errno; + if (errno == ENODEV) { + (void) close(fd); + return (cfga_ccid_error(CFGA_LIB_ERROR, errp, + "ap %s going away", ap)); + } + (void) close(fd); + return (cfga_ccid_error(CFGA_ERROR, errp, + "ioctl on ap %s failed: %s", ap, strerror(e))); + } + + /* + * Attempt to get a hold. If we cannot obtain a hold, we will not + * perform this unless the user has said we should force this. + */ + bzero(&begin, sizeof (begin)); + begin.uct_version = UCCID_CURRENT_VERSION; + begin.uct_flags = UCCID_TXN_DONT_BLOCK; + if (ioctl(fd, UCCID_CMD_TXN_BEGIN, &begin) != 0) { + if (errno != EBUSY) { + int e = errno; + (void) close(fd); + return (cfga_ccid_error(CFGA_ERROR, errp, "failed to " + "begin ccid transaction on ap %s: %s", ap, + strerror(e))); + } + + /* + * If the user didn't force this operation, prompt if we would + * interfere. + */ + if (!force) { + int confirm = 0; + const char *prompt = "CCID slot is held exclusively " + "by another program. Proceeding may interrupt " + "their functionality. Continue?"; + if (confp != NULL && confp->appdata_ptr != NULL) { + confirm = (*confp->confirm)(confp->appdata_ptr, + prompt); + } + + if (confirm == 0) { + (void) close(fd); + return (CFGA_NACK); + } + } + } else { + held = B_TRUE; + } + + if (ioctl(fd, UCCID_CMD_ICC_MODIFY, modify) != 0) { + int e = errno; + (void) close(fd); + return (cfga_ccid_error(CFGA_ERROR, errp, + "failed to modify state on ap %s: %s", ap, + strerror(e))); + } + + if (held) { + uccid_cmd_txn_end_t end; + + bzero(&end, sizeof (end)); + end.uct_version = UCCID_CURRENT_VERSION; + end.uct_flags = UCCID_TXN_END_RELEASE; + + if (ioctl(fd, UCCID_CMD_TXN_END, &end) != 0) { + int e = errno; + (void) close(fd); + return (cfga_ccid_error(CFGA_ERROR, errp, "failed to " + "end transaction on ap %s: %s", ap, + strerror(e))); + } + } + + (void) close(fd); + return (CFGA_OK); + +} + +cfga_err_t +cfga_change_state(cfga_cmd_t cmd, const char *ap, const char *opts, + struct cfga_confirm *confp, struct cfga_msg *msgp, char **errp, + cfga_flags_t flags) +{ + uccid_cmd_icc_modify_t modify; + + if (errp != NULL) { + *errp = NULL; + } + + if (ap == NULL) { + return (cfga_ccid_error(CFGA_APID_NOEXIST, errp, NULL)); + } + + if (opts != NULL) { + return (cfga_ccid_error(CFGA_ERROR, errp, + "hardware specific options are not supported")); + } + + bzero(&modify, sizeof (modify)); + modify.uci_version = UCCID_CURRENT_VERSION; + switch (cmd) { + case CFGA_CMD_CONFIGURE: + modify.uci_action = UCCID_ICC_POWER_ON; + break; + case CFGA_CMD_UNCONFIGURE: + modify.uci_action = UCCID_ICC_POWER_OFF; + break; + default: + (void) cfga_help(msgp, opts, flags); + return (CFGA_OPNOTSUPP); + } + + return (cfga_ccid_modify(&modify, ap, confp, msgp, errp, + (flags & CFGA_FLAG_FORCE) != 0)); +} + +cfga_err_t +cfga_private_func(const char *function, const char *ap, const char *opts, + struct cfga_confirm *confp, struct cfga_msg *msgp, char **errp, + cfga_flags_t flags) +{ + uccid_cmd_icc_modify_t modify; + + if (errp != NULL) { + *errp = NULL; + } + + if (function == NULL) { + return (CFGA_ERROR); + } + + if (ap == NULL) { + return (cfga_ccid_error(CFGA_APID_NOEXIST, errp, NULL)); + } + + if (opts != NULL) { + return (cfga_ccid_error(CFGA_ERROR, errp, + "hardware specific options are not supported")); + } + + if (strcmp(function, "warm_reset") != 0) { + return (CFGA_OPNOTSUPP); + } + + bzero(&modify, sizeof (modify)); + modify.uci_version = UCCID_CURRENT_VERSION; + modify.uci_action = UCCID_ICC_WARM_RESET; + + return (cfga_ccid_modify(&modify, ap, confp, msgp, errp, + (flags & CFGA_FLAG_FORCE) != 0)); +} + +/* + * We don't support the test entry point for CCID. + */ +cfga_err_t +cfga_test(const char *ap, const char *opts, struct cfga_msg *msgp, char **errp, + cfga_flags_t flags) +{ + (void) cfga_help(msgp, opts, flags); + return (CFGA_OPNOTSUPP); +} + +static void +cfga_ccid_fill_info(const uccid_cmd_status_t *ucs, char *buf, size_t len) +{ + const char *product, *serial, *tran, *prot; + uint_t bits = CCID_CLASS_F_TPDU_XCHG | CCID_CLASS_F_SHORT_APDU_XCHG | + CCID_CLASS_F_EXT_APDU_XCHG; + + if ((ucs->ucs_status & UCCID_STATUS_F_PRODUCT_VALID) != 0) { + product = ucs->ucs_product; + } else { + product = "<unknown>"; + } + + if ((ucs->ucs_status & UCCID_STATUS_F_SERIAL_VALID) != 0) { + serial = ucs->ucs_serial; + } else { + serial = "<unknown>"; + } + + switch (ucs->ucs_class.ccd_dwFeatures & bits) { + case 0: + tran = "Character"; + break; + case CCID_CLASS_F_TPDU_XCHG: + tran = "TPDU"; + break; + case CCID_CLASS_F_SHORT_APDU_XCHG: + case CCID_CLASS_F_EXT_APDU_XCHG: + tran = "APDU"; + break; + default: + tran = "Unknown"; + break; + } + + if ((ucs->ucs_status & UCCID_STATUS_F_PARAMS_VALID) != 0) { + switch (ucs->ucs_prot) { + case UCCID_PROT_T0: + prot = " (T=0)"; + break; + case UCCID_PROT_T1: + prot = " (T=1)"; + break; + default: + prot = "<unknown>"; + break; + } + } else { + prot = "<unknown>"; + } + + if ((ucs->ucs_status & UCCID_STATUS_F_CARD_ACTIVE) != 0) { + (void) snprintf(buf, len, "Product: %s Serial: %s " + "Transport: %s Protocol: %s", product, serial, + tran, prot); + } else { + (void) snprintf(buf, len, "Product: %s Serial: %s ", + product, serial); + } +} + +cfga_err_t +cfga_list_ext(const char *ap, struct cfga_list_data **ap_list, int *nlist, + const char *opts, const char *listopts, char **errp, cfga_flags_t flags) +{ + int fd; + uccid_cmd_status_t ucs; + struct cfga_list_data *cld; + + if (errp != NULL) { + *errp = NULL; + } + + if (ap == NULL) { + return (cfga_ccid_error(CFGA_APID_NOEXIST, errp, NULL)); + } + + if (opts != NULL) { + return (cfga_ccid_error(CFGA_ERROR, errp, + "hardware specific options are not supported")); + } + + if ((fd = open(ap, O_RDWR)) < 0) { + return (cfga_ccid_error(CFGA_LIB_ERROR, errp, + "failed to open %s: %s", ap, strerror(errno))); + } + + bzero(&ucs, sizeof (ucs)); + ucs.ucs_version = UCCID_CURRENT_VERSION; + + if (ioctl(fd, UCCID_CMD_STATUS, &ucs) != 0) { + int e = errno; + (void) close(fd); + if (e == ENODEV) { + return (cfga_ccid_error(CFGA_LIB_ERROR, errp, + "ap %s going away", ap)); + } + return (cfga_ccid_error(CFGA_ERROR, errp, + "ioctl on ap %s failed: %s", ap, strerror(e))); + } + (void) close(fd); + + if ((cld = calloc(1, sizeof (*cld))) == NULL) { + return (cfga_ccid_error(CFGA_LIB_ERROR, errp, "failed to " + "allocate memory for list entry")); + } + + if (snprintf(cld->ap_log_id, sizeof (cld->ap_log_id), "ccid%d/slot%u", + ucs.ucs_instance, ucs.ucs_slot) >= sizeof (cld->ap_log_id)) { + free(cld); + return (cfga_ccid_error(CFGA_LIB_ERROR, errp, "ap %s logical id" + " was too large", ap)); + } + + if (strlcpy(cld->ap_phys_id, ap, sizeof (cld->ap_phys_id)) >= + sizeof (cld->ap_phys_id)) { + free(cld); + return (cfga_ccid_error(CFGA_LIB_ERROR, errp, + "ap %s physical id was too long", ap)); + } + + cld->ap_class[0] = '\0'; + + if ((ucs.ucs_status & UCCID_STATUS_F_CARD_PRESENT) != 0) { + cld->ap_r_state = CFGA_STAT_CONNECTED; + if ((ucs.ucs_status & UCCID_STATUS_F_CARD_ACTIVE) != 0) { + cld->ap_o_state = CFGA_STAT_CONFIGURED; + } else { + cld->ap_o_state = CFGA_STAT_UNCONFIGURED; + } + } else { + cld->ap_r_state = CFGA_STAT_EMPTY; + cld->ap_o_state = CFGA_STAT_UNCONFIGURED; + } + + /* + * XXX We should probably have a way to indicate that there's an error + * when the ICC is basically foobar'd. We should also allow the status + * ioctl to know that the slot is resetting or something else is going + * on I guess. + */ + if ((ucs.ucs_class.ccd_dwFeatures & + (CCID_CLASS_F_SHORT_APDU_XCHG | CCID_CLASS_F_EXT_APDU_XCHG)) == 0) { + cld->ap_cond = CFGA_COND_UNUSABLE; + } else { + cld->ap_cond = CFGA_COND_OK; + } + cld->ap_busy = 0; + cld->ap_status_time = (time_t)-1; + cfga_ccid_fill_info(&ucs, cld->ap_info, sizeof (cld->ap_info)); + if (strlcpy(cld->ap_type, "icc", sizeof (cld->ap_type)) >= + sizeof (cld->ap_type)) { + free(cld); + return (cfga_ccid_error(CFGA_LIB_ERROR, errp, + "ap %s type overflowed ICC field", ap)); + } + + *ap_list = cld; + *nlist = 1; + return (CFGA_OK); +} + +cfga_err_t +cfga_help(struct cfga_msg *msgp, const char *opts, cfga_flags_t flags) +{ + (void) (*msgp->message_routine)(msgp, "CCID specific commands:\n"); + (void) (*msgp->message_routine)(msgp, + " cfgadm -c [configure|unconfigure] ap_id [ap_id...]\n"); + (void) (*msgp->message_routine)(msgp, + " cfgadm -x warm_reset ap_id [ap_id...]\n"); + + return (CFGA_OK); +} + +int +cfga_ap_id_cmp(const cfga_ap_log_id_t ap_id1, const cfga_ap_log_id_t ap_id2) +{ + return (strcmp(ap_id1, ap_id2)); +} diff --git a/usr/src/lib/cfgadm_plugins/ccid/common/mapfile-vers b/usr/src/lib/cfgadm_plugins/ccid/common/mapfile-vers new file mode 100644 index 0000000000..7c7f7d2c0e --- /dev/null +++ b/usr/src/lib/cfgadm_plugins/ccid/common/mapfile-vers @@ -0,0 +1,42 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2019, Joyent, Inc. +# + +# +# MAPFILE HEADER START +# +# WARNING: STOP NOW. DO NOT MODIFY THIS FILE. +# Object versioning must comply with the rules detailed in +# +# usr/src/lib/README.mapfiles +# +# You should not be making modifications here until you've read the most current +# copy of that file. If you need help, contact a gatekeeper for guidance. +# +# MAPFILE HEADER END +# + +$mapfile_version 2 + +SYMBOL_VERSION SUNWprivate_1.1 { + global: + cfga_change_state; + cfga_help; + cfga_list_ext; + cfga_private_func; + cfga_test; + cfga_version; + local: + *; +}; diff --git a/usr/src/lib/cfgadm_plugins/ccid/i386/Makefile b/usr/src/lib/cfgadm_plugins/ccid/i386/Makefile new file mode 100644 index 0000000000..66d7a51776 --- /dev/null +++ b/usr/src/lib/cfgadm_plugins/ccid/i386/Makefile @@ -0,0 +1,20 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2019, Joyent, Inc. +# + +include ../Makefile.com + +.KEEP_STATE: + +install: all $(ROOTLIBS) $(ROOTLINKS) diff --git a/usr/src/lib/libcmdutils/common/nicenum.c b/usr/src/lib/libcmdutils/common/nicenum.c index 8e3202f792..9b9a8fcd5e 100644 --- a/usr/src/lib/libcmdutils/common/nicenum.c +++ b/usr/src/lib/libcmdutils/common/nicenum.c @@ -22,6 +22,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2017 Jason king + * Copyright 2019, Joyent, Inc. */ #include <stdio.h> @@ -44,8 +45,15 @@ nicenum_scale(uint64_t n, size_t units, char *buf, size_t buflen, uint64_t divisor = 1; int index = 0; int rc = 0; + int spclen = 0; + char *spc = ""; char u; + if (flags & NN_UNIT_SPACE) { + spc = " "; + spclen = 1; + } + if (units == 0) units = 1; @@ -90,7 +98,7 @@ nicenum_scale(uint64_t n, size_t units, char *buf, size_t buflen, * If this is an even multiple of the base, always display * without any decimal precision. */ - rc = snprintf(buf, buflen, "%llu%c", n / divisor, u); + rc = snprintf(buf, buflen, "%llu%s%c", n / divisor, spc, u); } else { /* * We want to choose a precision that reflects the best choice @@ -104,8 +112,8 @@ nicenum_scale(uint64_t n, size_t units, char *buf, size_t buflen, */ int i; for (i = 2; i >= 0; i--) { - if ((rc = snprintf(buf, buflen, "%.*f%c", i, - (double)n / divisor, u)) <= 5) + if ((rc = snprintf(buf, buflen, "%.*f%s%c", i, + (double)n / divisor, spc, u)) <= 5 + spclen) break; } } diff --git a/usr/src/lib/libcmdutils/libcmdutils.h b/usr/src/lib/libcmdutils/libcmdutils.h index c9a61aab4d..54c025c9d9 100644 --- a/usr/src/lib/libcmdutils/libcmdutils.h +++ b/usr/src/lib/libcmdutils/libcmdutils.h @@ -26,7 +26,7 @@ * Copyright (c) 2013 RackTop Systems. */ /* - * Copyright 2018 Joyent, Inc. + * Copyright 2019 Joyent, Inc. */ /* @@ -163,6 +163,7 @@ extern int findnextuid(uid_t, uid_t, uid_t *); extern int findnextgid(gid_t, gid_t, gid_t *); #define NN_DIVISOR_1000 (1U << 0) +#define NN_UNIT_SPACE (1U << 1) /* Minimum size for the output of nicenum, including NULL */ #define NN_NUMBUF_SZ (6) diff --git a/usr/src/lib/libpcsc/Makefile b/usr/src/lib/libpcsc/Makefile new file mode 100644 index 0000000000..b5fdecb2e4 --- /dev/null +++ b/usr/src/lib/libpcsc/Makefile @@ -0,0 +1,43 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2019 Joyent, Inc. +# + +include ../Makefile.lib + +HDRS = wintypes.h winscard.h +HDRDIR = common +SUBDIRS = $(MACH) +$(BUILD64)SUBDIRS += $(MACH64) + +all := TARGET = all +clean := TARGET = clean +clobber := TARGET = clobber +install := TARGET = install + +.KEEP_STATE: + +all clean clobber: $(SUBDIRS) + +install: $(SUBDIRS) install_h + +install_h: $(ROOTHDRS) + +check: $(CHECKHDRS) + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: + +include ../Makefile.targ diff --git a/usr/src/lib/libpcsc/Makefile.com b/usr/src/lib/libpcsc/Makefile.com new file mode 100644 index 0000000000..7bc91ef667 --- /dev/null +++ b/usr/src/lib/libpcsc/Makefile.com @@ -0,0 +1,32 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2019, Joyent, Inc. +# + +LIBRARY = libpcsc.a +VERS = .1 +OBJECTS = libpcsc.o + +include ../../Makefile.lib + +LIBS = $(DYNLIB) +LDLIBS += -lc +CPPFLAGS += -I../common + +SRCDIR = ../common + +.KEEP_STATE: + +all: $(LIBS) + +include ../../Makefile.targ diff --git a/usr/src/lib/libpcsc/amd64/Makefile b/usr/src/lib/libpcsc/amd64/Makefile new file mode 100644 index 0000000000..a32567f965 --- /dev/null +++ b/usr/src/lib/libpcsc/amd64/Makefile @@ -0,0 +1,19 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2019 Joyent, Inc. +# + +include ../Makefile.com +include ../../Makefile.lib.64 + +install: all $(ROOTLIBS64) $(ROOTLINKS64) diff --git a/usr/src/lib/libpcsc/common/libpcsc.c b/usr/src/lib/libpcsc/common/libpcsc.c new file mode 100644 index 0000000000..41d646e8b1 --- /dev/null +++ b/usr/src/lib/libpcsc/common/libpcsc.c @@ -0,0 +1,615 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2019, Joyent, Inc. + */ + +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <fts.h> +#include <errno.h> +#include <strings.h> +#include <unistd.h> +#include <sys/debug.h> +#include <sys/filio.h> +#include <sys/usb/clients/ccid/uccid.h> + +#include <winscard.h> + +/* + * Implementation of the PCSC library leveraging the uccid framework. + */ + +/* + * The library handle is basically unused today. We keep this around such that + * consumers which expect to receive a non-NULL opaque handle have something + * they can use. + */ +typedef struct pcsc_hdl { + hrtime_t pcsc_create_time; +} pcsc_hdl_t; + +typedef struct pcsc_card { + int pcc_fd; +} pcsc_card_t; + +/* + * Required globals + */ +SCARD_IO_REQUEST g_rgSCardT0Pci = { + SCARD_PROTOCOL_T0, + 0 +}; + +SCARD_IO_REQUEST g_rgSCardT1Pci = { + SCARD_PROTOCOL_T1, + 0 +}; + +SCARD_IO_REQUEST g_rgSCardRawPci = { + SCARD_PROTOCOL_RAW, + 0 +}; + +const char * +pcsc_stringify_error(const LONG err) +{ + switch (err) { + case SCARD_S_SUCCESS: + return ("no error"); + case SCARD_F_INTERNAL_ERROR: + return ("internal error"); + case SCARD_E_CANCELLED: + return ("request cancelled"); + case SCARD_E_INVALID_HANDLE: + return ("invalid handle"); + case SCARD_E_INVALID_PARAMETER: + return ("invalid parameter"); + case SCARD_E_NO_MEMORY: + return ("no memory"); + case SCARD_E_INSUFFICIENT_BUFFER: + return ("buffer was insufficiently sized"); + case SCARD_E_INVALID_VALUE: + return ("invalid value passed"); + case SCARD_E_UNKNOWN_READER: + return ("unknown reader"); + case SCARD_E_TIMEOUT: + return ("timeout occurred"); + case SCARD_E_SHARING_VIOLATION: + return ("sharing violation"); + case SCARD_E_NO_SMARTCARD: + return ("no smartcard present"); + case SCARD_E_UNKNOWN_CARD: + return ("unknown ICC"); + case SCARD_E_PROTO_MISMATCH: + return ("protocol mismatch"); + case SCARD_F_COMM_ERROR: + return ("communication error"); + case SCARD_F_UNKNOWN_ERROR: + return ("unknown error"); + case SCARD_E_READER_UNAVAILABLE: + return ("reader unavailable"); + case SCARD_E_NO_SERVICE: + return ("service error"); + case SCARD_E_UNSUPPORTED_FEATURE: + return ("ICC requires unsupported feature"); + case SCARD_E_NO_READERS_AVAILABLE: + return ("no readers avaiable"); + case SCARD_W_UNSUPPORTED_CARD: + return ("ICC unsupported"); + case SCARD_W_UNPOWERED_CARD: + return ("ICC is not powered"); + case SCARD_W_RESET_CARD: + return ("ICC was reset"); + case SCARD_W_REMOVED_CARD: + return ("ICC has been removed"); + default: + return ("unknown error"); + } +} + + +/* + * This is called when a caller wishes to open a new Library context. + */ +LONG +SCardEstablishContext(DWORD scope, LPCVOID unused0, LPCVOID unused1, + LPSCARDCONTEXT outp) +{ + pcsc_hdl_t *hdl; + + if (outp == NULL) { + return (SCARD_E_INVALID_PARAMETER); + } + + if (scope != SCARD_SCOPE_SYSTEM) { + return (SCARD_E_INVALID_VALUE); + } + + hdl = calloc(1, sizeof (pcsc_hdl_t)); + if (hdl == NULL) { + return (SCARD_E_NO_MEMORY); + } + + hdl->pcsc_create_time = gethrtime(); + *outp = hdl; + return (SCARD_S_SUCCESS); +} + +/* + * This is called to free a library context from a client. + */ +LONG +SCardReleaseContext(SCARDCONTEXT hdl) +{ + free(hdl); + return (SCARD_S_SUCCESS); +} + +/* + * This is called to release memory allocated by the library. No, it doesn't + * make sense to take a const pointer when being given memory to free. It just + * means we have to cast it, but remember: this isn't our API. + */ +LONG +SCardFreeMemory(SCARDCONTEXT unused, LPCVOID mem) +{ + free((void *)mem); + return (SCARD_S_SUCCESS); +} + +/* + * This is called by a caller to get a list of readers that exist in the system. + * If lenp is set to SCARD_AUTOALLOCATE, then we are responsible for dealing + * with this memory. + */ +LONG +SCardListReaders(SCARDCONTEXT unused, LPCSTR groups, LPSTR bufp, LPDWORD lenp) +{ + FTS *fts; + FTSENT *ent; + char *const root[] = { "/dev/ccid", NULL }; + char *ubuf; + char **readers; + uint32_t len, ulen, npaths, nalloc, off, i; + int ret; + + if (groups != NULL || lenp == NULL) { + return (SCARD_E_INVALID_PARAMETER); + } + + fts = fts_open(root, FTS_LOGICAL | FTS_NOCHDIR, NULL); + if (fts == NULL) { + switch (errno) { + case ENOENT: + case ENOTDIR: + return (SCARD_E_NO_READERS_AVAILABLE); + case ENOMEM: + case EAGAIN: + return (SCARD_E_NO_MEMORY); + default: + return (SCARD_E_NO_SERVICE); + } + } + + npaths = nalloc = 0; + /* + * Account for the NUL we'll have to place at the end of this. + */ + len = 1; + readers = NULL; + while ((ent = fts_read(fts)) != NULL) { + size_t plen; + + if (ent->fts_level != 2 || ent->fts_info == FTS_DP) + continue; + + if (ent->fts_info == FTS_ERR || ent->fts_info == FTS_NS) + continue; + + if (S_ISCHR(ent->fts_statp->st_mode) == 0) + continue; + + plen = strlen(ent->fts_path) + 1; + if (UINT32_MAX - len <= plen) { + /* + * I mean, it's true. But I wish I could just give you + * EOVERFLOW. + */ + ret = SCARD_E_INSUFFICIENT_BUFFER; + goto out; + } + + if (npaths == nalloc) { + char **tmp; + + nalloc += 8; + tmp = reallocarray(readers, nalloc, sizeof (char *)); + if (tmp == NULL) { + ret = SCARD_E_NO_MEMORY; + goto out; + } + readers = tmp; + } + readers[npaths] = strdup(ent->fts_path); + npaths++; + len += plen; + } + + if (npaths == 0) { + ret = SCARD_E_NO_READERS_AVAILABLE; + goto out; + } + + ulen = *lenp; + *lenp = len; + if (ulen != SCARD_AUTOALLOCATE) { + if (bufp == NULL) { + ret = SCARD_S_SUCCESS; + goto out; + } + + if (ulen < len) { + ret = SCARD_E_INSUFFICIENT_BUFFER; + goto out; + } + + ubuf = bufp; + } else { + char **bufpp; + if (bufp == NULL) { + ret = SCARD_E_INVALID_PARAMETER; + goto out; + } + + ubuf = malloc(ulen); + if (ubuf == NULL) { + ret = SCARD_E_NO_MEMORY; + goto out; + } + + bufpp = (void *)bufp; + *bufpp = ubuf; + } + ret = SCARD_S_SUCCESS; + + for (off = 0, i = 0; i < npaths; i++) { + size_t slen = strlen(readers[i]) + 1; + bcopy(readers[i], ubuf + off, slen); + off += slen; + VERIFY3U(off, <=, len); + } + VERIFY3U(off, ==, len - 1); + ubuf[off] = '\0'; +out: + for (i = 0; i < npaths; i++) { + free(readers[i]); + } + free(readers); + (void) fts_close(fts); + return (ret); +} + +static LONG +uccid_status_helper(int fd, DWORD prots, uccid_cmd_status_t *ucs) +{ + /* + * Get the status of this slot and find out information about the slot. + * We need to see if there's an ICC present and if it matches the + * current protocol. If not, then we have to fail this. + */ + bzero(ucs, sizeof (uccid_cmd_status_t)); + ucs->ucs_version = UCCID_CURRENT_VERSION; + if (ioctl(fd, UCCID_CMD_STATUS, ucs) != 0) { + return (SCARD_F_UNKNOWN_ERROR); + } + + if ((ucs->ucs_status & UCCID_STATUS_F_CARD_PRESENT) == 0) { + return (SCARD_W_REMOVED_CARD); + } + + if ((ucs->ucs_status & UCCID_STATUS_F_CARD_ACTIVE) == 0) { + return (SCARD_W_UNPOWERED_CARD); + } + + if ((ucs->ucs_status & UCCID_STATUS_F_PARAMS_VALID) == 0) { + return (SCARD_W_UNSUPPORTED_CARD); + } + + if ((ucs->ucs_prot & prots) == 0) { + return (SCARD_E_PROTO_MISMATCH); + } + + return (0); +} + +LONG +SCardConnect(SCARDCONTEXT hdl, LPCSTR reader, DWORD mode, DWORD prots, + LPSCARDHANDLE iccp, LPDWORD protp) +{ + LONG ret; + uccid_cmd_status_t ucs; + pcsc_card_t *card; + + if (reader == NULL) { + return (SCARD_E_UNKNOWN_READER); + } + + if (iccp == NULL || protp == NULL) { + return (SCARD_E_INVALID_PARAMETER); + } + + if (mode != SCARD_SHARE_SHARED) { + return (SCARD_E_INVALID_VALUE); + } + + if ((prots & ~(SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1 | + SCARD_PROTOCOL_RAW | SCARD_PROTOCOL_T15)) != 0) { + return (SCARD_E_INVALID_VALUE); + } + + if ((prots & (SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1)) == 0) { + return (SCARD_E_UNSUPPORTED_FEATURE); + } + + if ((card = malloc(sizeof (*card))) == NULL) { + return (SCARD_E_NO_MEMORY); + } + + if ((card->pcc_fd = open(reader, O_RDWR)) < 0) { + free(card); + switch (errno) { + case ENOENT: + return (SCARD_E_UNKNOWN_READER); + default: + return (SCARD_F_UNKNOWN_ERROR); + } + } + + if ((ret = uccid_status_helper(card->pcc_fd, prots, &ucs)) != 0) + goto cleanup; + + *protp = ucs.ucs_prot; + *iccp = card; + return (SCARD_S_SUCCESS); +cleanup: + (void) close(card->pcc_fd); + free(card); + return (ret); +} + +LONG +SCardDisconnect(SCARDHANDLE arg, DWORD disposition) +{ + pcsc_card_t *card = arg; + + if (arg == NULL) { + return (SCARD_E_INVALID_HANDLE); + } + + if (disposition != SCARD_LEAVE_CARD) { + return (SCARD_E_INVALID_VALUE); + } + + if (close(card->pcc_fd) != 0) { + return (SCARD_F_UNKNOWN_ERROR); + } + + free(card); + return (SCARD_S_SUCCESS); +} + +LONG +SCardBeginTransaction(SCARDHANDLE arg) +{ + uccid_cmd_txn_begin_t txn; + pcsc_card_t *card = arg; + + if (card == NULL) { + return (SCARD_E_INVALID_HANDLE); + } + + /* + * The semantics of pcsc are that this operation does not block, but + * instead fails if we cannot grab it immediately. + */ + bzero(&txn, sizeof (uccid_cmd_txn_begin_t)); + txn.uct_version = UCCID_CURRENT_VERSION; + txn.uct_flags = UCCID_TXN_DONT_BLOCK; + + if (ioctl(card->pcc_fd, UCCID_CMD_TXN_BEGIN, &txn) != 0) { + VERIFY3S(errno, !=, EFAULT); + switch (errno) { + case ENODEV: + return (SCARD_E_READER_UNAVAILABLE); + case EEXIST: + /* + * This is an odd case. It's used to tell us that we + * already have it. For now, just treat it as success. + */ + return (SCARD_S_SUCCESS); + case EBUSY: + return (SCARD_E_SHARING_VIOLATION); + /* + * EINPROGRESS is a weird case. It means that we were trying to + * grab a hold while another instance using the same handle was. + * For now, treat it as an unknown error. + */ + case EINPROGRESS: + case EINTR: + default: + return (SCARD_F_UNKNOWN_ERROR); + } + } + return (SCARD_S_SUCCESS); +} + +LONG +SCardEndTransaction(SCARDHANDLE arg, DWORD state) +{ + uccid_cmd_txn_end_t txn; + pcsc_card_t *card = arg; + + if (card == NULL) { + return (SCARD_E_INVALID_HANDLE); + } + + bzero(&txn, sizeof (uccid_cmd_txn_end_t)); + txn.uct_version = UCCID_CURRENT_VERSION; + + switch (state) { + case SCARD_LEAVE_CARD: + txn.uct_flags = UCCID_TXN_END_RELEASE; + break; + case SCARD_RESET_CARD: + txn.uct_flags = UCCID_TXN_END_RESET; + break; + case SCARD_UNPOWER_CARD: + case SCARD_EJECT_CARD: + default: + return (SCARD_E_INVALID_VALUE); + } + + if (ioctl(card->pcc_fd, UCCID_CMD_TXN_END, &txn) != 0) { + VERIFY3S(errno, !=, EFAULT); + switch (errno) { + case ENODEV: + return (SCARD_E_READER_UNAVAILABLE); + case ENXIO: + return (SCARD_E_SHARING_VIOLATION); + default: + return (SCARD_F_UNKNOWN_ERROR); + } + } + return (SCARD_S_SUCCESS); +} + +LONG +SCardReconnect(SCARDHANDLE arg, DWORD mode, DWORD prots, DWORD init, + LPDWORD protp) +{ + uccid_cmd_status_t ucs; + pcsc_card_t *card = arg; + LONG ret; + + if (card == NULL) { + return (SCARD_E_INVALID_HANDLE); + } + + if (protp == NULL) { + return (SCARD_E_INVALID_PARAMETER); + } + + if (mode != SCARD_SHARE_SHARED) { + return (SCARD_E_INVALID_VALUE); + } + + if ((prots & ~(SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1 | + SCARD_PROTOCOL_RAW | SCARD_PROTOCOL_T15)) != 0) { + return (SCARD_E_INVALID_VALUE); + } + + if ((prots & (SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1)) == 0) { + return (SCARD_E_UNSUPPORTED_FEATURE); + } + + if (init != SCARD_LEAVE_CARD) { + return (SCARD_E_INVALID_VALUE); + } + + if ((ret = uccid_status_helper(card->pcc_fd, prots, &ucs)) != 0) + return (ret); + + *protp = ucs.ucs_prot; + return (SCARD_S_SUCCESS); +} + +LONG +SCardTransmit(SCARDHANDLE arg, const SCARD_IO_REQUEST *sendreq, + LPCBYTE sendbuf, DWORD sendlen, SCARD_IO_REQUEST *recvreq, LPBYTE recvbuf, + LPDWORD recvlenp) +{ + int len; + ssize_t ret; + pcsc_card_t *card = arg; + + if (card == NULL) { + return (SCARD_E_INVALID_HANDLE); + } + + /* + * Ignore sendreq / recvreq. + */ + if (sendbuf == NULL || recvbuf == NULL || recvlenp == NULL) { + return (SCARD_E_INVALID_PARAMETER); + } + + /* + * The CCID write will always consume all data or none. + */ + ret = write(card->pcc_fd, sendbuf, sendlen); + if (ret == -1) { + switch (errno) { + case E2BIG: + return (SCARD_E_INVALID_PARAMETER); + case ENODEV: + return (SCARD_E_READER_UNAVAILABLE); + case EACCES: + case EBUSY: + return (SCARD_E_SHARING_VIOLATION); + case ENXIO: + return (SCARD_W_REMOVED_CARD); + case EFAULT: + return (SCARD_E_INVALID_PARAMETER); + case ENOMEM: + default: + return (SCARD_F_UNKNOWN_ERROR); + } + } + ASSERT3S(ret, ==, sendlen); + + /* + * Now, we should be able to block in read. + */ + ret = read(card->pcc_fd, recvbuf, *recvlenp); + if (ret == -1) { + switch (errno) { + case EINVAL: + case EOVERFLOW: + /* + * This means that we need to update len with the real + * one. + */ + if (ioctl(card->pcc_fd, FIONREAD, &len) != 0) { + return (SCARD_F_UNKNOWN_ERROR); + } + *recvlenp = len; + return (SCARD_E_INSUFFICIENT_BUFFER); + case ENODEV: + return (SCARD_E_READER_UNAVAILABLE); + case EACCES: + case EBUSY: + return (SCARD_E_SHARING_VIOLATION); + case EFAULT: + return (SCARD_E_INVALID_PARAMETER); + case ENODATA: + default: + return (SCARD_F_UNKNOWN_ERROR); + } + } + + *recvlenp = ret; + + return (SCARD_S_SUCCESS); +} diff --git a/usr/src/lib/libpcsc/common/mapfile-vers b/usr/src/lib/libpcsc/common/mapfile-vers new file mode 100644 index 0000000000..5a3786670a --- /dev/null +++ b/usr/src/lib/libpcsc/common/mapfile-vers @@ -0,0 +1,50 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2019, Joyent, Inc. +# + +# +# MAPFILE HEADER START +# +# WARNING: STOP NOW. DO NOT MODIFY THIS FILE. +# Object versioning must comply with the rules detailed in +# +# usr/src/lib/README.mapfiles +# +# You should not be making modifications here until you've read the most current +# copy of that file. If you need help, contact a gatekeeper for guidance. +# +# MAPFILE HEADER END +# + +$mapfile_version 2 + +SYMBOL_VERSION SUNWprivate { + global: + g_rgSCardRawPci; + g_rgSCardT0Pci; + g_rgSCardT1Pci; + SCardEstablishContext; + SCardReleaseContext; + SCardFreeMemory; + SCardListReaders; + SCardConnect; + SCardDisconnect; + SCardBeginTransaction; + SCardEndTransaction; + SCardReconnect; + SCardTransmit; + pcsc_stringify_error; + local: + *; +}; diff --git a/usr/src/lib/libpcsc/common/winscard.h b/usr/src/lib/libpcsc/common/winscard.h new file mode 100644 index 0000000000..bec4960040 --- /dev/null +++ b/usr/src/lib/libpcsc/common/winscard.h @@ -0,0 +1,144 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2019 Joyent, Inc. + */ + +#ifndef _WINSCARD_H +#define _WINSCARD_H + +/* + * This library provides a compatibility interface with programs designed + * against the PC SmartCard Library. This originates from Microsoft and has been + * used on a few different forms over the years by folks. The purpose of this + * library is for compatibility. + * + * At the time of this writing, Microsofts API documentation can be found here: + * https://docs.microsoft.com/en-us/windows/win32/api/winscard/ + * + * New consumers should not use this library and instead should leverage + * ccid(7D) instead. + */ + +#include <stdint.h> +#include <wintypes.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This is a departure from the PCSC system which defines this as a LONG, + * which is the same size on 32bit and 64bit Windows (ILP32 and LLP64). + * We need to use the real native pointer size for the context handle as + * it wouldn't fit into a LONG on our LP64 platform. + */ +typedef void *SCARDCONTEXT; +typedef void **PSCARDCONTEXT; +typedef void **LPSCARDCONTEXT; +typedef void *SCARDHANDLE; +typedef void **PSCARDHANDLE; +typedef void **LPSCARDHANDLE; + +/* + * Conventionally this is supposed to be packed. + */ +#pragma pack(1) +typedef struct { + unsigned long dwProtocol; + unsigned long cbPciLength; +} SCARD_IO_REQUEST, *PSCARD_IO_REQUEST, *LPSCARD_IO_REQUEST; +#pragma pack() + +extern SCARD_IO_REQUEST g_rgSCardT0Pci, g_rgSCardT1Pci, g_rgSCardRawPci; +#define SCARD_PCI_T0 (&g_rgSCardT0Pci) +#define SCARD_PCI_T1 (&g_rgSCardT1Pci) +#define SCARD_PCI_RAW (&g_rgSCardRawPci) + +/* + * Return values and error codes. We strive to use the same error codes as + * Microsoft. + */ +#define SCARD_S_SUCCESS ((LONG)0x00000000) +#define SCARD_F_INTERNAL_ERROR ((LONG)0x80100001) +#define SCARD_E_CANCELLED ((LONG)0x80100002) +#define SCARD_E_INVALID_HANDLE ((LONG)0x80100003) +#define SCARD_E_INVALID_PARAMETER ((LONG)0x80100004) +#define SCARD_E_NO_MEMORY ((LONG)0x80100006) +#define SCARD_E_INSUFFICIENT_BUFFER ((LONG)0x80100008) +#define SCARD_E_UNKNOWN_READER ((LONG)0x80100009) +#define SCARD_E_TIMEOUT ((LONG)0x8010000a) +#define SCARD_E_SHARING_VIOLATION ((LONG)0x8010000b) +#define SCARD_E_NO_SMARTCARD ((LONG)0x8010000c) +#define SCARD_E_UNKNOWN_CARD ((LONG)0x8010000d) +#define SCARD_E_PROTO_MISMATCH ((LONG)0x8010000f) +#define SCARD_E_INVALID_VALUE ((LONG)0x80100011) +#define SCARD_F_COMM_ERROR ((LONG)0x80100013) +#define SCARD_F_UNKNOWN_ERROR ((LONG)0x80100014) +#define SCARD_E_READER_UNAVAILABLE ((LONG)0x80100017) +#define SCARD_E_NO_SERVICE ((LONG)0x8010001D) +#define SCARD_E_UNSUPPORTED_FEATURE ((LONG)0x80100022) +#define SCARD_E_NO_READERS_AVAILABLE ((LONG)0x8010002E) +#define SCARD_W_UNSUPPORTED_CARD ((LONG)0x80100065) +#define SCARD_W_UNPOWERED_CARD ((LONG)0x80100067) +#define SCARD_W_RESET_CARD ((LONG)0x80100068) +#define SCARD_W_REMOVED_CARD ((LONG)0x80100069) + +#define SCARD_SCOPE_USER 0x0000 +#define SCARD_SCOPE_TERMINAL 0x0001 +#define SCARD_SCOPE_SYSTEM 0x0002 +#define SCARD_SCOPE_GLOBAL 0x0003 + +#define SCARD_SHARE_EXCLUSIVE 0x0001 +#define SCARD_SHARE_SHARED 0x0002 +#define SCARD_SHARE_DIRECT 0x0003 + +#define SCARD_PROTOCOL_T0 0x0001 +#define SCARD_PROTOCOL_T1 0x0002 +#define SCARD_PROTOCOL_RAW 0x0004 +#define SCARD_PROTOCOL_T15 0x0008 + +#define SCARD_LEAVE_CARD 0x0000 +#define SCARD_RESET_CARD 0x0001 +#define SCARD_UNPOWER_CARD 0x0002 +#define SCARD_EJECT_CARD 0x0003 + +/* + * This is used to indicate that the framework should allocate memory. + */ +#define SCARD_AUTOALLOCATE UINT32_MAX + +extern LONG SCardEstablishContext(DWORD, LPCVOID, LPCVOID, LPSCARDCONTEXT); +extern LONG SCardReleaseContext(SCARDCONTEXT); + +extern LONG SCardListReaders(SCARDCONTEXT, LPCSTR, LPSTR, LPDWORD); + +extern LONG SCardFreeMemory(SCARDCONTEXT, LPCVOID); + +extern LONG SCardConnect(SCARDCONTEXT, LPCSTR, DWORD, DWORD, LPSCARDHANDLE, + LPDWORD); +extern LONG SCardDisconnect(SCARDHANDLE, DWORD); + +extern LONG SCardBeginTransaction(SCARDHANDLE); +extern LONG SCardEndTransaction(SCARDHANDLE, DWORD); +extern LONG SCardReconnect(SCARDHANDLE, DWORD, DWORD, DWORD, LPDWORD); + +extern LONG SCardTransmit(SCARDHANDLE, const SCARD_IO_REQUEST *, LPCBYTE, + DWORD, SCARD_IO_REQUEST *, LPBYTE, LPDWORD); + +extern const char *pcsc_stringify_error(const LONG); + +#ifdef __cplusplus +} +#endif + +#endif /* _WINSCARD_H */ diff --git a/usr/src/lib/libpcsc/common/wintypes.h b/usr/src/lib/libpcsc/common/wintypes.h new file mode 100644 index 0000000000..9bb50a87cc --- /dev/null +++ b/usr/src/lib/libpcsc/common/wintypes.h @@ -0,0 +1,50 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2019, Joyent, Inc. + */ + +#ifndef _WINTYPES_H +#define _WINTYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * While we don't want to, this expects that we have Win32 style type names. + * Deal with conversions between Win32 and reality. Remember that Windows is an + * ILP32 system, but it is a LLP64 system. + */ + +typedef uint8_t BYTE; +typedef uint8_t *LPBYTE; +typedef const uint8_t *LPCBYTE; +typedef const void *LPCVOID; +typedef uint32_t DWORD; +typedef uint32_t *LPDWORD; +typedef int32_t LONG; +typedef char *LPSTR; +typedef const char *LPCSTR; + +/* + * Include a few deprecated types because folks still use them. + */ +typedef char *LPTSTR; +typedef const char *LPCTSTR; +typedef char *LPCWSTR; + +#ifdef __cplusplus +} +#endif + +#endif /* _WINTYPES_H */ diff --git a/usr/src/lib/libpcsc/i386/Makefile b/usr/src/lib/libpcsc/i386/Makefile new file mode 100644 index 0000000000..e4bd71f624 --- /dev/null +++ b/usr/src/lib/libpcsc/i386/Makefile @@ -0,0 +1,18 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2019 Joyent, Inc. +# + +include ../Makefile.com + +install: all $(ROOTLIBS) $(ROOTLINKS) |