1/* readrec.c: The __opiereadrec() library function.
2
3%%% copyright-cmetz-96
4This software is Copyright 1996-2001 by Craig Metz, All Rights Reserved.
5The Inner Net License Version 3 applies to this software.
6You should have received a copy of the license with this software. If
7you didn't get a copy, you may request one from <license@inner.net>.
8
9	History:
10
11	Modified by cmetz for OPIE 2.4. Check that seed, sequence number, and
12		response values are valid.
13	Modified by cmetz for OPIE 2.31. Removed active attack protection
14		support. Fixed a debug message typo. Keep going after bogus
15                records. Set read flag.
16	Created by cmetz for OPIE 2.3.
17
18$FreeBSD: releng/10.3/contrib/opie/libopie/readrec.c 208586 2010-05-27 03:15:04Z cperciva $
19*/
20#include "opie_cfg.h"
21
22#include <stdio.h>
23#include <sys/types.h>
24#include <errno.h>
25#if HAVE_UNISTD_H
26#include <unistd.h>
27#endif /* HAVE_UNISTD_H */
28#if HAVE_STRING_H
29#include <string.h>
30#endif /* HAVE_STRING_H */
31#if HAVE_STDLIB_H
32#include <stdlib.h>
33#endif /* HAVE_STDLIB_H */
34#if HAVE_FCNTL_H
35#include <fcntl.h>
36#endif /* HAVE_FCNTL_H */
37#include <ctype.h>
38#include <errno.h>
39#if DEBUG
40#include <syslog.h>
41#endif /* DEBUG */
42#include "opie.h"
43
44static int parserec FUNCTION((opie), struct opie *opie)
45{
46  char *c, *c2;
47
48  if (!(c2 = strchr(opie->opie_principal = opie->opie_buf, ' ')))
49    return -1;
50
51  while(*c2 == ' ') c2++;
52  *(c2 - 1) = 0;
53
54  if (!(c2 = strchr(c = c2, ' ')))
55    return -1;
56
57  *(c2++) = 0;
58
59  {
60  char *c3;
61
62  opie->opie_n = strtoul(c, &c3, 10);
63
64  if (*c3 || (opie->opie_n <= 0) || (opie->opie_n > 9999))
65    return -1;
66  };
67
68  if (!(c2 = strchr(opie->opie_seed = c2, ' ')))
69    return -1;
70
71  *(c2++) = 0;
72
73  for (c = opie->opie_seed; *c; c++)
74    if (!isalnum(*c))
75      return -1;
76
77  while(*c2 == ' ') c2++;
78
79  if (!(c2 = strchr(opie->opie_val = c2, ' ')))
80    return -1;
81
82  *(c2++) = 0;
83
84  {
85  struct opie_otpkey otpkey;
86
87  if (!opieatob8(&otpkey, opie->opie_val))
88    return -1;
89  }
90
91  return 0;
92}
93
94int __opiereadrec FUNCTION((opie), struct opie *opie)
95{
96  FILE *f = NULL;
97  int rval = -1;
98
99  if (!(f = __opieopen(KEY_FILE, 0, 0600))) {
100#if DEBUG
101    syslog(LOG_DEBUG, "__opiereadrec: __opieopen(KEY_FILE..) failed!");
102#endif /* DEBUG */
103    goto ret;
104  }
105
106  {
107  int i;
108
109  if ((i = open(KEY_FILE, O_RDWR)) < 0) {
110    opie->opie_flags &= ~__OPIE_FLAGS_RW;
111#if DEBUG
112    syslog(LOG_DEBUG, "__opiereadrec: open(KEY_FILE, O_RDWR) failed: %s", strerror(errno));
113#endif /* DEBUG */
114  } else {
115    close(i);
116    opie->opie_flags |= __OPIE_FLAGS_RW;
117  }
118  }
119
120  if (opie->opie_buf[0]) {
121    if (fseek(f, opie->opie_recstart, SEEK_SET))
122      goto ret;
123
124    if (fgets(opie->opie_buf, sizeof(opie->opie_buf), f))
125      goto ret;
126
127    if (parserec(opie))
128      goto ret;
129
130    opie->opie_flags |= __OPIE_FLAGS_READ;
131    rval = 0;
132    goto ret;
133  }
134
135  if (!opie->opie_principal)
136    goto ret;
137
138  {
139    char *c, principal[OPIE_PRINCIPAL_MAX];
140    int i;
141
142    if (c = strchr(opie->opie_principal, ':'))
143      *c = 0;
144
145    strlcpy(principal, opie->opie_principal, sizeof(principal));
146
147    do {
148      if ((opie->opie_recstart = ftell(f)) < 0)
149	goto ret;
150
151      if (!fgets(opie->opie_buf, sizeof(opie->opie_buf), f)) {
152	rval = 1;
153	goto ret;
154      }
155
156      if (parserec(opie))
157	continue;
158    } while (strcmp(principal, opie->opie_principal));
159
160    rval = 0;
161  }
162
163ret:
164  if (f)
165    fclose(f);
166  return rval;
167}
168