]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/tlsclient.c
disk/format: implement long name support
[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, *dumpcert;
10
11 void
12 usage(void)
13 {
14         fprint(2, "usage: tlsclient [-D] [-a [-k keyspec] ] [-c clientcert.pem] [-d servercert] [-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, dfd;
47         char *addr;
48         TLSconn *conn;
49         Thumbprint *thumb;
50         AuthInfo *ai = nil;
51
52         fmtinstall('[', encodefmt);
53         fmtinstall('H', encodefmt);
54
55         ARGBEGIN{
56         case 'D':
57                 debug++;
58                 break;
59         case 'a':
60                 auth++;
61                 break;
62         case 'k':
63                 keyspec = EARGF(usage());
64                 break;
65         case 't':
66                 file = EARGF(usage());
67                 break;
68         case 'x':
69                 filex = EARGF(usage());
70                 break;
71         case 'c':
72                 ccert = EARGF(usage());
73                 break;
74         case 'd':
75                 dumpcert = EARGF(usage());
76                 break;
77         case 'n':
78                 servername = EARGF(usage());
79                 break;
80         case 'o':
81                 dialfile = 1;
82                 break;
83         default:
84                 usage();
85         }ARGEND
86
87         if(argc < 1)
88                 usage();
89
90         if(filex && !file)      
91                 sysfatal("specifying -x without -t is useless");
92
93         if(file){
94                 thumb = initThumbprints(file, filex, "x509");
95                 if(thumb == nil)
96                         sysfatal("initThumbprints: %r");
97         } else
98                 thumb = nil;
99
100         addr = *argv++;
101         if((fd = dialfile? open(addr, ORDWR): dial(addr, 0, 0, 0)) < 0)
102                 sysfatal("dial %s: %r", addr);
103
104         conn = (TLSconn*)mallocz(sizeof *conn, 1);
105         conn->serverName = servername;
106         if(ccert){
107                 conn->cert = readcert(ccert, &conn->certlen);
108                 if(conn->cert == nil)
109                         sysfatal("readcert: %r");
110         }
111
112         if(auth){
113                 ai = auth_proxy(fd, auth_getkey, "proto=p9any role=client %s", keyspec);
114                 if(ai == nil)
115                         sysfatal("auth_proxy: %r");
116
117                 conn->pskID = "p9secret";
118                 conn->psk = ai->secret;
119                 conn->psklen = ai->nsecret;
120         }
121
122         if(debug)
123                 conn->trace = reporter;
124
125         fd = tlsClient(fd, conn);
126         if(fd < 0)
127                 sysfatal("tlsclient: %r");
128
129         if(dumpcert){
130                 if((dfd = create(dumpcert, OWRITE, 0666)) < 0)
131                         sysfatal("create: %r");
132                 if(conn->cert != nil)
133                         write(dfd, conn->cert, conn->certlen);
134                 write(dfd, "", 0);
135                 close(dfd);
136         }
137
138         if(thumb){
139                 if(!okCertificate(conn->cert, conn->certlen, thumb))
140                         sysfatal("cert for %s not recognized: %r", servername ? servername : addr);
141                 freeThumbprints(thumb);
142         }
143
144         free(conn->cert);
145         free(conn->sessionID);
146         free(conn);
147         if(ai != nil)
148                 auth_freeAI(ai);
149
150         if(*argv){
151                 dup(fd, 0);
152                 dup(fd, 1);
153                 if(fd > 1)
154                         close(fd);
155                 exec(*argv, argv);
156                 sysfatal("exec: %r");
157         }
158
159         rfork(RFNOTEG);
160         switch(fork()){
161         case -1:
162                 sysfatal("fork: %r");
163         case 0:
164                 xfer(0, fd);
165                 break;
166         default:
167                 xfer(fd, 1);
168                 break;
169         }
170         postnote(PNGROUP, getpid(), "die yankee pig dog");
171         exits(0);
172 }