1 /* -*- mode: c; c-file-style:"stroustrup"; -*- */
2 
3 /*
4  * Copyright (c) 2018 Mastercard
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *   http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #include <config.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include "pkcs11lib.h"
25 
26 #ifdef _WIN32
27 #include <openssl/applink.c>
28 #endif
29 
30 #define COMMAND_SUMMARY \
31     "Copy PKCS#11 token object with a new label.\n\n"
32 
33 /* prototypes */
34 void print_usage(char *);
35 void print_version_info(char *progname);
36 int main( int argc, char **argv);
37 
38 
print_usage(char * progname)39 void print_usage(char *progname)
40 {
41     fprintf( stderr,
42 	     "USAGE: %s OPTIONS SOURCE DESTINATION\n"
43 	     "\n"
44 	     COMMAND_SUMMARY
45 	     "OPTIONS:\n"
46 	     "* -l <pkcs#11 library path> : path to PKCS#11 library\n"
47 	     "  -m <NSS config dir> ( e.g. '.' or 'sql:.' ) : NSS db directory \n"
48 	     "  -s <slot number>\n"
49 	     "  -t <token label> : if present, -s option is ignored\n"
50 	     "  -p <token PIN> | :::exec:<command> | :::nologin\n"
51 	     "  -S : login with SO privilege\n"
52 	     "  -y : force positive answer (non-interactive)\n"
53 	     "  -v : verbose\n"
54 	     "  -h : print usage information\n"
55 	     "  -V : print version information\n"
56 	     "|\n"
57 	     "+-> arguments marked with an asterix(*) are mandatory\n"
58              "|   (except if environment variable sets the value)\n"
59 	     "+-> arguments marked with a plus sign(+) can be repeated\n"
60 	     "\n"
61 	     "ARGUMENTS:\n"
62 	     " SOURCE        : source object label to move\n"
63 	     "                 can be prefixed with cert/, prvk/, pubk/ or seck/)\n"
64 	     "                 if no prefix, objects from all classes sharing the\n"
65 	     "                 same label are moved\n"
66 	     " DESTINATION   : target label\n"
67 	     "\n"
68              " ENVIRONMENT VARIABLES:\n"
69 	     "    PKCS11LIB         : path to PKCS#11 library,\n"
70              "                        overriden by option -l\n"
71 	     "    PKCS11NSSDIR      : NSS configuration directory directive,\n"
72              "                        overriden by option -m\n"
73 	     "    PKCS11SLOT        : token slot (integer)\n"
74 	     "                        overriden by PKCS11TOKENLABEL,\n"
75 	     "                        options -t or -s\n"
76 	     "    PKCS11TOKENLABEL  : token label\n"
77 	     "                        overriden by options -t or -s\n"
78 	     "    PKCS11PASSWORD    : password\n"
79              "                        overriden by option -p\n"
80 	     "\n"
81 	     , progname );
82 
83     exit( RC_ERROR_USAGE );
84 }
85 
main(int argc,char ** argv)86 int main( int argc, char ** argv )
87 {
88     extern char *optarg;
89     extern int optind, optopt;
90     int argnum = 0;
91     int errflag = 0;
92     char * library = NULL;
93     char * nsscfgdir = NULL;
94     char * password = NULL;
95     char * slotenv = NULL;
96     int slot = -1;
97     int interactive = 1;
98     int ask_confirm = 1;
99     char * tokenlabel = NULL;
100     int so=0;
101     int verbose=0;
102 
103     pkcs11Context * p11Context = NULL;
104     func_rc retcode = rc_error_usage;
105 
106     library = getenv("PKCS11LIB");
107     nsscfgdir = getenv("PKCS11NSSDIR");
108     tokenlabel = getenv("PKCS11TOKENLABEL");
109     if(tokenlabel==NULL) {
110 	slotenv = getenv("PKCS11SLOT");
111 	if (slotenv!=NULL) {
112 	    slot=atoi(slotenv);
113 	}
114     }
115     password = getenv("PKCS11PASSWORD");
116 
117     /* if a slot or a token is given, interactive is null */
118     if(slotenv!=NULL || tokenlabel!=NULL) {
119 	interactive=0;
120     }
121 
122     /* get the command-line arguments */
123     while ( ( argnum = getopt( argc, argv, "l:m:p:s:t:yvShV)" ) ) != -1 )
124     {
125 	switch ( argnum )
126 	{
127 	case 'l' :
128 	    library =  optarg;
129 	    break;
130 
131 	case 'm':
132 	    nsscfgdir = optarg;
133 	    break;
134 
135 	case 'p' :
136 	    password = optarg;
137 	    break;
138 
139 	case 's':
140 	    slot = atoi(optarg);
141 	    tokenlabel = NULL;
142 	    interactive = 0;
143 	    break;
144 
145 	case 't':
146 	    tokenlabel = optarg;
147 	    slot = -1;
148 	    interactive = 0;
149 	    break;
150 
151 	case 'y':
152 	    ask_confirm = 0;
153 	    break;
154 
155 	case 'v':
156 	    verbose = 1;
157 	    break;
158 
159 	case 'S':
160 	    so=1;
161 	  break;
162 
163 	case 'h':
164 	    print_usage(argv[0]);
165 	    break;
166 
167 	case 'V':
168 	    print_version_info(argv[0]);
169 	    break;
170 
171 	default:
172 	    errflag++;
173 	    break;
174 	}
175     }
176 
177     if ( errflag ) {
178 	fprintf(stderr, "Try `%s -h' for more information.\n", argv[0]);
179 	goto err;
180     }
181 
182 
183     if ( library == NULL || optind!=argc-2 ) {
184 	fprintf( stderr, "At least one required option or argument is wrong or missing.\n"
185 		 "Try `%s -h' for more information.\n", argv[0]);
186 	goto err;
187     }
188 
189     if((p11Context = pkcs11_newContext( library, nsscfgdir ))==NULL) {
190       goto err;
191     }
192 
193     /* validate the given provider library exists and can be opened */
194     if (( retcode = pkcs11_initialize( p11Context ) ) != CKR_OK ) {
195       goto err;
196     }
197 
198     retcode = pkcs11_open_session( p11Context, slot, tokenlabel, password, so, interactive);
199 
200     if ( retcode == rc_ok )
201     {
202 	pkcs11_cp_objects(p11Context, argv[optind], argv[optind+1], ask_confirm, verbose);
203 
204 	pkcs11_close_session( p11Context );
205     }
206     pkcs11_finalize( p11Context );
207 
208     /* free allocated memory */
209  err:
210     pkcs11_freeContext(p11Context);
211 
212     return retcode;
213 }
214