]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/cmd/tlsclient.c
webfs(4): document -d and -D flags
[plan9front.git] / sys / src / cmd / tlsclient.c
old mode 100755 (executable)
new mode 100644 (file)
index 8bfff5d..06d34a3
@@ -2,11 +2,16 @@
 #include <libc.h>
 #include <mp.h>
 #include <libsec.h>
+#include <auth.h>
+
+int debug, auth, dialfile;
+char *keyspec = "";
+char *servername, *file, *filex, *ccert, *dumpcert;
 
 void
 usage(void)
 {
-       fprint(2, "usage: tlsclient [-t /sys/lib/tls/xxx] [-x /sys/lib/tls/xxx.exclude] dialstring\n");
+       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");
        exits("usage");
 }
 
@@ -21,65 +26,140 @@ xfer(int from, int to)
                        break;
 }
 
+static int
+reporter(char *fmt, ...)
+{
+       va_list ap;
+       
+       va_start(ap, fmt);
+       fprint(2, "%s:  tls reports ", argv0);
+       vfprint(2, fmt, ap);
+       fprint(2, "\n");
+
+       va_end(ap);
+       return 0;
+}
+
 void
 main(int argc, char **argv)
 {
-       int fd, netfd;
-       uchar digest[20];
-       TLSconn conn;
-       char *addr, *file, *filex;
+       int fd, dfd;
+       char *addr;
+       TLSconn *conn;
        Thumbprint *thumb;
+       AuthInfo *ai = nil;
+
+       fmtinstall('[', encodefmt);
+       fmtinstall('H', encodefmt);
 
-       file = nil;
-       filex = nil;
-       thumb = nil;
        ARGBEGIN{
+       case 'D':
+               debug++;
+               break;
+       case 'a':
+               auth++;
+               break;
+       case 'k':
+               keyspec = EARGF(usage());
+               break;
        case 't':
                file = EARGF(usage());
                break;
        case 'x':
                filex = EARGF(usage());
                break;
+       case 'c':
+               ccert = EARGF(usage());
+               break;
+       case 'd':
+               dumpcert = EARGF(usage());
+               break;
+       case 'n':
+               servername = EARGF(usage());
+               break;
+       case 'o':
+               dialfile = 1;
+               break;
        default:
                usage();
        }ARGEND
 
-       if(argc != 1)
+       if(argc < 1)
                usage();
 
        if(filex && !file)      
                sysfatal("specifying -x without -t is useless");
+
        if(file){
-               thumb = initThumbprints(file, filex);
+               thumb = initThumbprints(file, filex, "x509");
                if(thumb == nil)
                        sysfatal("initThumbprints: %r");
-       }
+       } else
+               thumb = nil;
 
-       addr = argv[0];
-       if((netfd = dial(addr, 0, 0, 0)) < 0)
+       addr = *argv++;
+       if((fd = dialfile? open(addr, ORDWR): dial(addr, 0, 0, 0)) < 0)
                sysfatal("dial %s: %r", addr);
 
-       memset(&conn, 0, sizeof conn);
-       fd = tlsClient(netfd, &conn);
+       conn = (TLSconn*)mallocz(sizeof *conn, 1);
+       conn->serverName = servername;
+       if(ccert){
+               conn->cert = readcert(ccert, &conn->certlen);
+               if(conn->cert == nil)
+                       sysfatal("readcert: %r");
+       }
+
+       if(auth){
+               ai = auth_proxy(fd, auth_getkey, "proto=p9any role=client %s", keyspec);
+               if(ai == nil)
+                       sysfatal("auth_proxy: %r");
+
+               conn->pskID = "p9secret";
+               conn->psk = ai->secret;
+               conn->psklen = ai->nsecret;
+       }
+
+       if(debug)
+               conn->trace = reporter;
+
+       fd = tlsClient(fd, conn);
        if(fd < 0)
                sysfatal("tlsclient: %r");
+
+       if(dumpcert){
+               if((dfd = create(dumpcert, OWRITE, 0666)) < 0)
+                       sysfatal("create: %r");
+               if(conn->cert != nil)
+                       write(dfd, conn->cert, conn->certlen);
+               write(dfd, "", 0);
+               close(dfd);
+       }
+
        if(thumb){
-               if(conn.cert==nil || conn.certlen<=0)
-                       sysfatal("server did not provide TLS certificate");
-               sha1(conn.cert, conn.certlen, digest, nil);
-               if(!okThumbprint(digest, thumb)){
-                       fmtinstall('H', encodefmt);
-                       sysfatal("server certificate %.*H not recognized", SHA1dlen, digest);
-               }
+               if(!okCertificate(conn->cert, conn->certlen, thumb))
+                       sysfatal("cert for %s not recognized: %r", servername ? servername : addr);
+               freeThumbprints(thumb);
+       }
+
+       free(conn->cert);
+       free(conn->sessionID);
+       free(conn);
+       if(ai != nil)
+               auth_freeAI(ai);
+
+       if(*argv){
+               dup(fd, 0);
+               dup(fd, 1);
+               if(fd > 1)
+                       close(fd);
+               exec(*argv, argv);
+               sysfatal("exec: %r");
        }
-       free(conn.cert);
-       close(netfd);
 
        rfork(RFNOTEG);
        switch(fork()){
        case -1:
-               fprint(2, "%s: fork: %r\n", argv0);
-               exits("dial");
+               sysfatal("fork: %r");
        case 0:
                xfer(0, fd);
                break;