Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 321 lines (277 sloc) 8.093 kb
839b33a @fredrikt Add ykpamcfg - C/R setup command line utility.
fredrikt authored
1 /*
43cd3b4 @jas4711 Update copyright years.
jas4711 authored
2 * Copyright (c) 2011-2014 Yubico AB
839b33a @fredrikt Add ykpamcfg - C/R setup command line utility.
fredrikt authored
3 * All rights reserved.
4 *
5 * Author : Fredrik Thulin <fredrik@yubico.com>
6 *
7 * Based on ykchalresp.c from yubikey-personalization.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are
11 * met:
12 *
13 * * Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * * Redistributions in binary form must reproduce the above
17 * copyright notice, this list of conditions and the following
18 * disclaimer in the documentation and/or other materials provided
19 * with the distribution.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <stdio.h>
35 #include <unistd.h>
36 #include <sys/types.h>
37 #include <pwd.h>
38 #include <string.h>
39 #include <errno.h>
1eff1ad @TomAtYubico New feature, create directory in the user home.
TomAtYubico authored
40 #include <sys/stat.h>
41 #include <sys/types.h>
839b33a @fredrikt Add ykpamcfg - C/R setup command line utility.
fredrikt authored
42
43 #include <ykpers.h>
44
45 #undef DEBUG_PAM
46 #include "util.h"
47
48 #define ACTION_ADD_HMAC_CHALRESP "add_hmac_chalresp"
e2f9a7b @klali don't write to a constant pointer
klali authored
49 #define ACTION_MAX_LEN 1024
839b33a @fredrikt Add ykpamcfg - C/R setup command line utility.
fredrikt authored
50
51 const char *usage =
52 "Usage: ykpamcfg [options]\n"
53 "\n"
54 "Options :\n"
55 "\n"
56 "\t-1 Send challenge to slot 1. This is the default.\n"
57 "\t-2 Send challenge to slot 2.\n"
1d62f8d @fredrikt whitespace
fredrikt authored
58 "\t-A action What to do.\n"
ad27af3 @TomAtYubico Added option to specify a path for ykpamcfg.
TomAtYubico authored
59 "\t-p path Specify an output path for the challenge file.\n"
ba4e566 @klali add -i switch for setting iterations with ykpamcfg
klali authored
60 "\t-i iters Number of iterations to use for pbkdf2 (defaults to 10000)\n"
839b33a @fredrikt Add ykpamcfg - C/R setup command line utility.
fredrikt authored
61 "\n"
ec730d7 @klali add -V for version to ykpamcfg and exit earlier
klali authored
62 "\t-v Increase verbosity\n"
63 "\t-V Show version and exit\n"
64 "\t-h Show help (this text) and exit\n"
839b33a @fredrikt Add ykpamcfg - C/R setup command line utility.
fredrikt authored
65 "\n"
66 "Actions :\n"
67 "\n"
68 "\t" ACTION_ADD_HMAC_CHALRESP "\tAdds a challenge-response state file for a connected YubiKey (default)\n"
69 "\n"
70 "\n"
71 ;
ec730d7 @klali add -V for version to ykpamcfg and exit earlier
klali authored
72 const char *optstring = "12A:p:i:vVh";
839b33a @fredrikt Add ykpamcfg - C/R setup command line utility.
fredrikt authored
73
74 static void
307c88d @klali fix warnings
klali authored
75 report_yk_error(void)
839b33a @fredrikt Add ykpamcfg - C/R setup command line utility.
fredrikt authored
76 {
77 if (ykp_errno)
78 fprintf(stderr, "Yubikey personalization error: %s\n",
79 ykp_strerror(ykp_errno));
80 if (yk_errno) {
81 if (yk_errno == YK_EUSBERR) {
82 fprintf(stderr, "USB error: %s\n",
83 yk_usb_strerror());
84 } else {
85 fprintf(stderr, "Yubikey core error: %s\n",
86 yk_strerror(yk_errno));
87 }
88 }
89 }
90
307c88d @klali fix warnings
klali authored
91 static int
839b33a @fredrikt Add ykpamcfg - C/R setup command line utility.
fredrikt authored
92 parse_args(int argc, char **argv,
93 int *slot, bool *verbose,
ad27af3 @TomAtYubico Added option to specify a path for ykpamcfg.
TomAtYubico authored
94 char **action, char **output_dir,
ec730d7 @klali add -V for version to ykpamcfg and exit earlier
klali authored
95 unsigned int *iterations)
839b33a @fredrikt Add ykpamcfg - C/R setup command line utility.
fredrikt authored
96 {
8930cca @fredrikt parse_args: getopt() return value is int.
fredrikt authored
97 int c;
839b33a @fredrikt Add ykpamcfg - C/R setup command line utility.
fredrikt authored
98
99 while((c = getopt(argc, argv, optstring)) != -1) {
100 switch (c) {
101 case '1':
102 *slot = 1;
103 break;
104 case '2':
105 *slot = 2;
106 break;
107 case 'A':
e2f9a7b @klali don't write to a constant pointer
klali authored
108 strncpy(*action, optarg, ACTION_MAX_LEN);
839b33a @fredrikt Add ykpamcfg - C/R setup command line utility.
fredrikt authored
109 break;
ad27af3 @TomAtYubico Added option to specify a path for ykpamcfg.
TomAtYubico authored
110 case 'p':
111 *output_dir = optarg;
112 break;
ba4e566 @klali add -i switch for setting iterations with ykpamcfg
klali authored
113 case 'i':
ec730d7 @klali add -V for version to ykpamcfg and exit earlier
klali authored
114 {
115 char *endptr;
116 *iterations = strtoul(optarg, &endptr, 10);
117 if(*endptr != '\0') {
118 fprintf(stderr, "iterations must be numeric, %s isn't.\n", optarg);
119 exit(1);
120 }
ba4e566 @klali add -i switch for setting iterations with ykpamcfg
klali authored
121 }
122 break;
839b33a @fredrikt Add ykpamcfg - C/R setup command line utility.
fredrikt authored
123 case 'v':
124 *verbose = true;
125 break;
ec730d7 @klali add -V for version to ykpamcfg and exit earlier
klali authored
126 case 'V':
127 printf("%s\n", VERSION);
128 exit(0);
839b33a @fredrikt Add ykpamcfg - C/R setup command line utility.
fredrikt authored
129 case 'h':
130 default:
131 fputs(usage, stderr);
ec730d7 @klali add -V for version to ykpamcfg and exit earlier
klali authored
132 exit(0);
839b33a @fredrikt Add ykpamcfg - C/R setup command line utility.
fredrikt authored
133 }
134 }
1d62f8d @fredrikt whitespace
fredrikt authored
135
839b33a @fredrikt Add ykpamcfg - C/R setup command line utility.
fredrikt authored
136 return 1;
137 }
138
307c88d @klali fix warnings
klali authored
139 static int
ba4e566 @klali add -i switch for setting iterations with ykpamcfg
klali authored
140 do_add_hmac_chalresp(YK_KEY *yk, uint8_t slot, bool verbose, char *output_dir, unsigned int iterations, int *exit_code)
839b33a @fredrikt Add ykpamcfg - C/R setup command line utility.
fredrikt authored
141 {
4ce5983 @fredrikt Further pointer signedness fixes.
fredrikt authored
142 char buf[CR_RESPONSE_SIZE + 16];
839b33a @fredrikt Add ykpamcfg - C/R setup command line utility.
fredrikt authored
143 CR_STATE state;
144 int ret = 0;
145 unsigned int response_len;
146 char *fn;
147 struct passwd *p;
148 FILE *f = NULL;
149
ba4e566 @klali add -i switch for setting iterations with ykpamcfg
klali authored
150 state.iterations = iterations;
839b33a @fredrikt Add ykpamcfg - C/R setup command line utility.
fredrikt authored
151 state.slot = slot;
152 *exit_code = 1;
153
154 p = getpwuid (getuid ());
1eff1ad @TomAtYubico New feature, create directory in the user home.
TomAtYubico authored
155
839b33a @fredrikt Add ykpamcfg - C/R setup command line utility.
fredrikt authored
156 if (! p) {
157 fprintf (stderr, "Who am I???");
158 goto out;
159 }
160
1eff1ad @TomAtYubico New feature, create directory in the user home.
TomAtYubico authored
161 /*
162 * Create default output directory for the user
163 */
164
165 if (!output_dir){
307c88d @klali fix warnings
klali authored
166 struct stat st;
1eff1ad @TomAtYubico New feature, create directory in the user home.
TomAtYubico authored
167 char fullpath[256];
168 snprintf(fullpath, 256,"%s/.yubico",p->pw_dir);
169
170 //check if directory exists
171 if (stat(fullpath,&st)!=0 ){
172 if(mkdir(fullpath, S_IRWXU)==-1){
173 fprintf(stderr, "Failed creating directory '%s' :%s\n",
174 fullpath, strerror(errno));
175 }
176 if(verbose){
177 printf("Directory %s created successfully.\n", fullpath);
178 }
179 }
180 else{
181 if(!S_ISDIR(st.st_mode)){
182 fprintf(stderr, "Destination %s already exist and is not a directory.\n",
183 fullpath);
184 goto out;
185 }
186 }
187 }
188
839b33a @fredrikt Add ykpamcfg - C/R setup command line utility.
fredrikt authored
189 if (! get_user_challenge_file(yk, output_dir, p->pw_name, &fn)) {
190 fprintf (stderr, "Failed getting chalresp state filename\n");
191 goto out;
192 }
193
194 if (generate_random(state.challenge, CR_CHALLENGE_SIZE)) {
195 fprintf (stderr, "FAILED getting %i bytes of random data\n", CR_CHALLENGE_SIZE);
196 goto out;
197 }
198 state.challenge_len = CR_CHALLENGE_SIZE;
199
200 if (! challenge_response(yk, state.slot, state.challenge, CR_CHALLENGE_SIZE,
eb78d48 @klali refactor to use chalresp function from ykpers
klali authored
201 true, true, verbose,
839b33a @fredrikt Add ykpamcfg - C/R setup command line utility.
fredrikt authored
202 buf, sizeof(buf), &response_len))
203 goto out;
204
6db8c64 @klali add check that two challenges get different responses
klali authored
205 /* Make sure we get different responses for different challenges
206 There is a firmware bug in YubiKey 2.2 that makes it issue same
207 response for all challenges unless HMAC_LT64 is set. */
208 {
209 char buf2[CR_RESPONSE_SIZE + 16];
210 char challenge[CR_CHALLENGE_SIZE];
211
212 if (generate_random(challenge, CR_CHALLENGE_SIZE)) {
213 fprintf (stderr, "FAILED getting %i bytes of random data\n", CR_CHALLENGE_SIZE);
214 goto out;
215 }
216 if (! challenge_response(yk, state.slot, challenge, CR_CHALLENGE_SIZE,
eb78d48 @klali refactor to use chalresp function from ykpers
klali authored
217 true, true, verbose,
6db8c64 @klali add check that two challenges get different responses
klali authored
218 buf2, sizeof(buf2), &response_len))
219 goto out;
220
221 if (memcmp(buf, buf2, response_len) == 0) {
222 fprintf (stderr, "FAILED YubiKey is outputting the same response for different challenges."
223 "Make sure you configure the key with the option HMAC_LT64.\n");
224 goto out;
225 }
226 }
227
839b33a @fredrikt Add ykpamcfg - C/R setup command line utility.
fredrikt authored
228 if (response_len > sizeof (state.response)) {
fb6281f @fredrikt Fix clang indicated printf format warnings.
fredrikt authored
229 fprintf (stderr, "Got too long response ??? (%u/%lu)", response_len, (unsigned long) sizeof(state.response));
839b33a @fredrikt Add ykpamcfg - C/R setup command line utility.
fredrikt authored
230 goto out;
231 }
232 memcpy (state.response, buf, response_len);
233 state.response_len = response_len;
234
235 f = fopen (fn, "w");
236 if (! f) {
237 fprintf (stderr, "Failed opening '%s' for writing : %s\n", fn, strerror (errno));
238 goto out;
239 }
240
241 if (! write_chalresp_state (f, &state))
242 goto out;
243
244 printf ("Stored initial challenge and expected response in '%s'.\n", fn);
245
246 *exit_code = 0;
247 ret = 1;
248
249 out:
250 if (f)
251 fclose (f);
252
253 return ret;
254 }
255
256 int
257 main(int argc, char **argv)
258 {
259 YK_KEY *yk = NULL;
260 bool error = true;
261 int exit_code = 0;
262
263 /* Options */
264 bool verbose = false;
e2f9a7b @klali don't write to a constant pointer
klali authored
265 char action[ACTION_MAX_LEN];
266 char *ptr = action;
ad27af3 @TomAtYubico Added option to specify a path for ykpamcfg.
TomAtYubico authored
267 char *output_dir = NULL;
839b33a @fredrikt Add ykpamcfg - C/R setup command line utility.
fredrikt authored
268 int slot = 1;
ba4e566 @klali add -i switch for setting iterations with ykpamcfg
klali authored
269 unsigned int iterations = CR_DEFAULT_ITERATIONS;
839b33a @fredrikt Add ykpamcfg - C/R setup command line utility.
fredrikt authored
270
271 ykp_errno = 0;
272 yk_errno = 0;
273
e2f9a7b @klali don't write to a constant pointer
klali authored
274 strcpy (action, ACTION_ADD_HMAC_CHALRESP);
275
839b33a @fredrikt Add ykpamcfg - C/R setup command line utility.
fredrikt authored
276 if (! parse_args(argc, argv,
277 &slot, &verbose,
e2f9a7b @klali don't write to a constant pointer
klali authored
278 &ptr, &output_dir,
ec730d7 @klali add -V for version to ykpamcfg and exit earlier
klali authored
279 &iterations))
839b33a @fredrikt Add ykpamcfg - C/R setup command line utility.
fredrikt authored
280 goto err;
281
282 exit_code = 1;
283
e2f9a7b @klali don't write to a constant pointer
klali authored
284 if (! strncmp(action, ACTION_ADD_HMAC_CHALRESP, ACTION_MAX_LEN)) {
839b33a @fredrikt Add ykpamcfg - C/R setup command line utility.
fredrikt authored
285 /*
286 * Set up challenge-response login authentication
287 */
288 if (! init_yubikey (&yk))
289 goto err;
290
291 if (! check_firmware_version(yk, verbose, false))
1eff1ad @TomAtYubico New feature, create directory in the user home.
TomAtYubico authored
292 goto err;
839b33a @fredrikt Add ykpamcfg - C/R setup command line utility.
fredrikt authored
293
ba4e566 @klali add -i switch for setting iterations with ykpamcfg
klali authored
294 if (! do_add_hmac_chalresp (yk, slot, verbose, output_dir, iterations, &exit_code))
839b33a @fredrikt Add ykpamcfg - C/R setup command line utility.
fredrikt authored
295 goto err;
296 } else {
297 fprintf (stderr, "Unknown action '%s'\n", action);
298 goto err;
299 }
300
301 exit_code = 0;
302 error = false;
303
304 err:
305 if (error || exit_code != 0) {
306 report_yk_error ();
307 }
308
309 if (yk && !yk_close_key (yk)) {
310 report_yk_error ();
311 exit_code = 2;
312 }
313
314 if (!yk_release ()) {
315 report_yk_error ();
316 exit_code = 2;
317 }
318
319 exit (exit_code);
320 }
Something went wrong with that request. Please try again.