chiark / gitweb /
fix warnings
[nntp-merge-chiark.git] / nnrpwrap.c
1 /**/
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <ctype.h>
7 #include <errno.h>
8 #include <unistd.h>
9 #include <sys/socket.h>
10 #include <sys/time.h>
11 #include <arpa/inet.h>
12 #include <netinet/in.h>
13
14 #include "md5.h"
15
16 #define MAX_SECRET 64
17 #define NNRPDREAL "/usr/sbin/nnrpd.real"
18
19 static void chopspaces(char *buf) {
20   int n;
21   n= strlen(buf);
22   while (n > 0 && isspace(buf[n-1])) n--;
23   buf[n]= 0;
24 }
25
26 int main(int argc, char **argv) {
27   char *p, *q, **argvs;
28   unsigned char message[16+MAX_SECRET], expect[16];
29   char responsebuf[300];
30   char sesamebuf[MAX_SECRET*2+100];
31   struct sockaddr_in peername;
32   int c, namesize, n, l;
33   struct MD5Context md5ctx;
34   FILE *file;
35   unsigned long ul;
36   unsigned short us;
37   struct timeval timevab;
38
39   argvs= argv;
40   while ((p= *++argvs)) {
41     if (*p++ != '-') break;
42     c= *p++;
43     if (!c) break;
44     do {
45       if (c == 'r') {
46         if (*++argvs) {
47           printf("400 %s\r\n",*argvs); exit(1);
48         }
49         --argvs;
50         break;
51       } else if (c == 's' || c == 'S') {
52         if (!*++argvs) --argvs;
53         break;
54       }
55       c= *p++;
56     } while (c);
57   }
58
59   if (gettimeofday(&timevab,(void*)0)) {
60     printf("400 what year is it: %s\r\n",strerror(errno));
61     exit(1);
62   }
63   memcpy(message,&timevab.tv_sec,4);
64   ul= timevab.tv_usec; memcpy(message+4,&ul,4);
65   namesize= sizeof(peername);
66   if (getsockname(fileno(stdin),(struct sockaddr*)&peername,&namesize) &&
67       namesize == sizeof(peername) &&
68       peername.sin_family == AF_INET) {
69     memcpy(message+8,&peername.sin_addr,4);
70     memcpy(message+12,&peername.sin_port,2);
71   } else {
72     memset(message+8,'x',6);
73   }
74   us= getpid(); memcpy(message+14,&us,2);
75
76   printf("480 ");
77   for (n=0; n<16; n++) {
78     printf("%s%02x", n?":":"", message[n]);
79   }
80   printf("  halt !  who goes there ?\r\n");
81   if (fflush(stdout) || ferror(stdout)) { perror("stdout challenge"); exit(1); }
82   if (!fgets(responsebuf,sizeof(responsebuf),stdin)) {
83     if (ferror(stdin)) perror("stdin response");
84     else fprintf(stderr,"stdin response EOF\n");
85     exit(1);
86   }
87   chopspaces(responsebuf);
88   p= strchr(responsebuf,' ');
89   if (p) *p++= 0;
90   if (!strcasecmp(responsebuf,"QUIT")) {
91     printf("205 please remember your papers next time.\r\n");
92     exit(0);
93   }
94   if (strcasecmp(responsebuf,"PASS")) {
95     printf("500 guards !  guards !\r\n"
96            "400 this client was just leaving.\r\n");
97     exit(1);
98   }
99   if (!p) {
100     printf("501 fail.\r\n"
101            "400 we don't want failures here.\r\n");
102     exit(1);
103   }
104   file= fopen("/etc/news/sesame","r");
105   if (!file) {
106     printf("400 suddenly i can't see anything: %s\r\n",strerror(errno));
107     exit(1);
108   }
109   do {
110     if (!fgets(sesamebuf,sizeof(sesamebuf),file)) {
111       if (ferror(file)) {
112         printf("400 i'm not sure about that: %s\r\n",strerror(errno));
113       } else {
114         printf("400 happiness is mandatory.\r\n");
115       }
116       exit(1);
117     }
118     chopspaces(sesamebuf);
119   } while (!*sesamebuf || *sesamebuf == '#' || !(q= strchr(sesamebuf,' ')));
120   *q++= 0;
121   l= strlen(q);
122   if (l>MAX_SECRET) { printf("400 i feel all bloated.\r\n"); exit(1); }
123   memcpy(message+16,q,l);
124
125   MD5Init(&md5ctx);
126   MD5Update(&md5ctx,message,16+l);
127   MD5Final(expect,&md5ctx);
128
129   for (n=0; n<16; n++) sprintf(sesamebuf+n*3,"%02x:",expect[n]);
130   sesamebuf[47]= 0;
131   if (!strcasecmp(p,sesamebuf)) {
132     execvp(NNRPDREAL,argv);
133     printf("400 o master, i have failed you: %s\r\n",strerror(errno));
134     exit(1);
135   }
136   printf("502 impostor !\r\n"
137          "400 do not darken my door again.\r\n");
138   exit(1);
139 }