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
);