Example #1
0
        /// <summary>
        /// Gets credentials for an online reader.
        /// </summary>
        /// <param name="readerName"></param>
        /// <returns></returns>
        public static OnlineCredentials GetCredentials( string filename, string serviceName )
        {
            var xmlCredentials = new XmlDocument();
            xmlCredentials.Load( filename );

            OnlineCredentials credentials = new OnlineCredentials();

            foreach( XmlNode node in xmlCredentials.SelectNodes( "/credentials/service" ) )
            {
                if( node.Attributes["name"].Value.ToLower() == serviceName.ToLower() )
                {
                    bool encrypted = false;
                    if( node.Attributes["encrypted"] != null )
                        encrypted = Convert.ToBoolean( node.Attributes["Encrypted"].Value );

                    // Found matching Reader node
                    foreach( XmlNode childNode in node.ChildNodes )
                    {
                        if( childNode.Name.ToLower() == "add" )
                        {
                            credentials.Add( childNode.Attributes["key"].Value, childNode.Attributes["value"].Value );
                        }
                    }
                }
            }

            return credentials;
        }
Example #2
0
        public Downloader( 
			IDataProvider dataStorage,
			IOnlineService service,
			OnlineCredentials credentials )
        {
            // TODO: Convert to Microsoft Code Contracts
            //Assert.PreCondition( dataStorage != null );
            //Assert.PreCondition( service != null );
            //Assert.PreCondition( credentials != null );

            this.dataStorage = dataStorage;
            this.credentials = credentials;
            this.service = service;
        }
Example #3
0
        public override void Connect( OnlineCredentials credentials )
        {
            base.Connect( credentials );

            this.credentials = credentials;

            // Load initial page to establish a session
            string html;

            string baseUri = "https://secure.ingdirect.com";

            this.LogWrite( OnlineServiceEventType.Service, "Connecting to web site" );

            // Login

            html = this.browser.HttpGet( baseUri + "/myaccount/INGDirect/login.vm?device=web&locale=en_US&userType=Client" );

            this.LogWrite( OnlineServiceEventType.Service, "Sending username" );

            // Populate form fields, including hidden fields
            // This information was obtained by examining the HTML on the login page
            NameValueCollection fields = new NameValueCollection();
            fields.Add( "Locale", "en_US" );
            fields.Add( "Device", "web" );
            fields.Add( "UserType", "Client" );
            fields.Add( "AuthenticationType", "Primary" );
            fields.Add( "ApplicationType", "ViewAccount" );
            fields.Add( "DeviceToken", "" );
            fields.Add( "fp_browser", "" );
            fields.Add( "fp_screen", "" );
            fields.Add( "fp_software", "" );
            fields.Add( "from", "NewPage" );
            fields.Add( "pm_fp", "" );
            fields.Add( "publicUserId", credentials.Username );
            fields.Add( "_rememberMyCIF", "" );
            fields.Add( "pageType", "primary" );
            fields.Add( "eva", "" );

            html = this.browser.HttpPostForm( baseUri + "/myaccount/INGDirect/login.vm", fields, true );

            // Check for security questions page

            if( html.IndexOf( "you'll need to answer 2 of your security questions" ) >= 0 )
            {
                this.LogWrite( OnlineServiceEventType.Service, "Sending security responses" );

                // <form action="security_questions.vm" name="CustomerAuthenticate" method="POST" title="Sign In" id="CustomerAuthenticate" class="m_proxy" onkeypress="checkEnter(event, this);">

                fields.Clear();
                fields.Add( "AlternateQuestionsSource", "empty" );
                fields.Add( "isacif", "true" );
                fields.Add( "QuestionHelp", "" );
                fields.Add( "TLSearchNum", credentials.Username );
                // HACK: Assumes both security answers are the same
                fields.Add( "customerAuthenticationResponse.questionAnswer[0].answerText", credentials["Response1"] );
                fields.Add( "customerAuthenticationResponse.questionAnswer[1].answerText", credentials["Response2"] );
                fields.Add( "hidetyping", "false" );
                fields.Add( "_customerAuthenticationResponse.device[0].bind", "false" );
                fields.Add( "customerAuthenticationResponse.device[0].bind", "true" );
                fields.Add( "YES, I WANT TO CONTINUE.", "true" );

                html = this.browser.HttpPostForm( baseUri + "/myaccount/INGDirect/security_questions.vm", fields, true );

            }

            // Password

            this.LogWrite( OnlineServiceEventType.Service, "Sending password" );

            // ING does a very odd thing with the password (or PIN) entry.
            // Normally, you have to click the keypad on the page to enter
            // the numbers, but they have an alternate "keyboard" entry
            // where you key in letters that correspond to the digits
            // on the keypad. The thing is, the letters that you press
            // are different each time, so you have to sniff out which
            // letters they have assigned to each digit. It's a massive
            // pain in the butt but it doesn't do anything to prevent
            // a persistent programmer from scraping their data.

            // We can tell the letters they use by the names of the images displayed.
            MatchCollection matches = Regex.Matches( html,
                "<img src=\"https://images.ingdirect.com/images/secure/pinpad/([ABCDEFGHIJKLMNOPQRSTUVWXYZ]).gif\"" );

            // There should be exactly ten matches: 123 456 789 0
            if( matches.Count != 10 )
                throw new OnlineServiceException( "Unexpected number of PIN images - scraper may need updating" );

            // Build an array mapping the letters to numbers
            // (Move the 0 from the end to the beginning of the array.)
            Dictionary<string, string> digitMapping = new Dictionary<string,string>();
            for( int i = 0; i < 9; i++ )
                digitMapping[(i+1).ToString()] = matches[i].Groups[1].Value;
            digitMapping[0.ToString()] = matches[9].Groups[1].Value;

            // Translate the user's password into letters
            StringBuilder sb = new StringBuilder();
            foreach( char c in credentials.Password )
            {
                if( !Char.IsDigit( c ) )
                    throw new OnlineServiceCredentialsException( "Password (PIN) must consist of numbers only" );
                sb.Append( digitMapping[c.ToString()] );
            }
            string mappedPassword = sb.ToString();

            fields.Clear();
            fields.Add( "customerAuthenticationResponse.PIN", mappedPassword );
            fields.Add( "riskBasedAuthorizationResults", "" );

            html = this.browser.HttpPostForm( baseUri + "/myaccount/INGDirect/login_pinpad.vm", fields, true );

            if( html.IndexOf( "You've entered your PIN incorrectly. Please try again." ) >= 0 )
                throw new OnlineServiceCredentialsException( "Invalid user ID or password" );

            // Save the HTML for the Accounts getter below.
            this.accountHtml = html;
        }
Example #4
0
        public override void Connect( OnlineCredentials credentials )
        {
            base.Connect( credentials );

            this.LogWrite( OnlineServiceEventType.Service, "Logging in" );

            string html = this.browser.HttpGet(
                "https://www.suntrust.com/portal/server.pt" );

            string action = this.browser.RegexCapture( "<form method=\"post\" action=\"(https://.*?)\" name=\"lform\" id=\"loginFormID\" autocomplete=\"off\">", html );

            // Populate form fields, including hidden fields
            // This information was obtained by examining the Suntrust HTML
            NameValueCollection fields = new NameValueCollection();
            fields.Add( "in_hi_space", "Login" );
            fields.Add( "in_hi_spaceID", "0" );
            fields.Add( "in_hi_control", "Login" );
            fields.Add( "in_hi_dologin", "false" );	// was "true"
            fields.Add( "uid", credentials.Username );
            fields.Add( "password", credentials.Password );
            fields.Add( "in_bu_Login", "Log In" );

            html = this.browser.HttpPostForm( action, fields );

            if( html.IndexOf( "The User ID and/or password you entered does not match our records" ) >= 0 )
                throw new OnlineServiceCredentialsException(
                    "The supplied credentials were rejected by the Suntrust site." );

            // Verify that we got a page we expect.
            this.browser.RegexAssert(
                "Please wait while we validate your sign-on information", html );

            // Now work our way through several redirect pages until we get to
            // the summary page.

            action = this.browser.RegexCapture(
                "<form name=\"Form1_442\" method=\"post\" action=\"(.*?)\"", html );

            fields.Clear();
            fields.Add( "__EVENTTARGET",
                "phasedControl:cmdSubmitDeviceInfo" );
            fields.Add( "__EVENTARGUMENT",
                this.browser.RegexCapture(
                "<input type=\"hidden\" name=\"__EVENTARGUMENT\" id=\"__EVENTARGUMENT\" value=\"(.*?)\" />",
                html ) );
            fields.Add( "__VIEWSTATE",
                this.browser.RegexCapture(
                "<input type=\"hidden\" name=\"__VIEWSTATE\" id=\"__VIEWSTATE\" value=\"(.*?)\" />",
                html ) );
            fields.Add( "phasedControl:mfBrowserCookies",
                this.browser.CookieText );
            // Hardcoded:
            fields.Add( "phasedControl:mfDevicePrint",
                "version=1&pm_fpua=mozilla/5.0 (windows; u; windows nt 6.0; en-us; rv:1.9.0.8) gecko/2009032609 firefox/3.0.8 (.net clr 3.5.30729)|5.0 (Windows; en-US)|Win32&pm_fpsc=32|1680|1050|1020&pm_fpsw=|qt6|qt5|qt4|qt3|qt2|qt1|def|swf|pdf&pm_fptz=-4&pm_fpln=lang=en-US|syslang=|userlang=&pm_fpjv=0&pm_fpco=1" );
            // Hardcoded:
            fields.Add( "phasedControl:mfUserAgent",
                "mozilla/5.0 (windows; u; windows nt 6.0; en-us; rv:1.9.0.8) gecko/2009032609 firefox/3.0.8 (.net clr 3.5.30729)|5.0 (Windows; en-US)|Win32|en-US" );

            // Note that Suntrust will return varying forms of the following
            // page depending on the settings provided in the form populated above.
            html = this.browser.HttpPostForm( action, fields );

            action = this.browser.RegexCapture(
                @"window\.location\.replace\('(.*?)'\);", html );

            html = this.browser.HttpGet( action );

            action = this.browser.RegexCapture(
                "<meta HTTP-EQUIV=\"REFRESH\" CONTENT=\"0; URL=(.*?)\">", html );

            html = this.browser.HttpGet( action );

            action = "https://www.suntrust.com/portal/server.pt?" + this.browser.RegexCapture(
                @"window\.location=pt_533\.makeAbsoluteURL\(OpenerAS_GetApplicationBaseURL\(\) \+ ""(.*?)""\);", html );

            // Finally we get to the actual summary page.
            this.summaryPageHtml = this.browser.HttpGet( action );

            this.isLoggedIn = true;
        }
Example #5
0
        public override void Connect( OnlineCredentials credentials )
        {
            base.Connect( credentials );

            // Load initial page to establish a session
            string html;

            string baseVacuUri = "https://command.onlinebank.com/1899/";

            this.LogWrite( OnlineServiceEventType.Service, "Connecting to VACU web site" );

            // Home.aspx

            html = this.browser.HttpGet( baseVacuUri + "Home.aspx" );

            // 4/23/2011 VACU changed the control container names (M$ to M$L$),
            // made regex more generalized.

            this.LogWrite( OnlineServiceEventType.Service, "Sending username" );

            string action = this.browser.RegexCapture( "<form name=\"aspnetForm\" method=\"post\" action=\"(.*?)\"", html );
            if( action == null || action.Length == 0 )
                throw new OnlineServiceException( "Unable to locate form action URL." );

            // Populate form fields, including hidden fields
            // This information was obtained by examining the HTML at the Vacu login page
            NameValueCollection fields = new NameValueCollection();
            fields.Add( "M_content_ScriptManager_HiddenField", ";;System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35:en-US:1247b7d8-6b6c-419f-a45f-8ff264c90734:ea597d4b:b25378d2" );
            fields.Add( "UsePrinterFriendlyVersion", "Off" );
            fields.Add( "__VIEWSTATEID", this.browser.DotNetCaptureHidden( html, "__VIEWSTATEID" ) );
            fields.Add( "__VIEWSTATE", "" );
            fields.Add( "__EVENTVALIDATION", this.browser.DotNetCaptureHidden( html, "__EVENTVALIDATION" ) );
            foreach( Match match in Regex.Matches( html, @"<input name=""(.*?\$state)"" type=""hidden"" id="".*?_state"" />" ) )
                fields.Add( match.Groups[1].Value, string.Empty );
            fields.Add( this.browser.RegexCapture( @"<input name=""(.*?\$LoginName)"" type=""text""", html ), credentials.Username );
            fields.Add( this.browser.RegexCapture( @"<input type=""submit"" name=""(.*?\$cmdContinue)"" value=""Continue""", html ), "1" );

            // Post to Default.aspx
            html = this.browser.DotNetPostBack( baseVacuUri + action, fields,
                string.Empty, string.Empty );

            // Password

            this.LogWrite( OnlineServiceEventType.Service, "Sending password." );

            action = this.browser.RegexCapture( "<form name=\"aspnetForm\" method=\"post\" action=\"(.*?)\"", html );
            if( action == null || action.Length == 0 )
                throw new OnlineServiceException( "Unable to locate form action URL." );

            fields.Clear();
            fields.Add( "M_content_ScriptManager_HiddenField", ";;System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35:en-US:1247b7d8-6b6c-419f-a45f-8ff264c90734:ea597d4b:b25378d2" );
            fields.Add( "UsePrinterFriendlyVersion", "Off" );
            fields.Add( "__EVENTTARGET", string.Empty );
            fields.Add( "__EVENTARGUMENT", string.Empty );
            fields.Add( "__VIEWSTATEID", this.browser.DotNetCaptureHidden( html, "__VIEWSTATEID" ) );
            fields.Add( "__VIEWSTATE", string.Empty );
            fields.Add( "__EVENTVALIDATION", this.browser.DotNetCaptureHidden( html, "__EVENTVALIDATION" ) );
            foreach( Match match in Regex.Matches( html, @"<input name=""(.*?\$state)"" type=""hidden"" id="".*?_state"" />" ) )
                fields.Add( match.Groups[1].Value, string.Empty );
            fields.Add( this.browser.RegexCapture( @"<input name=""(.*?\$Password)"" type=""password""", html ), credentials.Password );
            fields.Add( this.browser.RegexCapture( @"<input type=""submit"" name=""(.*?\$cmdContinue)"" value=""Sign in""", html ), "1" );

            // Post to Password.aspx
            html = this.browser.HttpPostForm( baseVacuUri + "AOP/" + action, fields, true );

            if( html.IndexOf( "Invalid user ID or password" ) >= 0 )
                throw new OnlineServiceCredentialsException( "Invalid user ID or password" );

            // TODO: Possible additional security questions

            // Look for keyword indicating page is asking for security question
            if( html.IndexOf( "For additional security, please provide your answers to the following questions." ) >= 0 )
            {
                action = this.browser.RegexCapture( "<form name=\"aspnetForm\" method=\"post\" action=\"(.*?)\"", html );
                if( action == null || action.Length == 0 )
                    throw new OnlineServiceException( "Unable to locate form action URL." );

                string challengeQuestion = this.browser.RegexCapture( "<span id=\"M_content_.*?_ctl00_lblQuestion\">(.*?)</span>", html );
                string challengeResponse = "";

                this.LogWrite( OnlineServiceEventType.Service, "Responding to challenge question." );

                if( challengeQuestion.IndexOf( credentials["Challenge1"] ) >= 0 )
                    challengeResponse = credentials["Response1"];
                else if( challengeQuestion.IndexOf( credentials["Challenge2"] ) >= 0 )
                    challengeResponse = credentials["Response2"];
                else if( challengeQuestion.IndexOf( credentials["Challenge3"] ) >= 0 )
                    challengeResponse = credentials["Response3"];
                else
                    throw new OnlineServiceException( "Unrecognized challenge question ('" + challengeQuestion + "'). Unable to respond." );

                fields.Clear();
                fields.Add( "M_content_ScriptManager_HiddenField", ";;System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35:en-US:1247b7d8-6b6c-419f-a45f-8ff264c90734:ea597d4b:b25378d2" );
                fields.Add( "UsePrinterFriendlyVersion", "Off" );
                fields.Add( "__VIEWSTATEID", this.browser.DotNetCaptureHidden( html, "__VIEWSTATEID" ) );
                fields.Add( "__VIEWSTATE", "" );
                fields.Add( "__EVENTVALIDATION", this.browser.DotNetCaptureHidden( html, "__EVENTVALIDATION" ) );
                fields.Add( "M$content$PCDZ$M3WO5TB$ctl00$rptAnswerQuestions$ctl00$txtAnswer", challengeResponse );
                fields.Add( "M$content$PCDZ$M3WO5TB$ctl00$cmdSubmit", "1" );

                html = this.browser.DotNetPostBack( baseVacuUri + "AOP/" + action, fields,
                    string.Empty, string.Empty );
            }

            this.visaLink = this.browser.RegexCapture( @"<a target=""_blank"" href=""\.\./(PSCU\.aspx.*?)"">", html );

            // Summary Page
        }