1 /* opieauto.c: The opieauto program.
4 This software is Copyright 1996-2001 by Craig Metz, All Rights Reserved.
5 The Inner Net License Version 3 applies to this software.
6 You should have received a copy of the license with this software. If
7 you didn't get a copy, you may request one from <license@inner.net>.
11 Created by cmetz for OPIE 2.4 based on previously released
12 test code. Use opiestrncpy().
16 #include <sys/types.h>
17 #include <sys/socket.h>
21 #endif /* HAVE_SYS_TIME_H */
26 #endif /* HAVE_STRING_H */
30 #endif /* HAVE_STDLIB_H */
33 #endif /* HAVE_UNISTD_H */
39 #define max(x, y) (((x) > (y)) ? (x) : (y))
48 int parents, s[MAXCLIENTS + 1];
50 char cmd[1+1+1+1+4+1+OPIE_SEED_MAX+1+4+1+4+1+4+1+4+1];
53 struct cachedotp *next;
54 int algorithm, base, current;
55 struct opie_otpkey basekey;
56 char seed[OPIE_SEED_MAX+1];
59 struct cachedotp *head = NULL;
61 char *algids[] = { NULL, NULL, NULL, "sha1", "md4", "md5" };
64 fprintf(stderr, "%s: %s: %s(%d)\n", myname, x, strerror(errno), errno);
69 fprintf(stderr, "%s: %s\n", myname, x);
75 struct cachedotp *c = head, *c2;
79 memset(c, 0, sizeof(struct cachedotp));
86 int algorithm, sequence, i;
87 char *seed = NULL, *response = NULL;
89 if (((cmd[0] != 'S') && (cmd[0] != 's')) || (cmd[1] != '=') || (cmd[2] != ' ')) {
91 fprintf(stderr, "%s: got bogus command: %s\n", myname, cmd);
99 if (((algorithm = strtoul(&cmd[3], &c, 10)) < 3) || (algorithm > 5) || (*c != ' ')) {
101 fprintf(stderr, "%s: got bogus algorithm: %s\n", myname, cmd);
106 if (((sequence = strtoul(c + 1, &c, 10)) <= OPIE_SEQUENCE_RESTRICT) || (sequence > OPIE_SEQUENCE_MAX)) {
108 fprintf(stderr, "%s: got bogus sequence: %s\n", myname, cmd);
114 if (!(c = strchr(seed = c + 1, ' '))) {
116 fprintf(stderr, "%s: got bogus seed: %s\n", myname, cmd);
123 if (!(c = strchr(response = c + 1, '\n'))) {
125 fprintf(stderr, "%s: got bogus response: %s\n", myname, cmd);
132 if (!(c = strchr(seed = c + 1, '\n'))) {
134 fprintf(stderr, "%s: got bogus seed: %s\n", myname, cmd);
144 fprintf(stderr, "got cmd=%c, algorithm=%d sequence=%d seed=+%s+ response=+%s+ on fd %d\n", cmd[0], algorithm, sequence, seed, response, fd);
151 fprintf(stderr, "sequence < 10; can't do it\n");
153 sprintf(cmd, "%c- %d %d %s\n", cmd[0], algorithm, sequence, seed);
157 struct cachedotp **c;
159 for (c = &head; *c && (strcmp((*c)->seed, seed) || ((*c)->algorithm != algorithm)); c = &((*c)->next));
163 fprintf(stderr, "(seed, algorithm) not found for s command\n");
165 sprintf(cmd, "s- %d %d %s\n", algorithm, sequence, seed);
169 if (!(*c = malloc(sizeof(struct cachedotp))))
171 memset(*c, 0, sizeof(struct cachedotp));
173 (*c)->algorithm = algorithm;
174 opiestrncpy((*c)->seed, seed, OPIE_SEED_MAX);
178 (*c)->base = max(sequence - window + 1, OPIE_SEQUENCE_RESTRICT);
179 (*c)->current = sequence;
181 if (!opieatob8(&(*c)->basekey, response))
184 sprintf(cmd, "S+ %d %d %s\n", algorithm, sequence, (*c)->seed);
186 if (sequence != ((*c)->current - 1)) {
188 fprintf(stderr, "out of sequence: sequence=%d, base=%d, current=%d\n", sequence, (*c)->base, (*c)->current);
190 sprintf(cmd, "s- %d %d %s\n", algorithm, sequence, (*c)->seed);
194 if (sequence < (*c)->base) {
196 fprintf(stderr, "attempt to generate below base: sequence=%d, base=%d, current=%d\n", sequence, (*c)->base, (*c)->current);
198 sprintf(cmd, "s- %d %d %s\n", algorithm, sequence, (*c)->seed);
202 (*c)->current = sequence;
203 i = sequence - (*c)->base;
205 struct opie_otpkey key;
210 opiehash(&key, algorithm);
212 opiebtoa8(buffer, &key);
213 sprintf(cmd, "s+ %d %d %s %s\n", algorithm, sequence, (*c)->seed, buffer);
217 printf("%c otp-%s %d %s (%d/%d)\n", cmd[0], algids[algorithm], sequence, (*c)->seed, sequence - (*c)->base, window);
220 if (sequence == (*c)->base) {
221 struct cachedotp *c2 = *c;
223 memset(c2, 0, sizeof(struct cachedotp));
229 write(fd, cmd, i = strlen(cmd));
234 fprintf(stderr, "Invalid command on fd %d\n", fd);
242 fprintf(stderr, "usage: %s [-v] [-h] [-q] [-n <number of OTPs>]\n", myname);
246 int main(int argc, char **argv)
252 if (myname = strrchr(argv[0], '/'))
257 while((i = getopt(argc, argv, "w:hv")) != EOF) {
263 if (!(window = atoi(optarg))) {
264 fprintf(stderr, "%s: invalid number of OTPs: %s\n", myname, optarg);
277 if (!(myuid = getuid()) || !(myeuid = geteuid()) || (myuid != myeuid))
278 bail("this program must not be run with superuser priveleges or setuid.");
281 if (atexit(zerocache) < 0)
285 struct sockaddr_un sun;
287 memset(&sun, 0, sizeof(struct sockaddr_un));
288 sun.sun_family = AF_UNIX;
292 char *c2 = "/.opieauto";
294 if (!(c = getenv("HOME")))
295 bail("getenv(HOME) failed -- no HOME variable?");
297 if (strlen(c) > (sizeof(sun.sun_path) - strlen(c2) - 1))
298 bail("your HOME is too long");
300 strcpy(sun.sun_path, c);
301 strcat(sun.sun_path, c2);
302 sockpath = strdup(sun.sun_path);
305 if ((parents = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
308 if (unlink(sockpath) && (errno != ENOENT))
314 if (bind(parents, (struct sockaddr *)&sun, sizeof(struct sockaddr_un)))
317 if (stat(sockpath, &st) < 0)
320 if ((st.st_uid != myuid) || (!S_ISSOCK(st.st_mode)) || ((st.st_mode & 07777) != 0600))
321 bail("socket permissions and/or ownership were not correctly created.");
323 if (listen(parents, 1) < 0)
328 fd_set fds, rfds, efds;
333 FD_SET(parents, &fds);
336 memcpy(&rfds, &fds, sizeof(fd_set));
338 if (select(maxfd + 1, &rfds, NULL, NULL, NULL) < 0)
341 for (i = 0; s[i]; i++) {
342 if (!FD_ISSET(s[i], &rfds))
345 if (((j = read(s[i], cmd, sizeof(cmd)-1)) <= 0) || ((cmd[j] = 0) || doreq(s[i]))) {
352 for (j = i; s[j]; s[j] = s[j + 1], j++);
353 FD_SET(parents, &fds);
359 if (FD_ISSET(parents, &rfds)) {
360 for (i = 0; s[i]; i++)
362 bail("this message never printed");
364 if (stat(sockpath, &st) < 0)
367 if ((st.st_uid != myuid) || (!S_ISSOCK(st.st_mode)) || ((st.st_mode & 07777) != 0600))
368 bail("socket permissions and/or ownership has been messed with.");
370 if ((s[i] = accept(parents, NULL, 0)) < 0)
377 sprintf(cmd, "C+ %d\n", window);
378 if (write(s[i], cmd, j = strlen(cmd)) != j)
381 if (++i == MAXCLIENTS)
382 FD_CLR(parents, &fds);