summaryrefslogtreecommitdiffstats
path: root/contrib/opie/libopie/generator.c
blob: ccd67c7532f467a8aef5b3aec1bfa558c4ec3659 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/* generator.c: The opiegenerator() library function.

%%% portions-copyright-cmetz
Portions of this software are Copyright 1996 by Craig Metz, All Rights
Reserved. The Inner Net License Version 2 applies to these portions of
the software.
You should have received a copy of the license with this software. If
you didn't get a copy, you may request one from <license@inner.net>.

        History:

	Modified by cmetz for OPIE 2.3. Use _opieparsechallenge(). ifdef
	      around string.h. Output hex responses by default, output
	      OTP re-init extended responses (same secret) if sequence
	      number falls below 10.
	Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al.
              Bug fixes.
	Created at NRL for OPIE 2.2.
*/

#include "opie_cfg.h"
#if HAVE_STRING_H
#include <string.h>
#endif /* HAVE_STRING_H */
#include "opie.h"

static char *algids[] = { NULL, NULL, NULL, "sha1", "md4", "md5" };

int opiegenerator FUNCTION((buffer, secret, response), char *buffer AND char *secret AND char *response)
{
  int algorithm;
  int sequence;
  char *seed;
  char key[8];
  int i;

  if (!(buffer = strstr(buffer, "otp-")))
    return 1;

  buffer += 4;

  if (_opieparsechallenge(buffer, &algorithm, &sequence, &seed))
    return 1;

  if ((sequence < 2) || (sequence > 9999))
    return 1;

  if (opiepasscheck(secret))
    return -2;

  if (i = opiekeycrunch(algorithm, key, seed, secret))
    return i;

  if (sequence < 10) {
    char newseed[OPIE_SEED_MAX + 1];
    char newkey[8], cko[8], ckn[8], ckxor[8], cv[8];
    char *c;
    char buf[OPIE_SEED_MAX + 48 + 1];

    if (opienewseed(strcpy(newseed, seed)) < 0)
      return -1;

    if (opiekeycrunch(algorithm, newkey, newseed, secret))
      return -1;

    for (i = 0; i < 499; i++)
      opiehash(newkey, algorithm);

    if (opiekeycrunch(algorithm | 0x10, cko, seed, secret))
      return -1;

    if (opiekeycrunch(algorithm | 0x10, ckn, newseed, secret))
      return -1;

    for (i = 0; i < 8; i++)
      ckxor[i] = cko[i] ^ ckn[i];

    strcpy(response, "init:");
    strcat(response, opiebtoh(buf, key));
    sprintf(buf, ":%s 499 %s:", algids[algorithm], newseed);
    strcat(response, buf);
    strcat(response, opiebtoh(buf, newkey));
    strcat(response, ":");
    strcat(response, opiebtoh(buf, ckxor));
    strcat(response, ":");

    c = buf;
    memcpy(c, ckn, sizeof(ckn)); c += sizeof(ckn);
    memcpy(c, key, sizeof(key)); c += sizeof(key);
#ifdef HAVE_ANSISPRINTF
    c += sprintf(c, "%s 499 %s", algids[algorithm], newseed);
#else /* HAVE_ANSISPRINTF */
    sprintf(c, "%s 499 %s", algids[algorithm], newseed);
    while(*c) c++;
#endif /* HAVE_ANSISPRINTF */
    memcpy(c, newkey, sizeof(newkey)); c += sizeof(newkey);
    memcpy(c, ckxor, sizeof(ckxor)); c += sizeof(ckxor);
    memcpy(c, ckn, sizeof(ckn)); c += sizeof(ckn);
    opiehashlen(algorithm, buf, cv, (unsigned int)c - (unsigned int)buf);

    strcat(response, opiebtoh(buf, cv));
  } else {
    while (sequence-- != 0)
      opiehash(key, algorithm);
    
    opiebtoh(response, key);
  }

  return 0;
}
OpenPOWER on IntegriCloud