From 1a4e03cf93872eb78f498af8afd5d8c7d6143178 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Sun, 3 Apr 2022 04:19:46 +0000 Subject: [PATCH] ip/sol: kvm (vnc) redirect, bring back plain authentication as a fallback (when unsupported) --- sys/man/8/sol | 29 +++++++--- sys/src/cmd/ip/sol.c | 127 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 124 insertions(+), 32 deletions(-) diff --git a/sys/man/8/sol b/sys/man/8/sol index 106c3f656..be610c088 100644 --- a/sys/man/8/sol +++ b/sys/man/8/sol @@ -4,7 +4,7 @@ sol - Intel AMT serial-over-lan console .SH SYNOPSIS .B ip/sol [ -.B -rR +.B -TRrk ] [ .B -u .I user @@ -15,12 +15,10 @@ This program provides remote access to the serial-over-lan interface of intel AMT enabled machines. .PP -The protocol runs over tcp port 16995 and -and is protected using TLS. +The protocol runs over tcp ports 16994/16995 and +and is optinally protected using TLS. .PP -For authentication, a -.B proto=httpdigest -key with a username and password is required. +For authentication, a username and password is required. The default username, unless given by the .B -u @@ -30,6 +28,10 @@ The password will be prompted and kept in factotum. .PP The +.B -T +flag disables TLS encryption (enabled by default). +.PP +The .B -r and .B -R @@ -39,9 +41,20 @@ standard input and output. By default, raw mode is enabled when the .B $TERM environment variable has been set. +.PP +The +.B -k +flag connects to the VNC port instead. +.SH EXAMPLE +Connect to the KVM port with +.IR vnc(1): +.IP +.EX +execnet && vnc 'exec!ip/sol -k host' +.EE .SH SOURCE .B /sys/src/cmd/ip/sol.c .SH "SEE ALSO" -.IR ssh (1), -.IR consolefs (4), +.IR execnet (4), +.IR vncv (1), .IR factotum (4) diff --git a/sys/src/cmd/ip/sol.c b/sys/src/cmd/ip/sol.c index 659ddf7b7..13f66b61a 100644 --- a/sys/src/cmd/ip/sol.c +++ b/sys/src/cmd/ip/sol.c @@ -15,7 +15,10 @@ enum { HEATBEAT_INTERVAL = 5000, }; -int authok = 0, pid = 0, raw = -1, fd = -1; +char *user = "admin"; +int authok = 0, pid = 0, raw = -1, kvm = 0, fd = -1, tls = 1; +int reply, ok, n; +char buf[MAX_TRANSMIT_BUFFER]; Biobuf bin, bout; jmp_buf reconnect; @@ -123,12 +126,11 @@ send(char *fmt, ...) } } -void +int digestauth(char *server, char *user, char *method, char *url) { char realm[256+1], nonce[256+1], qop[256+1], nc[10], cnonce[32+1], chal[1024], resp[1024], ouser[256]; static uint counter; - int reply, ok, n; send("lblb[__b[____", 0x13, 4, 1+strlen(user) + 2 + 1+strlen(url) + 4, @@ -136,7 +138,7 @@ digestauth(char *server, char *user, char *method, char *url) strlen(url), url, strlen(url)); recv("lbl", &reply, &ok, &n); if(reply != 0x114 || ok != 4 || n == 0) - sysfatal("bad auth reply: %x %x", reply, ok); + return -1; /* not supported */ recv("b", &n); recv("[", realm, n); @@ -173,24 +175,52 @@ digestauth(char *server, char *user, char *method, char *url) strlen(qop), qop, strlen(qop)); recv("lb*", &reply, &ok); if(reply != 0x14 && ok != 4) - sysfatal("bad auth reply: %x %x", reply, ok); + sysfatal("bad digest auth reply: %x %x", reply, ok); + return 0; +} + +void +plainauth(char *user, char *pass) +{ + send("lblb[b[", 0x13, 1, + strlen(user)+1+strlen(pass)+1, + strlen(user), user, strlen(user), + strlen(pass), pass, strlen(pass)); + recv("lb*", &reply, &ok); + if(reply != 0x14 || ok != 1) + sysfatal("bad password auth reply: %x %x", reply, ok); +} + +void +auth(char *server, char *user) +{ + static UserPasswd *up = nil; + + if(up == nil){ + if(digestauth(server, user, "POST", "/RedirectionService") == 0) + return; + + /* if digest auth not supported, get plaintext password */ + up = auth_getuserpasswd(auth_getkey, + "proto=pass service=sol user=%q server=%q", + user, server); + if(up == nil) + sysfatal("auth_getuserpasswd: %r"); + longjmp(reconnect, 1); + } + plainauth(up->user, up->passwd); } void usage(void) { - fprint(2, "usage: %s [-Rr] [-u user] host\n", argv0); + fprint(2, "usage: %s [-TRrk] [-u user] host\n", argv0); exits("usage"); } void main(int argc, char *argv[]) { - uchar buf[MAX_TRANSMIT_BUFFER]; - TLSconn tls; - char *user = "admin"; - int reply, ok, n; - fmtinstall('[', encodefmt); fmtinstall('H', encodefmt); @@ -198,12 +228,18 @@ main(int argc, char *argv[]) case 'u': user = EARGF(usage()); break; + case 'T': + tls = 0; + break; case 'R': raw = 0; break; case 'r': raw = 1; break; + case 'k': + kvm = 1; + break; default: usage(); } ARGEND; @@ -211,6 +247,9 @@ main(int argc, char *argv[]) if(argc != 1) usage(); + if(kvm) + goto Connect; + if(raw < 0) { char *term = getenv("TERM"); raw = term && *term; @@ -230,18 +269,22 @@ main(int argc, char *argv[]) write(fd, "rawon", 5); } -Reconnect: - fd = dial(netmkaddr(argv[0], "tcp", "16995"), nil, nil, nil); +Connect: + fd = dial(netmkaddr(argv[0], "tcp", tls ? "16995" : "16994"), nil, nil, nil); if(fd < 0) sysfatal("dial: %r"); - memset(&tls, 0, sizeof(tls)); - fd = tlsClient(fd, &tls); - if(fd < 0) - sysfatal("tls client: %r"); - free(tls.cert); - free(tls.sessionID); - memset(&tls, 0, sizeof(tls)); + if(tls){ + TLSconn conn; + + memset(&conn, 0, sizeof(conn)); + fd = tlsClient(fd, &conn); + if(fd < 0) + sysfatal("tls: %r"); + free(conn.cert); + free(conn.sessionID); + memset(&conn, 0, sizeof(conn)); + } authok = 0; Binit(&bin, fd, OREAD); @@ -250,17 +293,52 @@ Reconnect: Bterm(&bin); Bterm(&bout); close(fd); - goto Reconnect; + goto Connect; } - send("l[", 0x10, "SOL ", 4); + if(kvm) + send("l[", 0x110, "KVMR", 4); + else + send("l[", 0x10, "SOL ", 4); + recv("lb*", &reply, &ok); if(reply != 0x11 || ok != 1) sysfatal("bad session reply: %x %x", reply, ok); - digestauth(argv[0], user, "POST", "/RedirectionService"); + auth(argv[0], user); authok = 1; + /* kvm port redirect */ + if(kvm){ + int from, to; + + send("b_______", 0x40); + if(read(fd, buf, 8) != 8 || buf[0] != 0x41) + sysfatal("bad redirection reply: %x %x", reply, ok); + + pid = fork(); + if(pid == 0){ + pid = getppid(); + from = 0; + to = fd; + } else { + from = fd; + to = 1; + } + atexit(killpid); + for(;;){ + n = read(from, buf, sizeof(buf)); + if(n < 0) + sysfatal("read: %r"); + if(n == 0) + break; + if(write(to, buf, n) != n) + sysfatal("write: %r"); + } + exits(nil); + } + + /* serial over lan */ send("l____wwwwww____", 0x20, MAX_TRANSMIT_BUFFER, TRANSMIT_BUFFER_TIMEOUT, @@ -270,7 +348,7 @@ Reconnect: HEATBEAT_INTERVAL); recv("lb*", &reply, &ok); if(reply != 0x21 || ok != 1) - sysfatal("bad redirection reply: %x %x", reply, ok); + sysfatal("bad sol reply: %x %x", reply, ok); pid = fork(); if(pid == 0){ @@ -305,5 +383,6 @@ Reconnect: } } } + exits(nil); }