]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/tlsclient.c
1b79fb739f57f9d4170f744e755c06e909c7e1d1
[plan9front.git] / sys / src / cmd / tlsclient.c
1 #include <u.h>
2 #include <libc.h>
3 #include <mp.h>
4 #include <libsec.h>
5 #include <auth.h>
6
7 int debug, auth, dialfile;
8 char *keyspec = "";
9 char *servername, *file, *filex, *ccert;
10
11 void
12 usage(void)
13 {
14         fprint(2, "usage: tlsclient [-D] [-a [-k keyspec] ] [-c lib/tls/clientcert] [-t /sys/lib/tls/xxx] [-x /sys/lib/tls/xxx.exclude] [-n servername] [-o] dialstring [cmd [args...]]\n");
15         exits("usage");
16 }
17
18 void
19 xfer(int from, int to)
20 {
21         char buf[12*1024];
22         int n;
23
24         while((n = read(from, buf, sizeof buf)) > 0)
25                 if(write(to, buf, n) < 0)
26                         break;
27 }
28
29 static int
30 reporter(char *fmt, ...)
31 {
32         va_list ap;
33         
34         va_start(ap, fmt);
35         fprint(2, "%s:  tls reports ", argv0);
36         vfprint(2, fmt, ap);
37         fprint(2, "\n");
38
39         va_end(ap);
40         return 0;
41 }
42
43 void
44 main(int argc, char **argv)
45 {
46         int fd;
47         char *addr;
48         TLSconn *conn;
49         Thumbprint *thumb;
50         AuthInfo *ai = nil;
51
52         fmtinstall('H', encodefmt);
53
54         ARGBEGIN{
55         case 'D':
56                 debug++;
57                 break;
58         case 'a':
59                 auth++;
60                 break;
61         case 'k':
62                 keyspec = EARGF(usage());
63                 break;
64         case 't':
65                 file = EARGF(usage());
66                 break;
67         case 'x':
68                 filex = EARGF(usage());
69                 break;
70         case 'c':
71                 ccert = EARGF(usage());
72                 break;
73         case 'n':
74                 servername = EARGF(usage());
75                 break;
76         case 'o':
77                 dialfile = 1;
78                 break;
79         default:
80                 usage();
81         }ARGEND
82
83         if(argc < 1)
84                 usage();
85
86         if(filex && !file)      
87                 sysfatal("specifying -x without -t is useless");
88
89         if(file){
90                 thumb = initThumbprints(file, filex, "x509");
91                 if(thumb == nil)
92                         sysfatal("initThumbprints: %r");
93         } else
94                 thumb = nil;
95
96         addr = *argv++;
97         if((fd = dialfile? open(addr, ORDWR): dial(addr, 0, 0, 0)) < 0)
98                 sysfatal("dial %s: %r", addr);
99
100         conn = (TLSconn*)mallocz(sizeof *conn, 1);
101         conn->serverName = servername;
102         if(ccert){
103                 conn->cert = readcert(ccert, &conn->certlen);
104                 if(conn->cert == nil)
105                         sysfatal("readcert: %r");
106         }
107
108         if(auth){
109                 ai = auth_proxy(fd, auth_getkey, "proto=p9any role=client %s", keyspec);
110                 if(ai == nil)
111                         sysfatal("auth_proxy: %r");
112
113                 conn->pskID = "p9secret";
114                 conn->psk = ai->secret;
115                 conn->psklen = ai->nsecret;
116         }
117
118         if(debug)
119                 conn->trace = reporter;
120
121         fd = tlsClient(fd, conn);
122         if(fd < 0)
123                 sysfatal("tlsclient: %r");
124
125         if(thumb){
126                 if(!okCertificate(conn->cert, conn->certlen, thumb))
127                         sysfatal("cert for %s not recognized: %r", servername ? servername : addr);
128                 freeThumbprints(thumb);
129         }
130
131         free(conn->cert);
132         free(conn->sessionID);
133         free(conn);
134         if(ai != nil)
135                 auth_freeAI(ai);
136
137         if(*argv){
138                 dup(fd, 0);
139                 dup(fd, 1);
140                 if(fd > 1)
141                         close(fd);
142                 exec(*argv, argv);
143                 sysfatal("exec: %r");
144         }
145
146         rfork(RFNOTEG);
147         switch(fork()){
148         case -1:
149                 sysfatal("fork: %r");
150         case 0:
151                 xfer(0, fd);
152                 break;
153         default:
154                 xfer(fd, 1);
155                 break;
156         }
157         postnote(PNGROUP, getpid(), "die yankee pig dog");
158         exits(0);
159 }