]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/opie/opiekey.c
This commit was generated by cvs2svn to compensate for changes in r56173,
[FreeBSD/FreeBSD.git] / contrib / opie / opiekey.c
1 /* opiekey.c: Stand-alone program for computing responses to OTP challenges.
2
3  Takes a sequence number and seed (presumably from an OPIE challenge)
4  as command line arguments, prompts for the user's secret pass phrase,
5  and outputs a response.
6
7 %%% portions-copyright-cmetz-96
8 Portions of this software are Copyright 1996-1997 by Craig Metz, All Rights
9 Reserved. The Inner Net License Version 2 applies to these portions of
10 the software.
11 You should have received a copy of the license with this software. If
12 you didn't get a copy, you may request one from <license@inner.net>.
13
14 Portions of this software are Copyright 1995 by Randall Atkinson and Dan
15 McDonald, All Rights Reserved. All Rights under this copyright are assigned
16 to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
17 License Agreement applies to this software.
18
19         History:
20
21         Modified by cmetz for OPIE 2.31. Renamed "init" and RESPONSE_INIT
22                 to "init-hex" and RESPONSE_INIT_HEX. Removed active attack
23                 protection support.
24         Modified by cmetz for OPIE 2.3. OPIE_PASS_MAX changed to
25                 OPIE_SECRET_MAX. Added extended responses, which created
26                 lots of changes. Eliminated extra variable. Added -x and
27                 -t to help. Added -f flag. Added SHA support.
28         Modified by cmetz for OPIE 2.22. Print newline after seed too long
29                 message. Check for minimum seed length. Correct a grammar
30                 error.
31         Modified at NRL for OPIE 2.2. Check opiereadpass() return.
32                 Change opiereadpass() calls to add echo arg. Use FUNCTION
33                 definition et al. Check seed length here, too. Added back
34                 hex output. Reworked final output function.
35         Modified at NRL for OPIE 2.0.
36         Written at Bellcore for the S/Key Version 1 software distribution
37                 (skey.c).
38 */
39 #include "opie_cfg.h"
40
41 #include <stdio.h>
42 #include <string.h>
43 #include <stdlib.h>
44
45 #include "opie.h"
46
47 #ifdef  __MSDOS__
48 #include <dos.h>
49 #endif
50
51 #if HAVE_FCNTL_H
52 #include <fcntl.h>
53 #endif /* HAVE_FCNTL_H */
54
55 extern char *optarg;
56 extern int optind, opterr;
57
58 int aflag = 0;
59
60 char *algnames[] = { NULL, NULL, NULL, "SHA-1", "MD4", "MD5" };
61 char *algids[] = { NULL, NULL, NULL, "sha1", "md4", "md5" };
62
63 /******** Begin real source code ***************/
64
65 static VOIDRET usage FUNCTION((s), char *s)
66 {
67   fprintf(stderr, "usage: %s [-v] [-h] [-f] [-x] [-t type] [-4 | -5 | -s] [-a] [-n count] sequence_number seed\n", s);
68   exit(1);
69 }
70
71 #define RESPONSE_STANDARD  0
72 #define RESPONSE_WORD      1
73 #define RESPONSE_HEX       2
74 #define RESPONSE_INIT_HEX  3
75 #define RESPONSE_INIT_WORD 4
76 #define RESPONSE_UNKNOWN   5
77
78 struct _rtrans {
79   int type;
80   char *name;
81 };
82
83 static struct _rtrans rtrans[] = {
84   { RESPONSE_WORD, "word" },
85   { RESPONSE_HEX, "hex" },
86   { RESPONSE_INIT_HEX, "init-hex" },
87   { RESPONSE_INIT_WORD, "init-word" },
88   { RESPONSE_STANDARD, "" },
89   { RESPONSE_STANDARD, "standard" },
90   { RESPONSE_STANDARD, "otp" },
91   { RESPONSE_UNKNOWN, NULL }
92 };
93
94 static void getsecret FUNCTION((secret, promptextra, retype), char *secret AND char *promptextra AND int flags)
95 {
96   fprintf(stderr, "Enter %ssecret pass phrase: ", promptextra);
97   if (!opiereadpass(secret, OPIE_SECRET_MAX, 0)) {
98     fprintf(stderr, "Error reading %ssecret pass phrase!\n", promptextra);
99     exit(1);
100   }
101   if (secret[0] && (flags & 1)) {
102     char verify[OPIE_SECRET_MAX + 1];
103
104     fprintf(stderr, "Again %ssecret pass phrase: ", promptextra);
105     if (!opiereadpass(verify, OPIE_SECRET_MAX, 0)) {
106       fprintf(stderr, "Error reading %ssecret pass phrase!\n", promptextra);
107       memset(verify, 0, sizeof(verify));
108       memset(secret, 0, sizeof(secret));
109       exit(1);
110     }
111     if (verify[0] && strcmp(verify, secret)) {
112       fprintf(stderr, "They don't match. Try again.\n");
113       memset(verify, 0, sizeof(verify));
114       memset(secret, 0, sizeof(secret));
115       exit(1);
116     }
117     memset(verify, 0, sizeof(verify));
118   }
119   if (!(flags & 2) && opiepasscheck(secret)) {
120     memset(secret, 0, sizeof(secret));
121     fprintf(stderr, "Secret pass phrases must be between %d and %d characters long.\n", OPIE_SECRET_MIN, OPIE_SECRET_MAX);
122     exit(1);
123   };
124 }
125
126 int main FUNCTION((argc, argv), int argc AND char *argv[])
127 {
128   /* variable declarations */
129   unsigned algorithm = MDX;     /* default algorithm per Makefile's MDX
130                                    symbol */
131   int keynum = 0;
132   int i;
133   int count = 1;
134   char secret[OPIE_SECRET_MAX + 1], newsecret[OPIE_SECRET_MAX + 1];
135   char key[8], newkey[8];
136   char *seed, newseed[OPIE_SEED_MAX + 1];
137   char response[OPIE_RESPONSE_MAX + 1];
138   char *slash;
139   int hex = 0;
140   int type = RESPONSE_STANDARD;
141   int force;
142
143   if (slash = strchr(argv[0], '/'))
144     slash++;
145   else
146     slash = argv[0];
147
148   if (!strcmp(slash, "key") || strstr(slash, "md4"))
149     algorithm = 4;
150
151   if (strstr(slash, "md5"))
152     algorithm = 5;
153
154   if (strstr(slash, "sha"))
155     algorithm = 3;
156
157   while ((i = getopt(argc, argv, "fhvn:x45at:s")) != EOF) {
158     switch (i) {
159     case 'v':
160       opieversion();
161
162     case 'n':
163       count = atoi(optarg);
164       break;
165
166     case 'x':
167       hex = 1;
168       break;
169
170     case 'f':
171 #if INSECURE_OVERRIDE
172       force = 1;
173 #else /* INSECURE_OVERRIDE */
174       fprintf(stderr, "Sorry, but the -f option is not supported by this build of OPIE.\n");
175 #endif /* INSECURE_OVERRIDE */
176       break;
177
178     case '4':
179       /* use MD4 algorithm */
180       algorithm = 4;
181       break;
182
183     case '5':
184       /* use MD5 algorithm */
185       algorithm = 5;
186       break;
187
188     case 'a':
189       aflag = 1;
190       break;
191
192     case 't':
193       {
194         struct _rtrans *r;
195         for (r = rtrans; r->name && strcmp(r->name, optarg); r++);
196         if (!r->name) {
197           fprintf(stderr, "%s: %s: unknown response type.\n", argv[0], optarg);
198           exit(1);
199         }
200         type = r->type;
201       }
202       break;
203
204     case 's':
205       algorithm = 3;
206       break;
207
208     default:
209       usage(argv[0]);
210     }
211   }
212
213   if ((argc - optind) < 2)
214     usage(argv[0]);
215
216   fprintf(stderr, "Using the %s algorithm to compute response.\n", algnames[algorithm]);
217
218   /* get sequence number, which is next-to-last parameter */
219   keynum = atoi(argv[optind]);
220   if (keynum < 1) {
221     fprintf(stderr, "Sequence number %s is not positive.\n", argv[optind]);
222     exit(1);
223   }
224   /* get seed string, which is last parameter */
225   seed = argv[optind + 1];
226   {
227     i = strlen(seed);
228
229     if (i > OPIE_SEED_MAX) {
230       fprintf(stderr, "Seeds must be less than %d characters long.\n", OPIE_SEED_MAX);
231       exit(1);
232     }
233     if (i < OPIE_SEED_MIN) {
234       fprintf(stderr, "Seeds must be greater than %d characters long.\n", OPIE_SEED_MIN);
235       exit(1);
236     }
237   }
238
239   fprintf(stderr, "Reminder: Don't use opiekey from telnet or dial-in sessions.\n");
240
241   if (opieinsecure()) {
242     fprintf(stderr, "Sorry, but you don't seem to be on the console or a secure terminal.\n");
243 #if INSECURE_OVERRIDE
244     if (force)
245       fprintf(stderr, "Warning: Continuing could disclose your secret pass phrase to an attacker!\n");
246     else
247 #endif /* INSECURE_OVERRIDE */
248       exit(1);
249   }
250
251   if ((type == RESPONSE_INIT_HEX) || (type == RESPONSE_INIT_WORD)) {
252 #if RETYPE
253     getsecret(secret, "old ", 1);
254 #else /* RETYPE */
255     getsecret(secret, "old ", 0);
256 #endif /* RETYPE */
257     getsecret(newsecret, "new ", 1);
258     if (!newsecret[0])
259       strcpy(newsecret, secret);
260
261     if (opienewseed(strcpy(newseed, seed)) < 0) {
262       fprintf(stderr, "Error updating seed.\n");
263       goto error;
264     }
265
266     if (opiekeycrunch(algorithm, newkey, newseed, newsecret)) {
267       fprintf(stderr, "%s: key crunch failed (1)\n", argv[0]);
268       goto error;
269     }
270
271     for (i = 0; i < 499; i++)
272       opiehash(newkey, algorithm);
273   } else
274 #if RETYPE
275     getsecret(secret, "", 1);
276 #else /* RETYPE */
277     getsecret(secret, "", 0);
278 #endif /* RETYPE */
279
280   /* Crunch seed and secret password into starting key normally */
281   if (opiekeycrunch(algorithm, key, seed, secret)) {
282     fprintf(stderr, "%s: key crunch failed\n", argv[0]);
283     goto error;
284   }
285
286   for (i = 0; i <= (keynum - count); i++)
287     opiehash(key, algorithm);
288
289   {
290     char buf[OPIE_SEED_MAX + 48 + 1];
291     char *c;
292
293     for (; i <= keynum; i++) {
294       if (count > 1)
295         printf("%d: %s", i, (type == RESPONSE_STANDARD) ? "" : "\n");
296       
297       switch(type) {
298       case RESPONSE_STANDARD:
299         if (hex)
300           opiebtoh(response, key);
301         else
302           opiebtoe(response, key);
303         break;
304       case RESPONSE_WORD:
305         strcpy(response, "word:");
306         strcat(response, opiebtoe(buf, key));
307         break;
308       case RESPONSE_HEX:
309         strcpy(response, "hex:");
310         strcat(response, opiebtoh(buf, key));
311         break;
312       case RESPONSE_INIT_HEX:
313       case RESPONSE_INIT_WORD:
314         if (type == RESPONSE_INIT_HEX) {
315           strcpy(response, "init:");
316           strcat(response, opiebtoh(buf, key));
317           sprintf(buf, ":%s 499 %s:", algids[algorithm], newseed);
318           strcat(response, buf);
319           strcat(response, opiebtoh(buf, newkey));
320         } else {
321           strcpy(response, "init-word:");
322           strcat(response, opiebtoe(buf, key));
323           sprintf(buf, ":%s 499 %s:", algids[algorithm], newseed);
324           strcat(response, buf);
325           strcat(response, opiebtoe(buf, newkey));
326         }
327         break;
328       }
329       puts(response);
330       opiehash(key, algorithm);
331     }
332   }
333
334   memset(secret, 0, sizeof(secret));
335   memset(newsecret, 0, sizeof(newsecret));
336   return 0;
337
338 error:
339   memset(secret, 0, sizeof(secret));
340   memset(newsecret, 0, sizeof(newsecret));
341   return 1;
342 }