I have the following code to connect to a remote machine and execute commands.It is working if I create a new session for each Invoke-Command call to the remote machine. I don't want to create a new session each time I use Invoke-Command as that will not scale for thousands of commands on hundreds of machines concurrently and session creation itself is a big overhead. I need a way so that I can reuse the same session object in the $session powershell variable for multiple Invoke-Command calls to the remote machines.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
public class PowerShellSession {
private static String subModule = "PowerShellSession";
String targetIpAddress;
String username;
String password;
public static Object connectPShellLock = new Object();
public PowerShellSession() {}
public void exec(String cmd, String credentials) {
String ex = "Invoke-Command -Session $session -ScriptBlock {" + cmd + "} -Computer " + targetIpAddress;
String[] args = new String[] { "powershell", ex};
try {
execRemote(args);
} catch (IOException e) {
e.printStackTrace();
}
}
public void close() {
String command = "Exit-PSSession";
String[] args = new String[] { "powershell", command};
try {
execRemote(args);
} catch (IOException e) {
e.printStackTrace();
}
}
private String getCredentials(String domain, String userName,
String password) throws IOException {
String creds = "$PlainPassword ='" + password
+ "'; $SecurePassword = $PlainPassword | ConvertTo-SecureString -AsPlainText -Force;"
+ "$mycred = new-object -typename System.Management.Automation.PSCredential('" + userName + "', $SecurePassword);";
creds += "$session = New-PSSession -ComputerName " + domain + " -Credential $mycred;";
String[] args = new String[] { "powershell", creds};
execRemote(args);
return creds;
}
private void execRemote(String[] arguments) throws IOException {
ProcessBuilder builder = new ProcessBuilder(arguments);
builder.redirectErrorStream(true);
Process process = builder.start();
doProcessIO(process);
}
// Do the IO for a passed process
private void doProcessIO(Process p) throws IOException {
p.getOutputStream().close();
String line;
System.out.println("Output:");
BufferedReader stdout = new BufferedReader(new InputStreamReader(
p.getInputStream()));
while ((line = stdout.readLine()) != null) {
System.out.println(line);
}
stdout.close();
System.out.println("Error:");
BufferedReader stderr = new BufferedReader(new InputStreamReader(
p.getErrorStream()));
while ((line = stderr.readLine()) != null) {
System.out.println(line);
}
stderr.close();
// System.out.println("Done");
}
public static void main(String[] args) throws IOException {
PowerShellSession psSession = new PowerShellSession();
String credentials = psSession.getCredentials("9.120.241.195", "username", "password");
psSession.targetIpAddress = "9.120.241.195";
if(!credentials.equals("")) {
Scanner input = new Scanner(System.in);
while(true) {
System.out.print("PS C:\\Windows\\system32> ");
String cmd = input.nextLine();
if(cmd.equals("q") || cmd.equals("e") || cmd.equals("quit") || cmd.equals("exit")) break;
psSession.username = "username";
psSession.password = "password";
psSession.exec(cmd, "");
}
System.out.println("Finished PowerShell remote session.");
input.close();
}
psSession.close();
}
}
See there are lot of logics involves in this which can help you.
Your session invoking is fine; But you cannot directly run a PS command like that. You have to invoke the powershell.exe first then you have to give the respective remote commands what you want to execute.
Finally you have execute the command you will prepare. Let me share you a sample code:
public String executeScript(String psFileName, Systems system) throws NMAException {
Runtime runtime = Runtime.getRuntime();
String filePath = ApplicationProperties.getPropertyValue("powershell.scripts.location");
String command;
switch (psFileName) {
case "TerminalServersSystemInfo.ps1":
command = POWERSHELL + filePath + psFileName + " " + system.getPassword() + " " + system.getUserName()
+ " " + system.getSystemName();
break;
case "SQLServerInfo.ps1":
command = POWERSHELL + filePath + psFileName + " " + system.getSystemName() + " "
+ system.getUserName() + " " + system.getPassword();
break;
case "MyPS.ps1":
{
command = POWERSHELL + filePath + psFileName + " " + system.getSystemName() + " "
+ system.getUserName()
+ " " + system.getPassword() + " " + system.getDatabaseName();
break;
}
default:
throw new NMAException("not available");
}
Here is how you should form the command object in Java and then you should execute this:
powershell -ExecutionPolicy Bypass -NoLogo -NoProfile -Command {Invoke-command ......}
For triggering a PS file you can use the -Filepath switch.
Next this will help you in executing that:
proc = runtime.exec(command);
proc.getOutputStream().close();
InputStream is = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader reader = new BufferedReader(isr);
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
reader.close();
proc.getOutputStream().close();
LOGGER.info("Command: " + command);
LOGGER.info("Result:" + sb.toString());
return sb.toString();
Hope it gives you a set off.
public class PowerShellSession {
private static String subModule = "PowerShellSession";
String targetIpAddress;
String username;
String password;
public static Object connectPShellLock = new Object();
public PowerShellSession() {}
public void exec(String cmd, String credentials) {
String ex = credentials +" Invoke-Command -ScriptBlock {" + cmd + "} -ComputerName " + targetIpAddress +" -Credential $mycred";
String[] args = new String[] { "powershell", ex};
try {
execRemote(args);
} catch (IOException e) {
e.printStackTrace();
}
}
public void close() {
String command = "Exit-PSSession";
String[] args = new String[] { "powershell", command};
try {
execRemote(args);
} catch (IOException e) {
e.printStackTrace();
}
}
private String getCredentials(String domain, String userName,
String password) throws IOException {
String creds = "$Username = '"+userName+"';$PlainPassword ='" + password
+ "'; $SecurePassword = ConvertTo-SecureString -AsPlainText $PlainPassword -Force;"
+ "$mycred = New-Object System.Management.Automation.PSCredential -ArgumentList $Username, $SecurePassword;";
//creds += "$session = New-PSSession -ComputerName " + domain + " -Credential $mycred;";
String[] args = new String[] { "powershell", creds};
execRemote(args);
return creds;
}
private void execRemote(String[] arguments) throws IOException {
ProcessBuilder builder = new ProcessBuilder(arguments);
builder.redirectErrorStream(true);
Process process = builder.start();
doProcessIO(process);
}
// Do the IO for a passed process
private void doProcessIO(Process p) throws IOException {
p.getOutputStream().close();
String line;
System.out.println("Output:");
BufferedReader stdout = new BufferedReader(new InputStreamReader(
p.getInputStream()));
while ((line = stdout.readLine()) != null) {
System.out.println(line);
}
stdout.close();
System.out.println("Error:");
BufferedReader stderr = new BufferedReader(new InputStreamReader(
p.getErrorStream()));
while ((line = stderr.readLine()) != null) {
System.out.println(line);
}
stderr.close();
System.out.println("Done");
}
public static void main(String[] args) throws IOException {
PropertiesFileReader propReader = new PropertiesFileReader(System.getProperty("user.dir")+"/cred.properties");
String user = propReader.getPropertyData("user");
String pass = propReader.getPropertyData("pass");
String ip_add = propReader.getPropertyData("ip");
PowerShellSession psSession = new PowerShellSession();
String credentials = psSession.getCredentials(ip_add, user, pass);
psSession.targetIpAddress = ip_add;//;
String cmdd = propReader.getPropertyData("command");//"Get-Culture";
if(!credentials.equals("")) {
psSession.exec(cmdd, credentials);
System.out.println("Finished PowerShell remote session.");
}
psSession.close();
}
}
Related
I'm trying to make ftpclient which will use only sockets. I'm making a connection with server but I don't have idea how to display files. Here is my code:
package pl.edu.ftp;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.*;
import pl.edu.config.ConfigData;
public class FTPProtocol {
private Socket socket;
private BufferedReader reader;
private OutputStreamWriter writer;
private Socket socket2;
private BufferedReader reader2;
private OutputStreamWriter writer2;
private String serverImportantOutput;
private boolean firstSocket = true;
public void makeConnection(ConfigData configData) throws UnknownHostException, IOException, InterruptedException {
socket = new Socket(configData.getServerAddress(), configData.getPort());
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
writer = new OutputStreamWriter(socket.getOutputStream());
(new Thread(new Runnable() {
public void run() {
try {
String line;
if (firstSocket == true) {
while ((line = reader.readLine()) != null) {
System.out.println("SERVER: " + line);
if (line.startsWith("227 Entering Passive Mode")) {
serverImportantOutput = line;
}
}
} else {
while ((line = reader.readLine()) != null) {
System.out.println("SERVER: " + line);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
})).start();
Thread.sleep(2000);
sendCommand("USER " + configData.getUsername());
sendCommand("PASS " + configData.getPassword());
sendCommand("SYST");
sendCommand("FEAT");
sendCommand("PWD");
sendCommand("TYPE I");
sendCommand("PWD");
List<String> newData = sendCommandPasv("PASV");
socket2 = new Socket(newData.get(0), Integer.parseInt(newData.get(1)));
reader2 = new BufferedReader(new InputStreamReader(socket2.getInputStream()));
writer2 = new OutputStreamWriter(socket2.getOutputStream());
sendCommand2("LIST");
}
private void sendCommand(String command) throws IOException, InterruptedException {
firstSocket = true;
writer.write(command + "\r\n");
writer.flush();
System.out.println("Client:" + command);
Thread.sleep(2000);
}
private void sendCommand2(String command) throws IOException, InterruptedException {
firstSocket = true;
writer2.write(command + "\r\n");
writer2.flush();
System.out.println("Client:" + command);
Thread.sleep(2000);
firstSocket = false;
Thread.sleep(2000);
}
private List<String> sendCommandPasv(String command) throws IOException, InterruptedException {
List<String> listOfStrings = new ArrayList<String>();
writer.write(command + "\r\n");
writer.flush();
System.out.println("Client:" + command);
Thread.sleep(2000);
String fullAdress = serverImportantOutput.substring(serverImportantOutput.indexOf("(") + 1,
serverImportantOutput.indexOf(")"));
List<String> partsOfAdress = Arrays.asList(fullAdress.replaceAll("\\s+", "").split(","));
String host = partsOfAdress.get(0) + "." + partsOfAdress.get(1) + "." + partsOfAdress.get(2) + "."
+ partsOfAdress.get(3);
String port = Integer
.toString(Integer.parseInt(partsOfAdress.get(4)) * 256 + Integer.parseInt(partsOfAdress.get(5)));
System.out.println("Host: " + host);
System.out.println("Port: " + port);
listOfStrings.add(host);
listOfStrings.add(port);
return listOfStrings;
}
}
I tried to use LIST, NLST, MLSD but still nothing work. In console I have:
SERVER: 227 Entering Passive Mode (127,0,0,1,197,183)
Host: 127.0.0.1
Port: 50615
Client:LIST
And "Client:LIST" I have to wait very long. After that I got:
SERVER: 421 Connection timed out.
Somebody have maybe any idea what I'm doing wrong?
I edited now this method:
private void sendCommand2(String command) throws IOException, InterruptedException {
writer.write(command + "\r\n");
writer.flush();
System.out.println("Client:" + command);
firstSocket = false;
Thread.sleep(2000);
}
And now as result I have:
SERVER: 227 Entering Passive Mode (127,0,0,1,196,72)
Host: 127.0.0.1
Port: 50248
Client:LIST
SERVER: 150 Opening data channel for directory listing of "/"
SERVER: 226 Successfully transferred "/"
But it still doesn't display any files.
Now I edited to read from reader2 when "bool firstSocket" is false. So it should read from "reader2" after sending "LIST" command, but it still display nothing.
(new Thread(new Runnable() {
public void run() {
try {
String line;
if (firstSocket == true) {
while ((line = reader.readLine()) != null) {
System.out.println("SERVER: " + line);
if (line.startsWith("227 Entering Passive Mode")) {
serverImportantOutput = line;
}
}
} else {
while ((line = reader2.readLine()) != null) {
System.out.println("SERVER: " + line);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
})).start();
You can try to connect to the IP/port returned in the PASV response only after receiving 1xx response to the LIST command.
You have to send the LIST command to the (main) control connection, not to the data connection.
Read RFC 959 for details.
import java.io.*;
public class Clasa {
public static void main(String args[]) {
try {
Runtime rt = Runtime.getRuntime();
String comand = "net start MySQL55";
Process pr = rt.exec(" cmd.exe /C " + "net start MySQL55");
BufferedReader input = new BufferedReader(
new InputStreamReader(pr.getInputStream()));
String line = null;
while ((line = input.readLine()) != null) {
System.out.println(line);
}
int exitVal = pr.waitFor();
System.out.println("Exited with error code " + exitVal);
} catch (Exception e) {
System.out.println(e.toString());
e.printStackTrace();
}
}
}
I try this and gives me the next error code: Exited with error code 2
I run my java webserver on port 6799
My directory has a txt.txt file and pdf.pdf file
When I give localhost:6799/txt.txt, it gives perfect output saying
GET /txt.txt HTTP/1.1HTTP/1.0 200 OK
Content-type: text/plain
This is a very simple text file
But when I give localhost:6799/pdf.pdf from browser, it gives java.lang.NullPointerException
This is my code
import java.net.*;
public final class WebServer {
public static void main(String args[]) throws Exception {
int port = 6799;
System.out.println("\nListening on port " + port);
ServerSocket listen = new ServerSocket(port);
while (true) {
Socket socket = listen.accept();
HttpRequest request = new HttpRequest(socket);
Thread thread = new Thread(request);
thread.start();
}
}
}
--
import java.io.*;
import java.net.*;
import java.util.StringTokenizer;
public final class HttpRequest implements Runnable {
final String CRLF = "\r\n";
Socket socket;
public HttpRequest(Socket socket) throws Exception {
this.socket = socket;
}
#Override
public void run() {
try {
processRequest();
} catch (Exception e) {
System.out.println(e);
}
}
private void processRequest() throws Exception {
BufferedReader br;
DataOutputStream dos;
try (InputStream is = socket.getInputStream()) {
br = new BufferedReader(new InputStreamReader(is));
String requestline = br.readLine();
System.out.println("\n" + requestline);
String headerLine = null;
while ((headerLine = br.readLine()).length() != 0) {
System.out.println(headerLine);
}
dos = new DataOutputStream(socket.getOutputStream());
dos.writeBytes(requestline);
StringTokenizer tokens = new StringTokenizer(requestline);
tokens.nextToken(); // skip over the method, which should be "GET"
String fileName = tokens.nextToken();
// Prepend a "." so that file request is within the current directory.
fileName = "." + fileName;
FileInputStream fis = null;
boolean fileExists = true;
try {
fis = new FileInputStream(fileName);
} catch (FileNotFoundException e) {
fileExists = false;
}
String statusLine = null;
String contentTypeLine = null;
String entityBody = null;
if (fileExists) {
statusLine = "HTTP/1.0 200 OK" + CRLF;
contentTypeLine = "Content-type: " + contentType(fileName) + CRLF;
} else {
statusLine = "HTTP/1.0 404 Not Found" + CRLF;
//contentTypeLine = "Content-type: " + "text/html" + CRLF;
entityBody = "<HTML>"
+ "<HEAD><TITLE>Not Found</TITLE></HEAD>"
+ "<BODY>Not Found</BODY></HTML>";
}
dos.writeBytes(statusLine);
dos.writeBytes(contentTypeLine);
dos.writeBytes(CRLF);
if (fileExists) {
sendBytes(fis, dos);
fis.close();
} else {
dos.writeBytes(entityBody);
}
}
br.close();
dos.close();
socket.close();
}
private void sendBytes(FileInputStream fis, DataOutputStream dos) throws IOException {
byte[] buffer = new byte[4096];
int bytes = 0;
while ((bytes = fis.read(buffer)) != -1) {
dos.write(buffer, 0, bytes);
}
}
private String contentType(String fileName) {
if (fileName.endsWith(".htm") || fileName.endsWith(".html")) {
return "text/html";
}
if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) {
return "image/jpeg";
}
if (fileName.endsWith(".gif")) {
return "image/gif";
}
if (fileName.endsWith(".txt")) {
return "text/plain";
}
if (fileName.endsWith(".pdf")) {
return "application/pdf";
}
return "application/octet-stream";
}
}
STACK TRACE
java.lang.NullPointerException
at java.io.DataOutputStream.writeBytes(DataOutputStream.java:274)
at HttpRequest.processRequest(HttpRequest.java:65)
at HttpRequest.run(HttpRequest.java:20)
at java.lang.Thread.run(Thread.java:724)
At least one issue is this code:
while ((headerLine = br.readLine()).length() != 0) {
System.out.println(headerLine);
}
BufferedReader will return null at the end of the stream, so calling .length() on a null object will yield a NullPointerException.
A more idiomatic way to write this is:
while ((headerLine = br.readLine()) != null && headerLine.length() != 0) {
System.out.println(headerLine);
}
...which takes advantage of short-circuit logic to not evaluate the second condition if the result of (headerLine = br.readLine()) is null.
It is happening because for some reason you have toggled comment on the following line:
//contentTypeLine = "Content-type: " + "text/html" + CRLF;
Untoggle it and you're good!
So I have a Server/Client layer app running between my application and database. I would like to get an array from the Server. I will paste some pieces of code which I think is enough to give you an idea of what is going on:
I send to the server the keyword for search in database (user and his password)
fromUser = Musername + "," + Password;
out.println(fromUser);
Here is the code of the Server:
public class Server {
public static String[] theOutput;
public static String inputLine;
public static String[] string_array;
public static String output = "";
public static String[] process(String Input) throws Exception {
String[] data = Input.split(",");
// Call database class to get the results and store them into the array
load_login pridobi = new load_login();
theOutput = pridobi.nalozi(data[0], data[1]);
return theOutput;
}
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(4444);
} catch (IOException e) {
System.exit(1);
}
Socket clientSocket = null;
try {
clientSocket = serverSocket.accept();
} catch (IOException e) {
System.exit(1);
}
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
// get the username and password
inputLine = in.readLine();
if (inputLine.length() != 0) {
string_array = process(inputLine);
}
// And here I would like to do something like that :/
out.println(string_array);
}
}
PS: NOTE that some array elements are actually long text.
I recommended you use other technically.
what happended if username and password that you send to the server contain a ",".
When you split you obtain a wrong data.
Before send: Example:
String username = URLEncoder.encoder("myusername", "utf-8");
String password = URLEncoder.encoder("mypassword", "utf-8");
String dataToSend = username + "," + password;
In your server:
String[] data = Input.split(",");
data[0] = URLDecoder.decoder(data[0],"utf-8");
data[1] = URLDecoder.decoder(data[1],"utf-8");
The server should response a string like this:
String responseData = URLEncoder.encoder(theOutput[0], "utf-8") + "," + URLEncoder.encoder(theOutput[1], "utf-8");
out.println(responseData);
The client side read the response like this:
String dataReceived = inputLine = in.readLine();
String data[] = dataReceived.split(",");
data[0] = URLDecoder.decoder(data[0],"utf-8");
data[1] = URLDecoder.decoder(data[1],"utf-8");
I am getting into the Defunct zombie process whenever the below code is executed. Could someone help me to resolve this issue.
private static boolean executeCommand(String command)
throws ClientException, IOException, InterruptedException {
int exitVal = 1; // 0 is success, so we default to a nonzero.
Process proc = null;
try{
Runtime rt = Runtime.getRuntime();
proc = rt.exec(command);
//Below lines are required to flush out the streams. else the process will hang.
ReadStream s1 = new ReadStream("stdin", proc.getInputStream ());
ReadStream s2 = new ReadStream("stderr", proc.getErrorStream ());
s1.start ();
s2.start ();
exitVal = proc.waitFor();
if (exitVal == 0) {
return true;
} else {
throw new ClientException("103", "" + command + " failed.");
}
}finally{
if(proc != null){
proc.destroy();
}
}
}
I am clearing all the streams in separate threads.
Here is my ReadStream class
public class ReadStream implements Runnable {
private static Logger logger = Logger.getLogger(ReadStream.class);
String name;
InputStream is;
Thread thread;
public ReadStream(String name, InputStream is) {
this.name = name;
this.is = is;
}
public void start() {
thread = new Thread(this);
thread.start();
}
public void run() {
try {
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
while (true) {
String s = br.readLine();
if (s == null)
break;
logger.info("[" + name + "] " + s);
}
is.close();
} catch (Exception ex) {
logger.error("Problem reading stream " + name + "... :" + ex);
}
}
}
I dont think this is the problem but try to change the run methode to:
try {
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
do {
String s = br.readLine();
if (s != null)
logger.info("[" + name + "] " + s);
} while (s != null);
is.close();
} catch (Exception ex) {
logger.error("Problem reading stream " + name + "... :" + ex);
}