package hudson.plugins.ec2.win; import hudson.plugins.ec2.win.winrm.WinRM; import hudson.plugins.ec2.win.winrm.WindowsProcess; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.InetSocketAddress; import java.net.Socket; import java.net.URLEncoder; import java.util.regex.Pattern; import jcifs.smb.NtlmPasswordAuthentication; import jcifs.smb.SmbFile; import jcifs.util.LogStream; import static java.util.regex.Pattern.quote; import java.util.logging.Level; import java.util.logging.Logger; public class WinConnection { private static final Logger log = Logger.getLogger(WinConnection.class.getName()); // ^[a-zA-Z]\:(\\|\/)([^\\\/\:\*\?\<\>\"\|]+(\\|\/){0,1})+$ private static final Pattern VALIDATE_WINDOWS_PATH = Pattern.compile("^[A-Za-z]:\\\\[-a-zA-Z0-9_.\\\\]*"); private final String host; private final String username; private final String password; private final NtlmPasswordAuthentication authentication; private boolean useHTTPS; private static final int TIMEOUT=8000; //8 seconds public WinConnection(String host, String username, String password) { this.host = host; this.username = username; this.password = password; this.authentication = new NtlmPasswordAuthentication(null, username, password); if(log.isLoggable(Level.FINE)){ LogStream.level=6; } } public WinRM winrm() { WinRM winrm = new WinRM(host, username, password); winrm.setUseHTTPS(useHTTPS); return winrm; } public WinRM winrm(int timeout) { WinRM winrm = winrm(); winrm.setTimeout(timeout); return winrm; } public WindowsProcess execute(String commandLine) { return execute(commandLine, 60); } public WindowsProcess execute(String commandLine, int timeout) { return winrm(timeout).execute(commandLine); } public OutputStream putFile(String path) throws IOException { SmbFile smbFile = new SmbFile(encodeForSmb(path), authentication); return smbFile.getOutputStream(); } public InputStream getFile(String path) throws IOException { SmbFile smbFile = new SmbFile(encodeForSmb(path), authentication); return smbFile.getInputStream(); } public boolean exists(String path) throws IOException { SmbFile smbFile = new SmbFile(encodeForSmb(path), authentication); return smbFile.exists(); } private String encodeForSmb(String path) { if (!VALIDATE_WINDOWS_PATH.matcher(path).matches()) { throw new IllegalArgumentException("Path '" + path + "' is not a valid windows path like C:\\Windows\\Temp"); } StringBuilder smbUrl = new StringBuilder(smbURLPrefix()); smbUrl.append(toAdministrativeSharePath(path).replace('\\', '/')); return smbUrl.toString(); } private static String toAdministrativeSharePath(String path) { // administrative windows share are DRIVE$path like return path.substring(0, 1) + "$" + path.substring(2); } private String smbURLPrefix() { StringBuilder prefix = new StringBuilder(); prefix.append("smb://"); if (username != null) { prefix.append(urlEncode(username.replaceFirst(quote("\\"), ";"))) .append(':') .append(urlEncode(password)) .append('@'); } // port? prefix.append(urlEncode(host)); prefix.append('/'); return prefix.toString(); } private static String urlEncode(String value) { try { return URLEncoder.encode(value, "UTF-8"); } catch (UnsupportedEncodingException e) { throw new RuntimeException("Invalid SMB URL", e); } } public boolean ping() { log.log(Level.FINE, "pinging " + host); try { Socket socket=new Socket(); socket.connect(new InetSocketAddress(host, 445), TIMEOUT); socket.close(); winrm().ping(); SmbFile test = new SmbFile(smbURLPrefix()+"IPC$", authentication); test.connect(); return true; } catch (Exception e) { log.log(Level.WARNING, "Failed to verify connectivity to Windows slave", e); return false; } } public void close() { } public void setUseHTTPS(boolean useHTTPS) { this.useHTTPS = useHTTPS; } }