📄 profile.c
字号:
/* * Initialize Cards according to PKCS#15 * * Copyright (C) 2002 Olaf Kirch <okir@lst.de> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <stdio.h>#include <ctype.h>#include <stdarg.h>#include <string.h>#include <limits.h>#ifdef HAVE_STRINGS_H#include <strings.h>#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include <assert.h>#include <stdlib.h>#include <opensc/scconf.h>#include "pkcs15-init.h"#include "profile.h"#define DEF_PRKEY_RSA_ACCESS 0x1D#define DEF_PRKEY_DSA_ACCESS 0x12#define DEF_PUBKEY_ACCESS 0x12/* * Parser state */struct state { struct state * frame; const char * filename; struct sc_profile * profile; struct file_info * file; struct pin_info * pin; struct auth_info * key;};struct command { const char * name; int min_args, max_args; int (*func)(struct state *, int, char **);};struct block { const char * name; int (*handler)(struct state *, struct block *, const char *, scconf_block *); struct command * cmd_info; struct block * blk_info;};struct map { const char * name; unsigned int val;};static struct map aclNames[] = { { "NONE", SC_AC_NONE }, { "NEVER", SC_AC_NEVER }, { "CHV", SC_AC_CHV }, { "TERM", SC_AC_TERM }, { "PRO", SC_AC_PRO }, { "AUT", SC_AC_AUT }, { "KEY", SC_AC_AUT }, { 0, 0 }};static struct map fileOpNames[] = { { "SELECT", SC_AC_OP_SELECT }, { "LOCK", SC_AC_OP_LOCK }, { "DELETE", SC_AC_OP_DELETE }, { "CREATE", SC_AC_OP_CREATE }, { "REHABILITATE",SC_AC_OP_REHABILITATE }, { "INVALIDATE", SC_AC_OP_INVALIDATE }, { "FILES", SC_AC_OP_LIST_FILES }, { "READ", SC_AC_OP_READ }, { "UPDATE", SC_AC_OP_UPDATE }, { "WRITE", SC_AC_OP_WRITE }, { "ERASE", SC_AC_OP_ERASE }, { "CRYPTO", SC_AC_OP_CRYPTO }, { 0, 0 }};static struct map fileTypeNames[] = { { "EF", SC_FILE_TYPE_WORKING_EF }, { "INTERNAL-EF",SC_FILE_TYPE_INTERNAL_EF }, { "DF", SC_FILE_TYPE_DF }, { 0, 0 }};static struct map fileStructureNames[] = { { "TRANSPARENT", SC_FILE_EF_TRANSPARENT }, { "LINEAR-FIXED", SC_FILE_EF_LINEAR_FIXED }, { "LINEAR-FIXED-TLV", SC_FILE_EF_LINEAR_FIXED_TLV }, { "LINEAR-VARIABLE", SC_FILE_EF_LINEAR_VARIABLE }, { "LINEAR-VARIABLE-TLV",SC_FILE_EF_LINEAR_VARIABLE_TLV }, { "CYCLIC", SC_FILE_EF_CYCLIC }, { "CYCLIC-TLV", SC_FILE_EF_CYCLIC_TLV }, { 0, 0 }};static struct map pkcs15DfNames[] = { { "PRKDF", SC_PKCS15_PRKDF }, { "PUKDF", SC_PKCS15_PUKDF }, { "PUKDF-TRUSTED", SC_PKCS15_PUKDF_TRUSTED }, { "SKDF", SC_PKCS15_SKDF }, { "CDF", SC_PKCS15_CDF }, { "CDF-TRUSTED", SC_PKCS15_CDF_TRUSTED }, { "CDF-USEFUL", SC_PKCS15_CDF_USEFUL }, { "DODF", SC_PKCS15_DODF }, { "AODF", SC_PKCS15_AODF }, { 0, 0 }};static struct map pinTypeNames[] = { { "BCD", 0 }, { "ascii-numeric", 1 }, { "utf8", 2 }, { "half-nibble-bcd", 3 }, { "iso9564-1", 4 }, { 0, 0 }};static struct map pinIdNames[] = { { "pin", SC_PKCS15INIT_USER_PIN }, { "puk", SC_PKCS15INIT_USER_PUK }, { "user-pin", SC_PKCS15INIT_USER_PIN }, { "user-puk", SC_PKCS15INIT_USER_PUK }, { "sopin", SC_PKCS15INIT_SO_PIN }, { "sopuk", SC_PKCS15INIT_SO_PUK }, { "so-pin", SC_PKCS15INIT_SO_PIN }, { "so-puk", SC_PKCS15INIT_SO_PUK }, { 0, 0 }};static struct map pinFlagNames[] = { { "case-sensitive", 0x0001 }, { "local", 0x0002 }, { "change-disabled", 0x0004 }, { "unblock-disabled", 0x0008 }, { "initialized", 0x0010 }, { "needs-padding", 0x0020 }, { "unblockingPin", 0x0040 }, { "soPin", 0x0080 }, { "disable-allowed", 0x0100 }, { "integrity-protected", 0x0200 }, { "confidentiality-protected", 0x0400 }, { "exchangeRefData", 0x0800 }, { 0, 0 }};static struct { const char * name; struct map * addr;} mapNames[] = { { "file ACL", aclNames }, { "file operation", fileOpNames }, { "file type", fileTypeNames }, { "file structure", fileStructureNames}, { "PKCS#15 file name", pkcs15DfNames }, { "pin encoding", pinTypeNames }, { "pin name", pinIdNames }, { "pin flag", pinFlagNames }, { NULL, NULL }};typedef struct pin_info pin_info;typedef struct file_info file_info;typedef struct auth_info auth_info;static const char * sc_profile_locate(const char *);static int process_conf(struct sc_profile *, scconf_context *);static int process_block(struct state *, struct block *, const char *, scconf_block *);static void init_state(struct state *, struct state *);static int get_authid(struct state *, const char *, unsigned int *, unsigned int *);static int get_uint(struct state *, const char *, unsigned int *);static int map_str2int(struct state *, const char *, unsigned int *, struct map *);static int setstr(char **strp, const char *value);static void parse_error(struct state *, const char *, ...);static file_info * sc_profile_find_file(struct sc_profile *, const char *);static file_info * sc_profile_find_file_by_path( struct sc_profile *, const struct sc_path *);static pin_info * new_pin(struct sc_profile *, unsigned int);static file_info * new_file(struct state *, const char *, unsigned int);static auth_info * new_key(struct sc_profile *, unsigned int, unsigned int);static void set_pin_defaults(struct sc_profile *, struct pin_info *);static struct sc_file *init_file(unsigned int type){ struct sc_file *file; unsigned int op; file = sc_file_new(); for (op = 0; op < SC_MAX_AC_OPS; op++) { sc_file_add_acl_entry(file, op, SC_AC_NONE, 0); } file->type = type; file->status = SC_FILE_STATUS_ACTIVATED; file->ef_structure = SC_FILE_EF_TRANSPARENT; return file;}/* * Initialize profile */struct sc_profile *sc_profile_new(){ struct sc_pkcs15_card *p15card; struct sc_profile *pro; pro = (struct sc_profile *) calloc(1, sizeof(*pro)); pro->p15_card = p15card = sc_pkcs15_card_new(); /* Set up EF(TokenInfo) and EF(ODF) */ p15card->file_tokeninfo = init_file(SC_FILE_TYPE_WORKING_EF); p15card->file_odf = init_file(SC_FILE_TYPE_WORKING_EF); if (p15card) { p15card->label = strdup("OpenSC Card"); p15card->manufacturer_id = strdup("OpenSC Project"); p15card->serial_number = strdup("0000"); p15card->flags = SC_PKCS15_CARD_FLAG_EID_COMPLIANT; p15card->version = 1; } /* Assume card does RSA natively, but no DSA */ pro->rsa_access_flags = DEF_PRKEY_RSA_ACCESS; pro->dsa_access_flags = DEF_PRKEY_DSA_ACCESS; pro->pin_encoding = 0x01; pro->pin_minlen = 4; pro->pin_maxlen = 8; return pro;}intsc_profile_load(struct sc_profile *profile, const char *filename){ scconf_context *conf; int res = 0; if (!(filename = sc_profile_locate(filename))) return SC_ERROR_FILE_NOT_FOUND; conf = scconf_new(filename); res = scconf_parse(conf); if (res < 0) return SC_ERROR_FILE_NOT_FOUND; if (res == 0) return SC_ERROR_SYNTAX_ERROR; res = process_conf(profile, conf); scconf_free(conf); return res;}intsc_profile_finish(struct sc_profile *profile){ struct file_info *fi; struct pin_info *pi; const char *reason, *name; reason = "Profile doesn't define a MF"; if (!(profile->mf_info = sc_profile_find_file(profile, "MF"))) goto whine; reason = "Profile doesn't define a PKCS15-AppDF"; if (!(profile->df_info = sc_profile_find_file(profile, "PKCS15-AppDF"))) goto whine; profile->p15_card->file_app = profile->df_info->file; profile->df_info->dont_free = 1; for (pi = profile->pin_list; pi; pi = pi->next) { set_pin_defaults(profile, pi); if (!(name = pi->file_name)) continue; if (!(fi = sc_profile_find_file(profile, name))) { if (profile->cbs) profile->cbs->error( "unknown PIN file \"%s\"\n", name); return SC_ERROR_INCONSISTENT_PROFILE; } pi->file = fi; } return 0;whine: if (profile->cbs) profile->cbs->error("%s\n", reason); return SC_ERROR_INCONSISTENT_PROFILE;}voidsc_profile_free(struct sc_profile *profile){ struct file_info *fi; struct auth_info *ai; struct pin_info *pi; while ((fi = profile->ef_list) != NULL) { profile->ef_list = fi->next; if (fi->dont_free == 0) sc_file_free(fi->file); free(fi->ident); free(fi); } while ((ai = profile->auth_list) != NULL) { profile->auth_list = ai->next; free(ai); } while ((pi = profile->pin_list) != NULL) { if (pi->file_name) free(pi->file_name); profile->pin_list = pi->next; free(pi); } if (profile->p15_card) sc_pkcs15_card_free(profile->p15_card); memset(profile, 0, sizeof(*profile)); free(profile);}static const char *sc_profile_locate(const char *name){ static char path[1024]; char profile_dir[PATH_MAX]; /* append ".profile" unless already in the name */ if (strstr(name, SC_PKCS15_PROFILE_SUFFIX)) { snprintf(path, sizeof(path), "%s", name); } else { snprintf(path, sizeof(path), "%s.%s", name, SC_PKCS15_PROFILE_SUFFIX); } /* Unchanged name? */ if (access(path, R_OK) == 0) return path; /* If it's got slashes, don't mess with it any further */ if (strchr(path, '/')) return path;#ifndef _WIN32 strncpy(profile_dir, SC_PKCS15_PROFILE_DIRECTORY, sizeof(profile_dir));#else if (!strncmp(SC_PKCS15_PROFILE_DIRECTORY, "%windir%", 8)) { GetWindowsDirectory(profile_dir, sizeof(profile_dir)); strncat(profile_dir, SC_PKCS15_PROFILE_DIRECTORY + 8, sizeof(profile_dir) - strlen(profile_dir)); } else strncpy(profile_dir, SC_PKCS15_PROFILE_DIRECTORY, sizeof(profile_dir));#endif /* Try directory */ /* append ".profile" unless already in the name */ if (strstr(name, SC_PKCS15_PROFILE_SUFFIX)) { snprintf(path, sizeof(path), "%s/%s", profile_dir, name); } else { snprintf(path, sizeof(path), "%s/%s.%s", profile_dir, name, SC_PKCS15_PROFILE_SUFFIX); } if (access(path, R_OK) == 0) return path; /* Unchanged name? */ if (access(name, R_OK) == 0) return name; return NULL;}voidsc_profile_set_pin_info(struct sc_profile *profile, unsigned int id, const struct sc_pkcs15_pin_info *info){ struct pin_info *pi; pi = new_pin(profile, id); pi->pin = *info;}voidsc_profile_get_pin_info(struct sc_profile *profile, unsigned int id, struct sc_pkcs15_pin_info *info){ struct pin_info *pi; pi = new_pin(profile, id); *info = pi->pin;}intsc_profile_get_pin_id(struct sc_profile *profile, unsigned int reference, unsigned int *id){ struct pin_info *pi; for (pi = profile->pin_list; pi; pi = pi->next) { if (pi->pin.reference == reference) { *id = pi->id; return 0; } } return SC_ERROR_OBJECT_NOT_FOUND;}intsc_profile_get_file(struct sc_profile *profile, const char *name, struct sc_file **ret){ struct file_info *fi; if ((fi = sc_profile_find_file(profile, name)) == NULL) return SC_ERROR_FILE_NOT_FOUND; sc_file_dup(ret, fi->file); return 0;}intsc_profile_get_path(struct sc_profile *profile, const char *name, struct sc_path *ret){ struct file_info *fi; if ((fi = sc_profile_find_file(profile, name)) == NULL) return SC_ERROR_FILE_NOT_FOUND; *ret = fi->file->path; return 0;}intsc_profile_get_file_by_path(struct sc_profile *profile, const struct sc_path *path, struct sc_file **ret){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -