> Date: Tue, 30 Dec 2014 11:46:38 -0500
> From: Ted Unangst <[email protected]>
>
> RFC 864 specifies the chargen service. The RFC recommends a recognizable
> pattern, but it was also written at a time when the internet was a
> kindler, gentler place. A better recommendation for the modern
> internet would be to produce random data.
>
> Diff follows. IMO the code is easier to reason about without the
> ring arithmetic. Benchmarking reveals the code is slightly slower now
> (8MB/s vs 10MB/s), but I think that's an acceptable tradeoff.
Jesus Ted, now you're defenitely beating dead horses.
inetd is disabled by default, within the default inetd.conf chargen is
disabled. If people still manage to enable this code, they deserve
what they get.
Besides I really don't understand what issue this tries to address.
Are you setting a trap for some poor Linux user who will blindly adopt
this "OpenBSD made chargen secure" diff on a system with a poor
arc4random implementation, exposing the internal state of the speudo
random generator to the internets?
Oh, and Wikipedia calls the existing pattern a "de facto standard".
> Index: inetd.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/inetd/inetd.c,v
> retrieving revision 1.142
> diff -u -p -r1.142 inetd.c
> --- inetd.c 29 Oct 2014 03:33:14 -0000 1.142
> +++ inetd.c 30 Dec 2014 16:39:09 -0000
> @@ -286,7 +286,6 @@ char *CONFIG = _PATH_INETDCONF;
>
> int dg_badinput(struct sockaddr *sa);
> void inetd_setproctitle(char *a, int s);
> -void initring(void);
> u_int32_t machtime(void);
>
> int
> @@ -1507,47 +1506,39 @@ discard_dg(int s, struct servtab *sep)
>
> #include <ctype.h>
> #define LINESIZ 72
> -char ring[128];
> -char *endring;
> +char charset[128];
> +int numcharset;
>
> void
> -initring(void)
> +initcharset(void)
> {
> int i;
> + char *p;
>
> - endring = ring;
> -
> - for (i = 0; i <= sizeof ring; ++i)
> + p = charset;
> + for (i = 0; i <= sizeof charset; ++i)
> if (isprint((unsigned char)i))
> - *endring++ = i;
> + *p++ = i;
> + numcharset = p - charset;
> }
>
> /* ARGSUSED */
> void
> chargen_stream(int s, struct servtab *sep)
> {
> - char *rs;
> - int len;
> char text[LINESIZ+2];
> + int i;
>
> inetd_setproctitle(sep->se_service, s);
>
> - if (!endring) {
> - initring();
> - rs = ring;
> - }
> + if (!numcharset)
> + initcharset();
>
> text[LINESIZ] = '\r';
> text[LINESIZ + 1] = '\n';
> - for (rs = ring;;) {
> - if ((len = endring - rs) >= LINESIZ)
> - memmove(text, rs, LINESIZ);
> - else {
> - memmove(text, rs, len);
> - memmove(text + len, ring, LINESIZ - len);
> - }
> - if (++rs == endring)
> - rs = ring;
> + while (1) {
> + for (i = 0; i < LINESIZ; i++)
> + text[i] = charset[arc4random_uniform(numcharset)];
> if (write(s, text, sizeof(text)) != sizeof(text))
> break;
> }
> @@ -1559,15 +1550,12 @@ void
> chargen_dg(int s, struct servtab *sep)
> {
> struct sockaddr_storage ss;
> - static char *rs;
> - int len;
> + int i;
> socklen_t size;
> char text[LINESIZ+2];
>
> - if (endring == 0) {
> - initring();
> - rs = ring;
> - }
> + if (!numcharset)
> + initcharset();
>
> size = sizeof(ss);
> if (recvfrom(s, text, sizeof(text), 0, (struct sockaddr *)&ss,
> @@ -1576,14 +1564,8 @@ chargen_dg(int s, struct servtab *sep)
> if (dg_badinput((struct sockaddr *)&ss))
> return;
>
> - if ((len = endring - rs) >= LINESIZ)
> - memmove(text, rs, LINESIZ);
> - else {
> - memmove(text, rs, len);
> - memmove(text + len, ring, LINESIZ - len);
> - }
> - if (++rs == endring)
> - rs = ring;
> + for (i = 0; i < LINESIZ; i++)
> + text[i] = charset[arc4random_uniform(numcharset)];
> text[LINESIZ] = '\r';
> text[LINESIZ + 1] = '\n';
> (void) sendto(s, text, sizeof(text), 0, (struct sockaddr *)&ss, size);
>
>