added tls code to client
This commit is contained in:
parent
5d66a9880c
commit
3021a1d405
2 changed files with 96 additions and 51 deletions
|
|
@ -51,7 +51,7 @@ openssl genrsa -passout pass:${CLTCAPASS} -aes256 -out $CLIENT_PATH/private.key
|
||||||
echo "[+] Generating Client signing request"
|
echo "[+] Generating Client signing request"
|
||||||
openssl req -passin pass:${CLTCAPASS} -new -key $CLIENT_PATH/private.key -out $CLIENT_PATH/request.csr -subj "/CN=${CLIENT_CN}"
|
openssl req -passin pass:${CLTCAPASS} -new -key $CLIENT_PATH/private.key -out $CLIENT_PATH/request.csr -subj "/CN=${CLIENT_CN}"
|
||||||
echo "[+] Generating Client certificate "
|
echo "[+] Generating Client certificate "
|
||||||
openssl x509 -req -passin pass:${CLTCAPASS} -days 365 -in $CLIENT_PATH/request.csr -CA $CLIENT_PATH/ca.crt -CAkey $CLIENT_PATH/ca.key -set_serial 01 -out $CLIENT_PATH/server.crt
|
openssl x509 -req -passin pass:${CLTCAPASS} -days 365 -in $CLIENT_PATH/request.csr -CA $CLIENT_PATH/ca.crt -CAkey $CLIENT_PATH/ca.key -set_serial 01 -out $CLIENT_PATH/client.crt
|
||||||
echo "[+] Removing passphrase from client key"
|
echo "[+] Removing passphrase from client key"
|
||||||
openssl rsa -passin pass:${CLTCAPASS} -in $CLIENT_PATH/private.key -out $CLIENT_PATH/private.key
|
openssl rsa -passin pass:${CLTCAPASS} -in $CLIENT_PATH/private.key -out $CLIENT_PATH/private.key
|
||||||
|
|
||||||
|
|
@ -61,7 +61,7 @@ openssl genrsa -passout pass:dontusethiskey -aes256 -out $TEST_PATH/private.key
|
||||||
echo "[+] Generating test signing request"
|
echo "[+] Generating test signing request"
|
||||||
openssl req -passin pass:dontusethiskey -new -key $TEST_PATH/private.key -out $TEST_PATH/request.csr -subj "/CN=${DontUseMe}"
|
openssl req -passin pass:dontusethiskey -new -key $TEST_PATH/private.key -out $TEST_PATH/request.csr -subj "/CN=${DontUseMe}"
|
||||||
echo "[+] Generating test certificate "
|
echo "[+] Generating test certificate "
|
||||||
openssl x509 -req -passin pass:dontusethiskey -days 365 -in $TEST_PATH/request.csr -CA $TEST_PATH/ca.crt -CAkey $TEST_PATH/ca.key -set_serial 01 -out $TEST_PATH/server.crt
|
openssl x509 -req -passin pass:dontusethiskey -days 365 -in $TEST_PATH/request.csr -CA $TEST_PATH/ca.crt -CAkey $TEST_PATH/ca.key -set_serial 01 -out $TEST_PATH/test.crt
|
||||||
echo "[+] Removing passphrase from test key"
|
echo "[+] Removing passphrase from test key"
|
||||||
openssl rsa -passin pass:dontusethiskey -in $TEST_PATH/private.key -out $TEST_PATH/private.key
|
openssl rsa -passin pass:dontusethiskey -in $TEST_PATH/private.key -out $TEST_PATH/private.key
|
||||||
|
|
||||||
|
|
@ -75,4 +75,4 @@ echo "[+] creating combine trust store"
|
||||||
cat $SERVER_PATH/ca.crt $CLIENT_PATH/ca.crt > resources/truststore.pem
|
cat $SERVER_PATH/ca.crt $CLIENT_PATH/ca.crt > resources/truststore.pem
|
||||||
|
|
||||||
echo "[+] initiating gradle build"
|
echo "[+] initiating gradle build"
|
||||||
./gradlew clear build
|
./gradlew clean build
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,13 @@ package JobServ;
|
||||||
import io.grpc.ManagedChannel;
|
import io.grpc.ManagedChannel;
|
||||||
import io.grpc.ManagedChannelBuilder;
|
import io.grpc.ManagedChannelBuilder;
|
||||||
import io.grpc.StatusRuntimeException;
|
import io.grpc.StatusRuntimeException;
|
||||||
|
import io.grpc.netty.GrpcSslContexts;
|
||||||
|
import io.grpc.netty.NettyChannelBuilder;
|
||||||
|
import io.netty.handler.ssl.SslContext;
|
||||||
|
import io.netty.handler.ssl.SslContextBuilder;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLException;
|
||||||
|
import java.io.File;
|
||||||
import java.util.InputMismatchException;
|
import java.util.InputMismatchException;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
@ -23,7 +30,8 @@ import java.util.Scanner;
|
||||||
*/
|
*/
|
||||||
public class JobServClient {
|
public class JobServClient {
|
||||||
|
|
||||||
/* The client should not use the same logging module as the server.
|
/*
|
||||||
|
* The client should not use the same logging module as the server.
|
||||||
* In a more robust product the server logging module will take advantage of system level
|
* In a more robust product the server logging module will take advantage of system level
|
||||||
* log aggregators such as journalctl, which the client should not be writing to on the users system
|
* log aggregators such as journalctl, which the client should not be writing to on the users system
|
||||||
*/
|
*/
|
||||||
|
|
@ -31,33 +39,49 @@ public class JobServClient {
|
||||||
|
|
||||||
private final ManagedChannel channel;
|
private final ManagedChannel channel;
|
||||||
|
|
||||||
/* blockingStub is used when the client needs to block until the server responds
|
/*
|
||||||
|
* blockingStub is used when the client needs to block until the server responds
|
||||||
* the client doesnt nessesarily need to support asynchronously firing off commands
|
* the client doesnt nessesarily need to support asynchronously firing off commands
|
||||||
* in this shell-like interface it would be disconcerting to get multiple returns out of order
|
* in this shell-like interface it would be disconcerting to get multiple returns out of order
|
||||||
*/
|
*/
|
||||||
private final ShellServerGrpc.ShellServerBlockingStub blockingStub;
|
private final ShellServerGrpc.ShellServerBlockingStub blockingStub;
|
||||||
|
|
||||||
// Constructor connects to server
|
/*
|
||||||
public JobServClient(String host, int port) {
|
* Constructor
|
||||||
this(ManagedChannelBuilder.forAddress(host, port)
|
* Creates an SslContext from cert, key, and trust store
|
||||||
// TODO: MTLS
|
* Creates a ManagedChannel object from SSL Parameters
|
||||||
.usePlaintext()
|
* Spawns a new blockingStub for network operations with the server
|
||||||
.build());
|
*/
|
||||||
}
|
public JobServClient(String host,
|
||||||
|
int port,
|
||||||
// private overload of constructor, used in the above constructor
|
String trustStore,
|
||||||
JobServClient(ManagedChannel channel) {
|
String clientCert,
|
||||||
this.channel = channel;
|
String clientPrivateKey) throws SSLException {
|
||||||
blockingStub = ShellServerGrpc.newBlockingStub(channel);
|
SslContextBuilder builder = GrpcSslContexts.forClient();
|
||||||
|
builder.trustManager(new File(trustStore));
|
||||||
|
builder.keyManager(new File(clientCert), new File(clientPrivateKey));
|
||||||
|
|
||||||
|
this.channel = NettyChannelBuilder.forAddress(host, port)
|
||||||
|
.sslContext(builder.build())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
blockingStub = ShellServerGrpc.newBlockingStub(this.channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* shutdown()
|
||||||
|
* Gets called when you press cntrl+c
|
||||||
|
* takes at most 5 seconds to close its connection
|
||||||
|
*/
|
||||||
public void shutdown() throws InterruptedException {
|
public void shutdown() throws InterruptedException {
|
||||||
channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
|
channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// sends the server a request for output from PID
|
/*
|
||||||
// different from getProcessStatus in output expected from the server
|
* getProcessInfo()
|
||||||
// returns process output as string
|
* sends the server a request for output from the process identified by 'pid'
|
||||||
|
* returns process output as string
|
||||||
|
*/
|
||||||
public String getProcessOutput(int pid) {
|
public String getProcessOutput(int pid) {
|
||||||
logger.info("[+] requesting output");
|
logger.info("[+] requesting output");
|
||||||
|
|
||||||
|
|
@ -77,8 +101,11 @@ public class JobServClient {
|
||||||
return response.getOutput();
|
return response.getOutput();
|
||||||
}
|
}
|
||||||
|
|
||||||
// sends the server a command for a new job, blocks until response
|
/*
|
||||||
// returns new pid of job
|
* sendNewJobMessage()
|
||||||
|
* sends a shell command to the api server
|
||||||
|
* returns new pid of job
|
||||||
|
*/
|
||||||
public int sendNewJobMessage(String command) {
|
public int sendNewJobMessage(String command) {
|
||||||
// thought of escaping this, but the vulnerability is only client side, from client user input.
|
// thought of escaping this, but the vulnerability is only client side, from client user input.
|
||||||
logger.info("[+] Sending command to server");
|
logger.info("[+] Sending command to server");
|
||||||
|
|
@ -103,8 +130,11 @@ public class JobServClient {
|
||||||
return response.getPid();
|
return response.getPid();
|
||||||
}
|
}
|
||||||
|
|
||||||
// requests running status of job
|
/*
|
||||||
// returns true if job still running else false
|
* getProcessStatus()
|
||||||
|
* requests running status of process pid
|
||||||
|
* returns true if process still running else false
|
||||||
|
*/
|
||||||
public Boolean getProcessStatus(int pid) {
|
public Boolean getProcessStatus(int pid) {
|
||||||
logger.info("[+] Requesting status of a job");
|
logger.info("[+] Requesting status of a job");
|
||||||
|
|
||||||
|
|
@ -124,9 +154,12 @@ public class JobServClient {
|
||||||
return response.getIsRunning();
|
return response.getIsRunning();
|
||||||
}
|
}
|
||||||
|
|
||||||
// sends PID to server expecting the return cod eof a process
|
/*
|
||||||
// function returns a 0-255 return code or 277 if still running
|
* sends PID to server
|
||||||
// or 278 if error in API
|
* returns process exit code
|
||||||
|
* returns a 0-255 return code or 277 if still running
|
||||||
|
* or 278 if error in API
|
||||||
|
*/
|
||||||
public int getProcessReturn(int pid) {
|
public int getProcessReturn(int pid) {
|
||||||
logger.info("[+] Requesting return code of a job");
|
logger.info("[+] Requesting return code of a job");
|
||||||
|
|
||||||
|
|
@ -146,8 +179,11 @@ public class JobServClient {
|
||||||
return response.getProcessReturnCode();
|
return response.getProcessReturnCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
// send a PID to be killed, returns nothing
|
/*
|
||||||
// logs warning if job status comes back still running
|
* killProcess()
|
||||||
|
* send a PID to be killed, function returns nothing
|
||||||
|
* logs warning if job status comes back still running
|
||||||
|
*/
|
||||||
public void killProcess(int pid) {
|
public void killProcess(int pid) {
|
||||||
logger.info("[+] Killing a job");
|
logger.info("[+] Killing a job");
|
||||||
|
|
||||||
|
|
@ -169,40 +205,49 @@ public class JobServClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client entrypoint
|
/*
|
||||||
|
* main()
|
||||||
|
* Client entrypoint
|
||||||
|
* Parses arguments and calls the correct function
|
||||||
|
*/
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
if (args.length == 1 && args[0] == "help"){
|
if (args.length == 1 && args[0] == "help"){
|
||||||
outputHelp();
|
outputHelp();
|
||||||
}
|
}
|
||||||
|
|
||||||
// check args
|
// check args
|
||||||
if (args.length < 3) {
|
if (args.length < 7) {
|
||||||
System.out.println("Usage: $ jobservclient host port command");
|
System.out.println("Usage: $ ./jobserv-client privatekey, cert, truststore, host, port, command, args");
|
||||||
System.out.println("Or try client --help");
|
System.out.println("Or try $ ./jobserv-client help");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// start client (or fail if port is improperly formatted)
|
// start client
|
||||||
|
// fails if port is improperly formatted or if an ssl exception occurs
|
||||||
JobServClient client;
|
JobServClient client;
|
||||||
try {
|
try {
|
||||||
client = new JobServClient(args[0], Integer.parseInt(args[1]));
|
client = new JobServClient(args[0], Integer.parseInt(args[1]), args[2], args[1], args[0]);
|
||||||
|
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
System.out.println("Invalid Port");
|
System.out.println("Invalid Port");
|
||||||
return;
|
return;
|
||||||
|
} catch (SSLException e) {
|
||||||
|
System.out.println(e.getMessage());
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// declare up here so that multiple switch cases can use it
|
// declare pid up here so that multiple switch cases can use it
|
||||||
int candidatePid;
|
int candidatePid;
|
||||||
|
// parse remaining args
|
||||||
switch (args[2]) {
|
switch (args[2]) {
|
||||||
case "new":
|
case "new":
|
||||||
if (args.length < 4) {
|
if (args.length < 7) {
|
||||||
System.out.println("Improper formatting, try client --help");
|
System.out.println("Improper formatting, try client --help");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
String command = "";
|
String command = "";
|
||||||
for (int token = 3; token < args.length; token++) {
|
for (int token = 6; token < args.length; token++) {
|
||||||
command += " " + args[token];
|
command += " " + args[token];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -211,15 +256,15 @@ public class JobServClient {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "output":
|
case "output":
|
||||||
if (args.length != 4) {
|
if (args.length != 7) {
|
||||||
System.out.println("Improper formatting, try client --help");
|
System.out.println("Improper formatting, try client --help");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
candidatePid = Integer.parseInt(args[3]);
|
candidatePid = Integer.parseInt(args[6]);
|
||||||
} catch (InputMismatchException e) {
|
} catch (InputMismatchException e) {
|
||||||
System.out.println(args[3] + " is not a valid int, much less a valid pid");
|
System.out.println(args[6] + " is not a valid int, much less a valid pid");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -228,16 +273,16 @@ public class JobServClient {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "status":
|
case "status":
|
||||||
if (args.length != 4) {
|
if (args.length != 7) {
|
||||||
System.out.println("Improper formatting, try client --help");
|
System.out.println("Improper formatting, try client --help");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
candidatePid = Integer.parseInt(args[3]);
|
candidatePid = Integer.parseInt(args[6]);
|
||||||
|
|
||||||
} catch (InputMismatchException e) {
|
} catch (InputMismatchException e) {
|
||||||
System.out.println(args[3] + " is not a valid int, much less a valid pid");
|
System.out.println(args[6] + " is not a valid int, much less a valid pid");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -246,16 +291,16 @@ public class JobServClient {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "kill":
|
case "kill":
|
||||||
if (args.length != 4) {
|
if (args.length != 7) {
|
||||||
System.out.println("Improper formatting, try client --help");
|
System.out.println("Improper formatting, try client --help");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
candidatePid = Integer.parseInt(args[3]);
|
candidatePid = Integer.parseInt(args[6]);
|
||||||
|
|
||||||
} catch (InputMismatchException e) {
|
} catch (InputMismatchException e) {
|
||||||
System.out.println(args[3] + " is not a valid int, much less a valid pid");
|
System.out.println(args[6] + " is not a valid int, much less a valid pid");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -264,16 +309,16 @@ public class JobServClient {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "return":
|
case "return":
|
||||||
if (args.length != 4) {
|
if (args.length != 7) {
|
||||||
System.out.println("Improper formatting, try client --help");
|
System.out.println("Improper formatting, try client --help");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
candidatePid = Integer.parseInt(args[3]);
|
candidatePid = Integer.parseInt(args[6]);
|
||||||
|
|
||||||
} catch (InputMismatchException e) {
|
} catch (InputMismatchException e) {
|
||||||
System.out.println(args[3] + " is not a valid int, much less a valid pid");
|
System.out.println(args[6] + " is not a valid int, much less a valid pid");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue