Exemplo n.º 1
0
        internal static SftpClient CreateSftpClient(this string connectionString)
        {
            if (connectionString == null)
            {
                throw new ArgumentNullException("connectionString");
            }

            // get parts of connection string
            var csb = new DbConnectionStringBuilder {
                ConnectionString = connectionString
            };
            var host     = csb["host"] as string;
            var username = csb["username"] as string;
            var password = csb["password"] as string;
            var hostkey  = csb["hostkey"] as string;
            var port     = Attempt.Get(() => Convert.ToInt32(csb["port"]));

            // do this when connstring is bad
            Action <string> badConnString = detail =>
            {
                throw new FormatException(
                          string.Format(
                              "SFTP connection string invalid. {0} Example: username=USERNAME;password=PASSWORD;host=HOSTNAME;hostkey=ssh-dss 1024 3b:1c:20:aa:27:00:83:4f:7a:49:9c:9f:e7:67:ab:03",
                              detail ?? ""));
            };

            // check required conn string params
            if (new[] { host, username, password, hostkey }.Any(string.IsNullOrWhiteSpace))
            {
                badConnString("Missing required parameter.");
            }

            // check format of host key
            var hostKeyParts =
                hostkey.Split().Where(x => !string.IsNullOrWhiteSpace(x)).Select(x => x.Trim().ToLower()).ToArray();

            // host key needs 3 parts: name, length, fingerprint
            if (hostKeyParts.Length != 3)
            {
                badConnString(string.Format("Host key '{0}' is incorrectly formatted.", hostkey));
            }

            // length neeeds to be an int
            int hostKeyLength;

            if (!int.TryParse(hostKeyParts[1], out hostKeyLength))
            {
                badConnString(string.Format("Host key length '{0}' is not an integer.", hostKeyParts[1]));
            }

            // finter print needs to be a byte array as hex string
            var hostKeyPrint =
                Attempt.Get(() => SoapHexBinary.Parse(string.Concat(hostKeyParts[2].Where(char.IsLetterOrDigit))).Value);

            if (!hostKeyPrint.Succeeded)
            {
                badConnString(string.Format("Invalid host key fingerprint '{0}'.", hostKeyParts[2]));
            }

            // using only pw auth for time being
            var pwAuthMethod = new PasswordAuthenticationMethod(username, password);
            var connInfo     = port.Succeeded
                ? new ConnectionInfo(host, port.Value, username, pwAuthMethod)
                : new ConnectionInfo(host, username, pwAuthMethod);

            var sftpClient = new SftpClient(connInfo);

            // validate host key
            sftpClient.HostKeyReceived += (s, e) =>
            {
                e.CanTrust = hostKeyParts[0].Equals(e.HostKeyName.Trim(), StringComparison.OrdinalIgnoreCase) &&
                             hostKeyLength == e.KeyLength &&
                             hostKeyPrint.Value.SequenceEqual(e.FingerPrint);
            };

            return(sftpClient);
        }