chiark / gitweb /
new lwc_fixed for distrib.pats and distributions
[nntp-merge-chiark.git] / sharedsecret.c
1 /**/
2
3 #include <stdlib.h>
4 #include <string.h>
5 #include <stdio.h>
6 #include <errno.h>
7 #include <unistd.h>
8
9 #include "md5.h"
10 #define MAX_SECRET 100
11
12 static void ohshit(const char *p) {
13   fprintf(stderr,"md5cookie1way: fatal error: %s\n",p); exit(1);
14 }
15
16 static void ohshite(const char *p) {
17   fprintf(stderr,"md5cookie1way: fatal system error: %s: %s\n",p,strerror(errno));
18   exit(1);
19 }
20
21 static void try(FILE **fp, const char *fn) {
22   if (*fp) return;
23   *fp= fopen(fn,"r");
24 }
25
26 static int parsehex(char *p, unsigned char *up, int maxlen) {
27   int nused, v, n;
28   
29   nused= 0;
30   while (nused < maxlen && (n=-1, sscanf(p,"%x%n",&v,&n) >0) && n>0) {
31     p+= n;
32     *up++= v;
33     nused++;
34     if (*p == ':') p++;
35   }
36   return nused;
37 }
38
39 int main(int argc, char **argv) {
40   char *authfds, *claim, *here, *p;
41   int rfd, wfd, n, nused;
42   char buf[200];
43   unsigned char message[16+MAX_SECRET], reply[16];
44   struct MD5Context md5ctx;
45   FILE *file;
46
47   if (argc != 2) ohshit("bad args");
48   claim= argv[1];
49
50   authfds= getenv("NNTP_AUTH_FDS"); if (!authfds) ohshit("no NNTP_AUTH_FDS");
51   p= strchr(authfds,'.'); if (!p) ohshit("no . in NNTP_AUTH_FDS");
52   rfd= atoi(authfds);
53   wfd= atoi(p+1);
54   dup2(rfd,0); dup2(wfd,1);
55
56   file= 0;
57   if ((p= getenv("HOME"))) {
58     sprintf(buf,"%.180s/News/md5cookies",p); try(&file,buf);
59     sprintf(buf,"%.180s/.newscookies",p); try(&file,buf);
60   }
61   try(&file,"/etc/news/md5cookies.read");
62   try(&file,"/etc/news/md5cookies");
63   if (!file) ohshite("no cookies file");
64
65   for (;;) {
66     errno= 0; if (!(fgets(buf,sizeof(buf),file))) ohshite("no line for claim");
67     if (!*buf || *buf == '\n' || *buf == '#' || *buf == '@') continue;
68     here= strtok(buf," \t\n");
69     if (!here) continue;
70     if (!strcmp(here,claim)) break;
71   }
72
73   p= strtok(0," \t\n");
74   if (!p) ohshit("no cookie on line");
75
76   nused= parsehex(p,message+16,MAX_SECRET);
77
78   errno= 0; if (!fgets(buf,sizeof(buf),stdin)) ohshite("no comm with server");
79   if (strncmp(buf,"100 ",4)) {
80     fprintf(stderr,"\nunable to authenticate - server sent:\n %s",buf);
81     exit(1);
82   }
83
84   if (parsehex(buf+4,message,17) != 16) ohshit("server sent wrong amount of hex");
85
86   MD5Init(&md5ctx);
87   MD5Update(&md5ctx,message,16+nused);
88   MD5Final(reply,&md5ctx);
89
90   printf("MD5 ");
91   for (n=0; n<16; n++) {
92     printf("%s%02x", n?":":"", reply[n]);
93   }
94   printf("\r\n");
95   fflush(stdout);
96
97   errno= 0; if (!fgets(buf,sizeof(buf),stdin)) ohshite("no reply from server");
98   if (strncmp(buf,"281",3)) ohshit("server didn't send 281");
99
100   exit(0);
101 }