aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--src/otputil.c140
-rw-r--r--src/otputil.h38
-rw-r--r--src/widget-hotp.c2
-rw-r--r--src/widget-otp.c322
-rw-r--r--src/widget-skey.c252
-rw-r--r--src/widget-totp.c2
7 files changed, 730 insertions, 28 deletions
diff --git a/Makefile.am b/Makefile.am
index 32bcbfc..cc1aeb6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -220,6 +220,8 @@ src_otputil_LDADD = $(AM_LIBS) $(noinst_LIBRARIES) $(lib_LTLIBRARIES)
220src_otputil_SOURCES = src/otputil.c \ 220src_otputil_SOURCES = src/otputil.c \
221 src/otputil.h \ 221 src/otputil.h \
222 src/widget-hotp.c \ 222 src/widget-hotp.c \
223 src/widget-otp.c \
224 src/widget-skey.c \
223 src/widget-totp.c 225 src/widget-totp.c
224 226
225 227
diff --git a/src/otputil.c b/src/otputil.c
index 6c32b50..9524b63 100644
--- a/src/otputil.c
+++ b/src/otputil.c
@@ -116,7 +116,7 @@ otputil_widget_lookup(
116//--------------------------// 116//--------------------------//
117#pragma mark widgets prototypes 117#pragma mark widgets prototypes
118 118
119static int 119extern int
120otputil_widget_debug( 120otputil_widget_debug(
121 otputil_config_t * cnf ); 121 otputil_config_t * cnf );
122 122
@@ -146,7 +146,7 @@ static otputil_widget_t otputil_widget_map[] =
146 { .name = "debug", 146 { .name = "debug",
147 .desc = NULL, 147 .desc = NULL,
148 .usage = NULL, 148 .usage = NULL,
149 .short_opt = "0123456789abc:d:efghijk:lm:nopqrst:uvwx:yzABCDEFGHIJKLMNOPQRST:UVWXYZ", 149 .short_opt = "0123456789abc:d:efghijk:lm:nopqrs:t:uvwx:yzABCDEFGHIJKLMNOP:QRST:UVWXYZ",
150 .arg_min = 0, 150 .arg_min = 0,
151 .arg_max = 4096, 151 .arg_max = 4096,
152 .aliases = NULL, 152 .aliases = NULL,
@@ -165,17 +165,67 @@ static otputil_widget_t otputil_widget_map[] =
165 { .name = "hotp", 165 { .name = "hotp",
166 .desc = "hotp tools (RFC 4226)", 166 .desc = "hotp tools (RFC 4226)",
167 .usage = " [ code ]", 167 .usage = " [ code ]",
168 .short_opt = (TOTP_SHORT_OPT "c:d:k:m:p"), 168 .short_opt = (TOTP_SHORT_OPT "c:d:k:m:o"),
169 .arg_min = 0, 169 .arg_min = 0,
170 .arg_max = 1, 170 .arg_max = 1,
171 .aliases = NULL, 171 .aliases = NULL,
172 .func_exec = &otputil_widget_hotp, 172 .func_exec = &otputil_widget_hotp,
173 .func_usage = NULL, 173 .func_usage = NULL,
174 }, 174 },
175 { .name = "otp",
176 .desc = "otp tools (RFC 2289)",
177 .usage = " [ sequence ] seed ]",
178 .short_opt = (TOTP_SHORT_OPT "c:m:oP:ps:"),
179 .arg_min = 0,
180 .arg_max = 2,
181 .aliases = NULL,
182 .func_exec = &otputil_widget_otp,
183 .func_usage = &otputil_widget_otp_usage,
184 },
185 { .name = "otp-md4",
186 .desc = "otp alias for MD4",
187 .usage = " [ sequence ] seed ]",
188 .short_opt = (TOTP_SHORT_OPT "c:oP:ps:"),
189 .arg_min = 0,
190 .arg_max = 2,
191 .aliases = NULL,
192 .func_exec = &otputil_widget_otp_md4,
193 .func_usage = NULL,
194 },
195 { .name = "otp-md5",
196 .desc = "otp alias for MD5",
197 .usage = " [ sequence ] seed ]",
198 .short_opt = (TOTP_SHORT_OPT "c:oP:ps:"),
199 .arg_min = 0,
200 .arg_max = 2,
201 .aliases = NULL,
202 .func_exec = &otputil_widget_otp_md5,
203 .func_usage = NULL,
204 },
205 { .name = "otp-sha1",
206 .desc = "otp alias for SHA1",
207 .usage = " [ sequence ] seed ]",
208 .short_opt = (TOTP_SHORT_OPT "c:oP:ps:"),
209 .arg_min = 0,
210 .arg_max = 2,
211 .aliases = NULL,
212 .func_exec = &otputil_widget_otp_sha1,
213 .func_usage = NULL,
214 },
215 { .name = "skey",
216 .desc = "s/key tools (RFC 1760)",
217 .usage = " [ sequence ]",
218 .short_opt = (TOTP_SHORT_OPT "c:m:oP:p"),
219 .arg_min = 0,
220 .arg_max = 1,
221 .aliases = NULL,
222 .func_exec = &otputil_widget_skey,
223 .func_usage = &otputil_widget_skey_usage,
224 },
175 { .name = "totp", 225 { .name = "totp",
176 .desc = "totp tools (RFC 6238)", 226 .desc = "totp tools (RFC 6238)",
177 .usage = " [ code ]", 227 .usage = " [ code ]",
178 .short_opt = (TOTP_SHORT_OPT "d:k:m:pT:t:x:"), 228 .short_opt = (TOTP_SHORT_OPT "d:k:m:oT:t:x:"),
179 .arg_min = 0, 229 .arg_min = 0,
180 .arg_max = 1, 230 .arg_max = 1,
181 .aliases = NULL, 231 .aliases = NULL,
@@ -234,6 +284,7 @@ main(
234 cnf->prog_name = &cnf->prog_name[1]; 284 cnf->prog_name = &cnf->prog_name[1];
235 if (!(cnf->prog_name)) 285 if (!(cnf->prog_name))
236 cnf->prog_name = argv[0]; 286 cnf->prog_name = argv[0];
287 otputil_set_param(NULL, OTPUTIL_OPT_DESC, cnf->prog_name);
237 288
238 289
239 // skip argument processing if called via alias 290 // skip argument processing if called via alias
@@ -288,6 +339,7 @@ otputil_arguments(
288 char * endptr; 339 char * endptr;
289 int rc; 340 int rc;
290 int i; 341 int i;
342 const char * str;
291 343
292 // getopt options 344 // getopt options
293 static const char * short_opt = "+" TOTP_SHORT_OPT; 345 static const char * short_opt = "+" TOTP_SHORT_OPT;
@@ -317,17 +369,16 @@ otputil_arguments(
317 369
318 case 'c': 370 case 'c':
319 uval = strtoull(optarg, &endptr, 0); 371 uval = strtoull(optarg, &endptr, 0);
372 i = (int)uval;
320 if ((optarg == endptr) || (endptr[0] != '\0')) 373 if ((optarg == endptr) || (endptr[0] != '\0'))
321 { 374 {
322 fprintf(stderr, "%s: invalid value for `-c'\n", PROGRAM_NAME); 375 fprintf(stderr, "%s: invalid value for `-c'\n", PROGRAM_NAME);
323 fprintf(stderr, "Try `%s --help' for more information.\n", PROGRAM_NAME); 376 fprintf(stderr, "Try `%s --help' for more information.\n", PROGRAM_NAME);
324 return(1); 377 return(1);
325 }; 378 };
326 if ((rc = otputil_set_param(NULL, OTPUTIL_OPT_HOTP_C, &uval)) != OTPUTIL_SUCCESS) 379 otputil_set_param(NULL, OTPUTIL_OPT_HOTP_C, &uval);
327 { 380 otputil_set_param(NULL, OTPUTIL_OPT_OTP_SEQ, &i);
328 fprintf(stderr, "%s: otputil_set_param(OTPUTIL_OPT_HOTP_C): %s\n", PROGRAM_NAME, otputil_err2string(rc)); 381 otputil_set_param(NULL, OTPUTIL_OPT_SKEY_SEQ, &i);
329 return(1);
330 };
331 break; 382 break;
332 383
333 case 'd': 384 case 'd':
@@ -370,31 +421,29 @@ otputil_arguments(
370 break; 421 break;
371 422
372 case 'm': 423 case 'm':
373 if ((i = otputil_str2md(optarg)) == -1) 424 str = (!(strncasecmp("otp-", optarg, 4))) ? &optarg[4] : optarg;
425 if ((i = otputil_str2md(str)) == -1)
374 { 426 {
375 fprintf(stderr, "%s: message digest for `-m'\n", PROGRAM_NAME); 427 fprintf(stderr, "%s: %s: unknown message digest for `-m'\n", PROGRAM_NAME, str);
376 fprintf(stderr, "Try `%s --help' for more information.\n", PROGRAM_NAME); 428 fprintf(stderr, "Try `%s --help' for more information.\n", PROGRAM_NAME);
377 return(1); 429 return(1);
378 }; 430 };
379 if ((rc = otputil_set_param(NULL, OTPUTIL_OPT_HMAC, &i)) != OTPUTIL_SUCCESS) 431 otputil_set_param(NULL, OTPUTIL_OPT_HOTP_HMAC, &i);
380 { 432 otputil_set_param(NULL, OTPUTIL_OPT_OTP_HASH, &i);
381 fprintf(stderr, "%s: otputil_set_param(OTPUTIL_OPT_HMAC): %s\n", PROGRAM_NAME, otputil_err2string(rc)); 433 otputil_set_param(NULL, OTPUTIL_OPT_SKEY_HASH, &i);
382 return(1); 434 otputil_set_param(NULL, OTPUTIL_OPT_TOTP_HMAC, &i);
383 };
384 break; 435 break;
385 436
386 case 's': 437 case 'o':
387 cnf->quiet = 1; 438 cnf->prompt_otp_pass = 1;
388 if ((cnf->verbose)) 439 break;
389 { 440
390 fprintf(stderr, "%s: incompatible options\n", PROGRAM_NAME); 441 case 'P':
391 fprintf(stderr, "Try `%s --help' for more information.\n", PROGRAM_NAME); 442 cnf->user_pass = optarg;
392 return(1);
393 };
394 break; 443 break;
395 444
396 case 'p': 445 case 'p':
397 cnf->otp_pass = otputil_getpass("Enter OTP password or code: ", NULL, 0); 446 cnf->prompt_user_pass = 1;
398 break; 447 break;
399 448
400 case 'q': 449 case 'q':
@@ -407,6 +456,14 @@ otputil_arguments(
407 }; 456 };
408 break; 457 break;
409 458
459 case 's':
460 if ((rc = otputil_set_param(NULL, OTPUTIL_OPT_OTP_SEED, optarg)) != OTPUTIL_SUCCESS)
461 {
462 fprintf(stderr, "%s: otputil_set_param(OTPUTIL_OPT_OTP_SEED): %s\n", PROGRAM_NAME, otputil_err2string(rc));
463 return(1);
464 };
465 break;
466
410 case 'T': 467 case 'T':
411 uval = strtoull(optarg, &endptr, 0); 468 uval = strtoull(optarg, &endptr, 0);
412 if ((optarg == endptr) || (endptr[0] != '\0')) 469 if ((optarg == endptr) || (endptr[0] != '\0'))
@@ -493,6 +550,33 @@ otputil_arguments(
493 return(1); 550 return(1);
494 }; 551 };
495 552
553 // process user password
554 if ( ((cnf->user_pass)) && ((cnf->prompt_user_pass)) )
555 {
556 fprintf(stderr, "%s: incompatible options `-P' and `-p'\n", PROGRAM_NAME);
557 fprintf(stderr, "Try `%s --help' for more information.\n", PROGRAM_NAME);
558 return(1);
559 };
560 if ((cnf->prompt_user_pass))
561 cnf->user_pass = otputil_getpass("Enter user's password: ", NULL, 0);
562 if ((cnf->user_pass))
563 {
564 if ((rc = otputil_set_param(NULL, OTPUTIL_OPT_SKEY_PASS, cnf->user_pass)) != OTPUTIL_SUCCESS)
565 {
566 fprintf(stderr, "%s: otputil_set_param(OTPUTIL_OPT_SKEY_PASS): %s\n", PROGRAM_NAME, otputil_err2string(rc));
567 return(1);
568 };
569 if ((rc = otputil_set_param(NULL, OTPUTIL_OPT_OTP_PASS, cnf->user_pass)) != OTPUTIL_SUCCESS)
570 {
571 fprintf(stderr, "%s: otputil_set_param(OTPUTIL_OPT_OTP_PASS): %s\n", PROGRAM_NAME, otputil_err2string(rc));
572 return(1);
573 };
574 };
575
576 // process OTP password
577 if ((cnf->prompt_otp_pass))
578 cnf->otp_pass = otputil_getpass("Enter OTP password or code: ", NULL, 0);
579
496 return(0); 580 return(0);
497} 581}
498 582
@@ -615,12 +699,16 @@ otputil_widget_usage(
615 printf(" %s-%s [OPTIONS]%s\n", PROGRAM_NAME, widget_name, widget_help); 699 printf(" %s-%s [OPTIONS]%s\n", PROGRAM_NAME, widget_name, widget_help);
616 printf(" %s%s [OPTIONS]%s\n", PROGRAM_NAME, widget_name, widget_help); 700 printf(" %s%s [OPTIONS]%s\n", PROGRAM_NAME, widget_name, widget_help);
617 printf("OPTIONS:\n"); 701 printf("OPTIONS:\n");
618 if ((strchr(short_opt, 'c'))) printf(" -c num counter value\n"); 702 if ((strchr(short_opt, 'c'))) printf(" -c num counter/sequence value\n");
619 if ((strchr(short_opt, 'd'))) printf(" -d num number of digits in code\n"); 703 if ((strchr(short_opt, 'd'))) printf(" -d num number of digits in code\n");
620 if ((strchr(short_opt, 'k'))) printf(" -k string shared user key\n"); 704 if ((strchr(short_opt, 'k'))) printf(" -k string shared user key\n");
621 if ((strchr(short_opt, 'h'))) printf(" -h, --help print this help and exit\n"); 705 if ((strchr(short_opt, 'h'))) printf(" -h, --help print this help and exit\n");
622 if ((strchr(short_opt, 'm'))) printf(" -m hash use message digest hash\n"); 706 if ((strchr(short_opt, 'm'))) printf(" -m hash use message digest hash\n");
707 if ((strchr(short_opt, 'o'))) printf(" -o prompt for OTP password/code to verify\n");
708 if ((strchr(short_opt, 'P'))) printf(" -P str user password\n");
709 if ((strchr(short_opt, 'p'))) printf(" -p prompt for user password\n");
623 if ((strchr(short_opt, 'q'))) printf(" -q, --quiet, --silent do not print messages\n"); 710 if ((strchr(short_opt, 'q'))) printf(" -q, --quiet, --silent do not print messages\n");
711 if ((strchr(short_opt, 's'))) printf(" -s seed OTP seed\n");
624 if ((strchr(short_opt, 'T'))) printf(" -T seconds current Unix time\n"); 712 if ((strchr(short_opt, 'T'))) printf(" -T seconds current Unix time\n");
625 if ((strchr(short_opt, 't'))) printf(" -t seconds Unix time start of time steps\n"); 713 if ((strchr(short_opt, 't'))) printf(" -t seconds Unix time start of time steps\n");
626 if ((strchr(short_opt, 'V'))) printf(" -V, --version print version number and exit\n"); 714 if ((strchr(short_opt, 'V'))) printf(" -V, --version print version number and exit\n");
diff --git a/src/otputil.h b/src/otputil.h
index 5471cd8..cd6bd18 100644
--- a/src/otputil.h
+++ b/src/otputil.h
@@ -87,10 +87,13 @@ struct _otputil_cli_config
87 int quiet; 87 int quiet;
88 int verbose; 88 int verbose;
89 int opt_index; 89 int opt_index;
90 int prompt_user_pass;
91 int prompt_otp_pass;
90 int argc; 92 int argc;
91 char ** argv; 93 char ** argv;
92 const char * prog_name; 94 const char * prog_name;
93 const char * otp_pass; 95 const char * otp_pass;
96 const char * user_pass;
94 const otputil_widget_t * widget; 97 const otputil_widget_t * widget;
95}; 98};
96 99
@@ -125,6 +128,41 @@ otputil_widget_hotp(
125 128
126 129
127extern int 130extern int
131otputil_widget_otp(
132 otputil_config_t * cnf );
133
134
135extern int
136otputil_widget_otp_md4(
137 otputil_config_t * cnf );
138
139
140extern int
141otputil_widget_otp_md5(
142 otputil_config_t * cnf );
143
144
145extern int
146otputil_widget_otp_sha1(
147 otputil_config_t * cnf );
148
149
150extern int
151otputil_widget_otp_usage(
152 otputil_config_t * cnf );
153
154
155extern int
156otputil_widget_skey(
157 otputil_config_t * cnf );
158
159
160extern int
161otputil_widget_skey_usage(
162 otputil_config_t * cnf );
163
164
165extern int
128otputil_widget_totp( 166otputil_widget_totp(
129 otputil_config_t * cnf ); 167 otputil_config_t * cnf );
130 168
diff --git a/src/widget-hotp.c b/src/widget-hotp.c
index af1e51e..535d543 100644
--- a/src/widget-hotp.c
+++ b/src/widget-hotp.c
@@ -116,7 +116,7 @@ otputil_widget_hotp(
116 return((rc == -1) ? 0 : 1); 116 return((rc == -1) ? 0 : 1);
117 if ( ((cnf->otp_pass)) && (cnf->argc > optind) ) 117 if ( ((cnf->otp_pass)) && (cnf->argc > optind) )
118 { 118 {
119 fprintf(stderr, "%s: cannot specify code and use `-p'\n", cnf->prog_name); 119 fprintf(stderr, "%s: cannot specify code and use `-o'\n", cnf->prog_name);
120 fprintf(stderr, "Try `%s --help' for more information.\n", cnf->prog_name); 120 fprintf(stderr, "Try `%s --help' for more information.\n", cnf->prog_name);
121 return(1); 121 return(1);
122 }; 122 };
diff --git a/src/widget-otp.c b/src/widget-otp.c
new file mode 100644
index 0000000..ae67a86
--- /dev/null
+++ b/src/widget-otp.c
@@ -0,0 +1,322 @@
1/*
2 * OTP Utilities
3 * Copyright (C) 2022 David M. Syzdek <david@syzdek.net>.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * * Neither the name of David M. Syzdek nor the
15 * names of its contributors may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
19 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID M SYZDEK BE LIABLE FOR
22 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30/*
31 * @file src/widget-otp.c
32 */
33#define _SRC_WIDGET_OTP_C 1
34
35///////////////
36// //
37// Headers //
38// //
39///////////////
40#pragma mark - Headers
41
42#include <otputil_compat.h>
43
44#ifdef HAVE_CONFIG_H
45# include <config.h>
46#endif
47
48#include <errno.h>
49#include <assert.h>
50#include <stdarg.h>
51#include <string.h>
52#include <strings.h>
53#include <stdlib.h>
54#include <getopt.h>
55#include <stdio.h>
56
57#include "otputil.h"
58
59
60//////////////////
61// //
62// Prototypes //
63// //
64//////////////////
65#pragma mark - Prototypes
66
67static int
68otputil_widget_otp_verbose(
69 otputil_config_t * cnf,
70 const otputil_bv_t * otp_data,
71 const otputil_bv_t * otp_verify,
72 const char * status );
73
74
75/////////////////
76// //
77// Functions //
78// //
79/////////////////
80#pragma mark - Functions
81
82
83//---------------//
84// main function //
85//---------------//
86#pragma mark main function
87
88int
89otputil_widget_otp(
90 otputil_config_t * cnf )
91{
92 int rc;
93 int hash;
94 int seq;
95 uint64_t meth;
96 char * pass;
97 char * endptr;
98 const char * str;
99 const char * status;
100 static char buff[OTPUTIL_MAX_ENCODE_SIZE];
101 otputil_bv_t otp_data;
102 otputil_bv_t otp_verify;
103 otputil_bv_t * a;
104 otputil_bv_t * b;
105 uint8_t otp_data_val[512];
106 uint8_t otp_verify_val[512];
107
108 assert(cnf != NULL);
109
110 // set OTP method
111 meth = OTPUTIL_METH_OTP;
112 if ((rc = otputil_set_param(NULL, OTPUTIL_OPT_METHOD, &meth)) == -1)
113 {
114 fprintf(stderr, "%s: otputil_set_param(METHOD): %s\n", cnf->prog_name, otputil_err2string(rc));
115 return(1);
116 };
117
118 // initial processing of cli arguments
119 if ((rc = otputil_arguments(cnf, cnf->argc, cnf->argv)) != 0)
120 return((rc == -1) ? 0 : 1);
121 if (cnf->argc > optind)
122 {
123 seq = (int)strtoul(cnf->argv[optind], &endptr, 0);
124 if ((endptr == cnf->argv[optind]) || (endptr[0] != '\0'))
125 {
126 fprintf(stderr, "%s: invalid sequence number\n", cnf->prog_name);
127 fprintf(stderr, "Try `%s --help' for more information.\n", cnf->prog_name);
128 return(1);
129 };
130 if ((rc = otputil_set_param(NULL, OTPUTIL_OPT_OTP_SEQ, &seq)) != OTPUTIL_SUCCESS)
131 {
132 fprintf(stderr, "%s: otputil_set_param(OTP_SEQ): %s\n", cnf->prog_name, otputil_err2string(rc));
133 return(1);
134 };
135 };
136 if (cnf->argc > (optind+1))
137 {
138 if ((rc = otputil_set_param(NULL, OTPUTIL_OPT_OTP_SEED, cnf->argv[optind+1])) != OTPUTIL_SUCCESS)
139 {
140 fprintf(stderr, "%s: otputil_set_param(OTP_SEED): %s\n", cnf->prog_name, otputil_err2string(rc));
141 return(1);
142 };
143 };
144
145 // verify password and seed were provided
146 otputil_get_param(NULL, OTPUTIL_OPT_OTP_PASS, &pass);
147 if (!(pass))
148 {
149 str = otputil_getpass("Enter user's password:", NULL, 0);
150 if ((rc = otputil_set_param(NULL, OTPUTIL_OPT_OTP_PASS, str)) != OTPUTIL_SUCCESS)
151 {
152 fprintf(stderr, "%s: otputil_set_param(OTP_PASS): %s\n", cnf->prog_name, otputil_err2string(rc));
153 return(1);
154 };
155 };
156 if ((pass))
157 free(pass);
158 otputil_get_param(NULL, OTPUTIL_OPT_OTP_SEED, &pass);
159 if (!(pass))
160 {
161 fprintf(stderr, "%s: must provide OTP seed\n", cnf->prog_name);
162 fprintf(stderr, "Try `%s --help' for more information.\n", cnf->prog_name);
163 return(1);
164 };
165 free(pass);
166
167 // generate OTP pass phrase
168 if ((str = otputil_str(NULL, buff, sizeof(buff))) == NULL)
169 {
170 fprintf(stderr, "%s: internal error\n", cnf->prog_name);
171 return(1);
172 };
173 otp_data.bv_val = otp_data_val;
174 otp_data.bv_len = sizeof(otp_data_val);
175 otputil_get_param(NULL, OTPUTIL_OPT_OTP_HASH, &hash);
176 otputil_otp_decode(str, &otp_data, hash);
177
178 // verify existing code
179 if ((cnf->otp_pass))
180 {
181 otp_verify.bv_val = otp_verify_val;
182 otp_verify.bv_len = sizeof(otp_verify_val);
183 if (otputil_otp_decode(cnf->otp_pass, &otp_verify, hash) == NULL)
184 {
185 fprintf(stderr, "%s: not a valid OTP passphrase to verify\n", cnf->prog_name);
186 return(1);
187 };
188 a = &otp_data;
189 b = &otp_verify;
190 rc = ((otputil_bvcmp(&a, &b))) ? 2 : 0;
191 status = ((rc)) ? "invalid code" : "valid code";
192 if ((cnf->verbose))
193 otputil_widget_otp_verbose(cnf, &otp_data, &otp_verify, status);
194 else
195 printf("%s\n", status);
196 return(rc);
197 };
198
199 // print results
200 if ( ((cnf->quiet)) || (!(cnf->verbose)) )
201 {
202 printf("%s\n", str);
203 return(0);
204 };
205 otputil_widget_otp_verbose(cnf, &otp_data, NULL, NULL);
206
207 return(0);
208}
209
210
211int
212otputil_widget_otp_md4(
213 otputil_config_t * cnf )
214{
215 int rc;
216 int hash;
217 assert(cnf != NULL);
218 hash = OTPUTIL_MD_MD4;
219 if ((rc = otputil_set_param(NULL, OTPUTIL_OPT_OTP_HASH, &hash)) == -1)
220 {
221 fprintf(stderr, "%s: otputil_set_param(OTP_HASH): %s\n", cnf->prog_name, otputil_err2string(rc));
222 return(1);
223 };
224 return(otputil_widget_otp(cnf));
225}
226
227
228int
229otputil_widget_otp_md5(
230 otputil_config_t * cnf )
231{
232 int rc;
233 int hash;
234 assert(cnf != NULL);
235 hash = OTPUTIL_MD_MD5;
236 if ((rc = otputil_set_param(NULL, OTPUTIL_OPT_OTP_HASH, &hash)) == -1)
237 {
238 fprintf(stderr, "%s: otputil_set_param(OTP_HASH): %s\n", cnf->prog_name, otputil_err2string(rc));
239 return(1);
240 };
241 return(otputil_widget_otp(cnf));
242}
243
244
245int
246otputil_widget_otp_sha1(
247 otputil_config_t * cnf )
248{
249 int rc;
250 int hash;
251 assert(cnf != NULL);
252 hash = OTPUTIL_MD_SHA1;
253 if ((rc = otputil_set_param(NULL, OTPUTIL_OPT_OTP_HASH, &hash)) == -1)
254 {
255 fprintf(stderr, "%s: otputil_set_param(OTP_HASH): %s\n", cnf->prog_name, otputil_err2string(rc));
256 return(1);
257 };
258 return(otputil_widget_otp(cnf));
259}
260
261
262int
263otputil_widget_otp_usage(
264 otputil_config_t * cnf )
265{
266 assert(cnf != NULL);
267 printf("ALGORITHMS:\n");
268 printf(" md4 MD4 Message-Digest Algorithm\n");
269 printf(" md5 MD5 message-digest algorithm\n");
270 printf(" sha1 SHA-1 (Secure Hash Algorithm 1)\n");
271 printf(" sha256 SHA-2 (Secure Hash Algorithm 2) with 256 bits\n");
272 printf(" sha512 SHA-2 (Secure Hash Algorithm 2) with 512 bits\n");
273 return(0);
274}
275
276
277int
278otputil_widget_otp_verbose(
279 otputil_config_t * cnf,
280 const otputil_bv_t * otp_data,
281 const otputil_bv_t * otp_verify,
282 const char * status )
283{
284 int otp_seq;
285 char * util_desc;
286 char * otp_seed;
287 char * otp_pass;
288 int otp_hash;
289
290 otputil_get_param(NULL, OTPUTIL_OPT_OTP_SEQ, &otp_seq);
291 otputil_get_param(NULL, OTPUTIL_OPT_OTP_HASH, &otp_hash);
292 otputil_get_param(NULL, OTPUTIL_OPT_OTP_SEED, &otp_seed);
293 otputil_get_param(NULL, OTPUTIL_OPT_OTP_PASS, &otp_pass);
294 otputil_get_param(NULL, OTPUTIL_OPT_DESC, &util_desc);
295
296 // print secret information
297 printf("S/KEY Secret:\n");
298 printf(" Description: %s\n", (((util_desc)) ? util_desc : "n/a") );
299 printf(" Method: OTP (RFC2289)\n");
300 printf(" Hash: %s\n", otputil_md2str(otp_hash));
301 if (cnf->verbose > 1)
302 printf(" User Passsword: %s\n", otp_pass);
303 else
304 printf(" User Passsword: ********\n");
305 printf(" Seed: %s\n", otp_seed);
306 printf(" Sequence: %i\n", otp_seq );
307 if ((cnf->otp_pass))
308 printf(" Entered Pass Phrase: %s\n", cnf->otp_pass );
309 if ((cnf->otp_pass))
310 printf(" Expected Code: %s\n", otputil_otp_encode(otp_verify, NULL, 0, OTPUTIL_ENC_HEX) );
311 printf(" OTP Code: %s\n", otputil_otp_encode(otp_data, NULL, 0, OTPUTIL_ENC_HEX) );
312 if ((cnf->otp_pass))
313 printf(" Expected Pass Phrase: %s\n", otputil_otp_encode(otp_verify, NULL, 0, OTPUTIL_ENC_SIXWORD) );
314 printf(" OTP Pass Phrase: %s\n", otputil_otp_encode(otp_data, NULL, 0, OTPUTIL_ENC_SIXWORD) );
315 if ((status))
316 printf(" Status: %s\n", status );
317 printf("\n");
318
319 return(0);
320}
321
322/* end of source file */
diff --git a/src/widget-skey.c b/src/widget-skey.c
new file mode 100644
index 0000000..9fa69ea
--- /dev/null
+++ b/src/widget-skey.c
@@ -0,0 +1,252 @@
1/*
2 * OTP Utilities
3 * Copyright (C) 2022 David M. Syzdek <david@syzdek.net>.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * * Neither the name of David M. Syzdek nor the
15 * names of its contributors may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
19 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID M SYZDEK BE LIABLE FOR
22 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30/*
31 * @file src/widget-otp.c
32 */
33#define _SRC_WIDGET_OTP_C 1
34
35///////////////
36// //
37// Headers //
38// //
39///////////////
40#pragma mark - Headers
41
42#include <otputil_compat.h>
43
44#ifdef HAVE_CONFIG_H
45# include <config.h>
46#endif
47
48#include <errno.h>
49#include <assert.h>
50#include <stdarg.h>
51#include <string.h>
52#include <strings.h>
53#include <stdlib.h>
54#include <getopt.h>
55#include <stdio.h>
56
57#include "otputil.h"
58
59
60//////////////////
61// //
62// Prototypes //
63// //
64//////////////////
65#pragma mark - Prototypes
66
67static int
68otputil_widget_skey_verbose(
69 otputil_config_t * cnf,
70 const otputil_bv_t * otp_data,
71 const otputil_bv_t * otp_verify,
72 const char * status );
73
74
75/////////////////
76// //
77// Functions //
78// //
79/////////////////
80#pragma mark - Functions
81
82
83//---------------//
84// main function //
85//---------------//
86#pragma mark main function
87
88int
89otputil_widget_skey(
90 otputil_config_t * cnf )
91{
92 int rc;
93 int hash;
94 int seq;
95 uint64_t meth;
96 char * pass;
97 char * endptr;
98 const char * str;
99 const char * status;
100 static char buff[OTPUTIL_MAX_ENCODE_SIZE];
101 otputil_bv_t skey_data;
102 otputil_bv_t skey_verify;
103 otputil_bv_t * a;
104 otputil_bv_t * b;
105 uint8_t skey_data_val[512];
106 uint8_t skey_verify_val[512];
107
108 assert(cnf != NULL);
109
110 // set OTP method
111 meth = OTPUTIL_METH_SKEY;
112 if ((rc = otputil_set_param(NULL, OTPUTIL_OPT_METHOD, &meth)) == -1)
113 {
114 fprintf(stderr, "%s: otputil_set_param(METHOD): %s\n", cnf->prog_name, otputil_err2string(rc));
115 return(1);
116 };
117
118 // initial processing of cli arguments
119 if ((rc = otputil_arguments(cnf, cnf->argc, cnf->argv)) != 0)
120 return((rc == -1) ? 0 : 1);
121 if (cnf->argc > optind)
122 {
123 seq = (int)strtoul(cnf->argv[optind], &endptr, 0);
124 if ((endptr == cnf->argv[optind]) || (endptr[0] != '\0'))
125 {
126 fprintf(stderr, "%s: invalid sequence number\n", cnf->prog_name);
127 fprintf(stderr, "Try `%s --help' for more information.\n", cnf->prog_name);
128 return(1);
129 };
130 if ((rc = otputil_set_param(NULL, OTPUTIL_OPT_SKEY_SEQ, &seq)) != OTPUTIL_SUCCESS)
131 {
132 fprintf(stderr, "%s: otputil_set_param(SKEY_SEQ): %s\n", cnf->prog_name, otputil_err2string(rc));
133 return(1);
134 };
135 };
136
137 // verify password was provided
138 otputil_get_param(NULL, OTPUTIL_OPT_SKEY_PASS, &pass);
139 if (!(pass))
140 {
141 str = otputil_getpass("Enter user's password:", NULL, 0);
142 if ((rc = otputil_set_param(NULL, OTPUTIL_OPT_SKEY_PASS, str)) != OTPUTIL_SUCCESS)
143 {
144 fprintf(stderr, "%s: otputil_set_param(SKEY_PASS): %s\n", cnf->prog_name, otputil_err2string(rc));
145 return(1);
146 };
147 };
148 if ((pass))
149 free(pass);
150
151 // generate OTP pass phrase
152 if ((str = otputil_str(NULL, buff, sizeof(buff))) == NULL)
153 {
154 fprintf(stderr, "%s: internal error\n", cnf->prog_name);
155 return(1);
156 };
157 skey_data.bv_val = skey_data_val;
158 skey_data.bv_len = sizeof(skey_data_val);
159 otputil_get_param(NULL, OTPUTIL_OPT_OTP_HASH, &hash);
160 otputil_otp_decode(str, &skey_data, hash);
161
162 // verify existing code
163 if ((cnf->otp_pass))
164 {
165 skey_verify.bv_val = skey_verify_val;
166 skey_verify.bv_len = sizeof(skey_verify_val);
167 if (otputil_otp_decode(cnf->otp_pass, &skey_verify, hash) == NULL)
168 {
169 fprintf(stderr, "%s: not a valid OTP passphrase to verify\n", cnf->prog_name);
170 return(1);
171 };
172 a = &skey_data;
173 b = &skey_verify;
174 rc = ((otputil_bvcmp(&a, &b))) ? 2 : 0;
175 status = ((rc)) ? "invalid code" : "valid code";
176 if ((cnf->verbose))
177 otputil_widget_skey_verbose(cnf, &skey_data, &skey_verify, status);
178 else
179 printf("%s\n", status);
180 return(rc);
181 };
182
183 // print results
184 if ( ((cnf->quiet)) || (!(cnf->verbose)) )
185 {
186 printf("%s\n", str);
187 return(0);
188 };
189 otputil_widget_skey_verbose(cnf, &skey_data, NULL, NULL);
190
191 return(0);
192}
193
194
195int
196otputil_widget_skey_usage(
197 otputil_config_t * cnf )
198{
199 assert(cnf != NULL);
200 printf("ALGORITHMS:\n");
201 printf(" md4 MD4 Message-Digest Algorithm\n");
202 printf(" md5 MD5 message-digest algorithm\n");
203 printf(" sha1 SHA-1 (Secure Hash Algorithm 1)\n");
204 printf(" sha256 SHA-2 (Secure Hash Algorithm 2) with 256 bits\n");
205 printf(" sha512 SHA-2 (Secure Hash Algorithm 2) with 512 bits\n");
206 return(0);
207}
208
209
210int
211otputil_widget_skey_verbose(
212 otputil_config_t * cnf,
213 const otputil_bv_t * skey_data,
214 const otputil_bv_t * skey_verify,
215 const char * status )
216{
217 int skey_hash;
218 int skey_seq;
219 char * util_desc;
220 char * skey_pass;
221
222 otputil_get_param(NULL, OTPUTIL_OPT_SKEY_SEQ, &skey_seq);
223 otputil_get_param(NULL, OTPUTIL_OPT_SKEY_HASH, &skey_hash);
224 otputil_get_param(NULL, OTPUTIL_OPT_SKEY_PASS, &skey_pass);
225 otputil_get_param(NULL, OTPUTIL_OPT_DESC, &util_desc);
226
227 // print secret information
228 printf("S/KEY Secret:\n");
229 printf(" Description: %s\n", (((util_desc)) ? util_desc : "n/a") );
230 printf(" Method: S/KEY (RFC1760)\n");
231 printf(" Hash: %s\n", otputil_md2str(skey_hash));
232 if (cnf->verbose > 1)
233 printf(" User Passsword: %s\n", skey_pass);
234 else
235 printf(" User Passsword: ********\n");
236 printf(" Sequence: %i\n", skey_seq );
237 if ((cnf->otp_pass))
238 printf(" Entered Pass Phrase: %s\n", cnf->otp_pass );
239 if ((cnf->otp_pass))
240 printf(" Expected Code: %s\n", otputil_otp_encode(skey_verify, NULL, 0, OTPUTIL_ENC_HEX) );
241 printf(" OTP Code: %s\n", otputil_otp_encode(skey_data, NULL, 0, OTPUTIL_ENC_HEX) );
242 if ((cnf->otp_pass))
243 printf(" Expected Pass Phrase: %s\n", otputil_otp_encode(skey_verify, NULL, 0, OTPUTIL_ENC_SIXWORD) );
244 printf(" OTP Pass Phrase: %s\n", otputil_otp_encode(skey_data, NULL, 0, OTPUTIL_ENC_SIXWORD) );
245 if ((status))
246 printf(" Status: %s\n", status );
247 printf("\n");
248
249 return(0);
250}
251
252/* end of source file */
diff --git a/src/widget-totp.c b/src/widget-totp.c
index 0c5a41d..fe08220 100644
--- a/src/widget-totp.c
+++ b/src/widget-totp.c
@@ -117,7 +117,7 @@ otputil_widget_totp(
117 return((rc == -1) ? 0 : 1); 117 return((rc == -1) ? 0 : 1);
118 if ( ((cnf->otp_pass)) && (cnf->argc > optind) ) 118 if ( ((cnf->otp_pass)) && (cnf->argc > optind) )
119 { 119 {
120 fprintf(stderr, "%s: cannot specify code and use `-p'\n", cnf->prog_name); 120 fprintf(stderr, "%s: cannot specify code and use `-o'\n", cnf->prog_name);
121 fprintf(stderr, "Try `%s --help' for more information.\n", cnf->prog_name); 121 fprintf(stderr, "Try `%s --help' for more information.\n", cnf->prog_name);
122 return(1); 122 return(1);
123 }; 123 };