ref: 3e05a1d462b44a519621901be94566e9300eca93
dir: /cpu.c/
/*
* cpu.c - Make a connection to a cpu server
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <openssl/ssl.h>
#include <u.h>
#include <args.h>
#include <libc.h>
#include <auth.h>
#include <authsrv.h>
#include <libsec.h>
#include "fncs.h"
char *argv0;
char *authserver;
static char *user, *pass;
SSL_CTX *ssl_ctx;
SSL *ssl_conn;
//callback needs access to ai returned from p9any
static AuthInfo *ai;
static uint
psk_client_cb(SSL *ssl, const char *hint, char *identity, uint max_iden_len, uchar *psk, uint max_psk_len)
{
uint nsecret = ai->nsecret;
char i[] = "p9secret";
if(max_iden_len < sizeof i || max_psk_len < ai->nsecret)
sysfatal("psk buffers are too small");
memcpy(identity, i, sizeof i);
memcpy(psk, ai->secret, ai->nsecret);
memset(ai, 0, sizeof *ai);
return nsecret;
}
/*
* p9any authentication followed by tls-psk encryption
*/
static int
p9authtls(int fd)
{
ai = p9any(user, pass, fd);
if(ai == nil)
sysfatal("can't authenticate");
SSL_set_fd(ssl_conn, fd);
if(SSL_connect(ssl_conn) < 0)
sysfatal("ssl could not connect");
return fd;
}
typedef size_t (*iofunc)(int, void*, size_t);
size_t tls_send(int f, void *b, size_t n) { return SSL_write(ssl_conn, b, n); }
size_t tls_recv(int f, void *b, size_t n) { return SSL_read(ssl_conn, b, n); }
size_t s_send(int f, void *b, size_t n) { return write(f, b, n); }
size_t s_recv(int f, void *b, size_t n) { return read(f, b, n); }
void
xfer(int from, int to, iofunc recvf, iofunc sendf)
{
char buf[12*1024];
size_t n;
while((n = recvf(from, buf, sizeof buf)) > 0){
if(sendf(to, buf, n) < 0)
break;
}
}
void
usage(void)
{
fprint(2, "Usage: %s [ -R ] [ -u user ] [ -h host ] [ -a authserver ] -p port cmd...\n", argv0);
exits("usage");
}
int
main(int argc, char **argv)
{
int Rflag;
int fd;
char buf2[1024];
char buf[1024];
size_t n;
char *port;
char *host;
int pin[2];
int pout[2];
int infd, outfd;
int i;
pid_t execc, xferc;
execc = xferc = 0;
Rflag = 0;
infd = 0;
outfd = 1;
user = getenv("USER");
host = getenv("CPU");
authserver = getenv("AUTH");
pass = getenv("PASS");
port = nil;
ARGBEGIN {
case 'u': user = EARGF(usage()); break;
case 'h': host = EARGF(usage()); break;
case 'a': authserver = EARGF(usage()); break;
case 'p': port = EARGF(usage()); break;
case 'R': Rflag++; break;
} ARGEND
if(Rflag)
port = "17019";
if(user == nil || host == nil || authserver == nil || port == nil)
usage();
if(pass == nil)
pass = getpass("password:");
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
ssl_ctx = SSL_CTX_new(TLSv1_2_client_method());
SSL_CTX_set_psk_client_callback(ssl_ctx, psk_client_cb);
if(ssl_ctx == nil)
sysfatal("could not init openssl");
ssl_conn = SSL_new(ssl_ctx);
if(*argv && !Rflag){
pipe(pin);
pipe(pout);
switch((execc = fork())){
case -1:
sysfatal("fork");
case 0:
close(pin[1]);
close(pout[0]);
dup2(pin[0], 0);
dup2(pout[1], 1);
execvp(argv[0], argv);
sysfatal("exec");
}
close(pout[1]);
close(pin[0]);
infd = pout[0];
outfd = pin[1];
}
fd = unix_dial(host, port);
if(fd < 0){
sysfatal("Failed to connect to the client");
}
p9authtls(fd);
if(*argv && Rflag) {
for(i=0,n=0; i<argc; i++)
n += snprint(buf+n, sizeof buf - n - 1, "%s ", argv[i]);
if(n <= 0)
usage();
buf[n-1] = '\n';
buf[n] = '\0';
i = strlen(buf);
snprint(buf2, sizeof buf2, "%7d\n", i);
tls_send(-1, buf2, strlen(buf2));
tls_send(-1, buf, i);
}
switch((xferc = fork())){
case -1:
sysfatal("fork");
case 0:
xfer(infd, -1, s_recv, tls_send);
break;
default:
xfer(-1, outfd, tls_recv, s_send);
break;
}
if(xferc)
kill(xferc, SIGTERM);
if(execc)
kill(execc, SIGTERM);
}