Tuesday, May 26, 2015

Solving Visual Studio DEP0700 Error Under Parallels

Today I ran into a problem where I was using Windows 8.1 under Parallels for Mac, and I created a brand new Visual Studio project.  Just to make sure everything worked fine, I hit "Run" and went head-first into an error DEP0700.

This is a frustrating error as it's (by design) trying to stop you from running a project who's output is on a network share when in "Local Machine" mode, but of course, it has no idea that this network share is actually on your local machine in the first place, as a result of running in Parallels.

The simple solution is therefore to tell Visual Studio to run the solution on a remote machine, then set the name of the remote machine to "localhost". 

Easy fix to an annoying problem. 

Sunday, May 24, 2015

The Price Of Rushed Software For Apple Watch...

See bottom of article for June 25, 2015 Update

The Apple watch has caused a flurry of apps to be quickly updated to support it, sometimes successfully, and other times it would appear that it was done as part of a "look at us too" campaign by some companies shoe-horning their app onto the device.  With the rush to get software out, I am seeing some mistakes slipping through the QA systems of certain apps.  

Recently, I was contacted by one of my banks about a customer service issue, and as I sometimes do with that bank when they reach out to me, I pulled a single item off my pile of security issues and threw them a bonus bone to chew on.  (If they go to the trouble of reaching out to me, the least I can do is give them something to make themselves safer).

I raised this issue with the bank, who accidentally left "Backdoor" (their term, not mine) URL's for the iPad and iPhone in the localization strings under the Watchkit Extension for their app. 

Personally, I don't run this bank's app, but given my history in Canadian mobile banking (I've still got code in the Canadian retail banking pipeline that won't see light of day until 2016 or 2017 in everything from location services, to photo cheque deposit anti-fraud), I do keep an eye on this bank's mobile software to remain aware of the industry. 

Just to clarify for the legally minded, this isn't hacking/reverse-engineering/etc ... Hacking means breaking in or causing software to be coerced into doing something unintended, and reverse-engineering means taking software and getting back to the source to work out how something is done.  In this case, you don't need to even open/run the app, or perform any reverse-engineering...  As this information is left open, you just download the app from the Apple App Store, then open it up in Finder on a Mac and start reading what was left unprotected.  This is no more "hacking or reverse engineering" than reading the pages in a book is "reverse engineering that book".

The bank in question here can easily say "this posed no threat to our operations or customers" and they'd be totally correct... in the same way that leaving a million dollars on the sidewalk or having the entire CxO team dance naked down Bay Street would have little impact on customer privacy or be detrimental to operations - however it's still not something anyone should do willingly.  

What it does point to is a botched rollout where technical mistakes were pushed through to meet management deadlines.  Here's three reasons that led me to this conclusion.

First, URL's, in a bank app shouldn't be public.  As a bank, they're just asking for trouble when script-kiddies find this kind of stuff.   The URL's should be inside the app itself, where no class dumping tools can get to the strings (because they'd be encrypted, but whoever approved this from a security standpoint didn't understand that point when it was OK'd).

Second, from an architectural standpoint, this makes no sense as the iPad and iPhone URL's don't belong in the WatchKit extension (the iPhone/iPad does the internet stuff, not the Watch). At first glance, this looks like a schoolboy error in cut & paste coding.

Third, from a technical standpoint, this is sheer lunacy;  URL's don't belong in the localization strings file because you plug in the parameters of the language at runtime, not hardcode the URL's to the UI localization.

What we can do, is take the information that the bank provided and show what they should have done if they were doing this properly.  They should have created a function like this for the "Registration" url, and buried that in the app itself.

-(NSString*) getLocalisedRegistrationURL {
    NSString *URL = @"/olbtxn/registration/Registration.cibc?register=initRegistration&visitorId=native&locale=%@";
    NSString * locale = [[NSLocale currentLocale] localeIdentifier];
    return [NSString stringWithFormat:@"%@%@", URL, locale];

...then repeat this process for any other URL's that must be localised.  That's what should have been done.

Now, having said all the above, we can also take a step back from the technical lunacy and architectural nonsense, and ask if this was actually done deliberately?  

In my mind, this is the more likely scenario... 

In the above links there are instances of what appears to be a possible smoking gun in the form of "visitorId=native".  This gives the impression that under the hood, the app is doing a popular trick in the form of substituting the token flag word "native" for the value returned by identifierForVendor, which allows the bank to identify your device and track you, meaning that the URL is actually very likely being processed further in the app to do substitutions on the URL string. 

This obviously begs the question as to why they didn't substitute the locale when they've had every opportunity to do so?

I think the answer to this question would be that this is a somewhat ham-fisted attempt at casting the possible ISO locale values to force them to either "en_CA" or "fr_CA" because the backend servers don't have any idea what to do with en_US/en_UK, fr_FR, etc.

As you can guess, this problem is also easily solved... if the French language is not the user's primary language, cast the result to Canadian English:

-(NSString*) getEnglishOrFrenchLanguage {
    if([[[NSLocale preferredLanguages] objectAtIndex:0] isEqualToString:@"fr"]) {
        return @"fr_CA";
    } else {
        return @"en_CA";

At this point, we've drawn two boxes around two mistakes, been given the preferred tracking mechanism and uncovered what looks like the hallmarks of a rushed rollout that at first glance looks like a schoolboy error and then later looks like back-end issues are being ham-fisted quickly to make deadlines... 

...all for the sake of seven lines of code.

Update - Jun 25, 2015

So the bank said that they would update the app to remove the backdoor URLs.  This week, I noticed that they have updated the app.  I took a look to see if they had removed them as they'd said they would.

This is what I found:

Yes, the word "Backdoor" has been replaced with "BD"...  

*face palm*

Getting Live Environment Canada Weather Using PHP

The other day a little project I had running at home required some live weather data... Nothing fancy, just the current temptation, condition and a quick blurb for the forecast.

I had a number of ways I could've done this, but I chose to do this in PHP (for me, it was just a process that would run and put these three items somewhere else, so nothing major necessary).

The PHP code is here, just in case anyone else needs to do this.


$weatherXML = getLiveWeatherXML();

$toronto = simplexml_load_string($weatherXML);
$currentCondition = $toronto->currentConditions->condition;
$currentTemperature = $toronto->currentConditions->temperature;
$forecastCondition = $toronto->forecastGroup->forecast->textSummary;

$arrayData = array(
array('CURRCONDITON' => $currentCondition),
array('CURRTEMP' => $currentTemperature),
array('FORECAST' => $forecastCondition),

//Do what you want with the array here...

function getLiveWeatherXML() {
return file_get_contents("http://dd.weather.gc.ca/citypage_weather/xml/ON/s0000458_e.xml");


Friday, May 8, 2015

CIBC Reference Number Logic - An Update

Last Saturday, I had a show down with CIBC staff over a situation that got out of hand and today I'd like to present an update.  You can read about it in full here, but the core point of the story is that CIBC were trying to harass me for money that I had every reason to believe they already had in their possession, and their tactic was to try and put the burden of proof on the customer to prove it.  They even tried to get information about other bank accounts, which I'm pretty sure is overstepping the proper bounds of privacy.

As experience has taught me that CIBC is prone to this type of cock-up, I refused to change my stance and it was left with me telling the horrible lady at CIBC that I was doing nothing further, until they call me back on Monday or Tuesday to confirm that there really was a problem because I don't believe them.

Guess what?  CIBC never called back.  

Today I decided to just double-check and see what CIBC was saying now?

Here's the chart from the Credit account.  CIBC shows that had the money one day before they called me, and proves that I was totally correct in my assumption that the customer service was just being unreasonable yet again.


I'd like to be surprised, but I'm not.  

When you understand the clearing process within banks, it becomes very apparent that the people trying to squeeze money out of me in the face of the evidence presented to them have not been adequately trained on these same cycles.  

Saturday, May 2, 2015

CIBC and Reference Numbers Logic

Had an interesting run-in with CIBC today.    

The phone rings at 4pm on Saturday afternoon, just as I’m getting the kids down for an afternoon nap.  I’m sitting next to the kids, and thanks to the wonders of iOS 8, even though the phone has been silenced, the laptop I’m using suddenly rings.  The kids wake up and I swear like a sailor.

I call back the number after re-settling the kids.  It’s CIBC.  Their phone system says it doesn’t know my phone number and so I have to punch it in.  After a wait of about 3 minutes, a women answers the phone.  After she confirms my identity, I am informed that she has no idea why I’ve called or why they called to begin with.


I ask her to put a note on file that I don’t like being called for no reason.  After about another 30 seconds she magically finds the reason they called.  They’re looking for a credit card payment.  

Luckily, my wife had sent the payment they were looking for from TD Bank on the previous Wednesday, so I told CIBC this is just a case of another call from CIBC looking for money that is likely already in their system.  They asked for the reference number, so we gave it to her.  

If you’re not familiar with how Canadian banks work, the worse case is a Canadian tier one bank will take a full working day to process an electronic payment request, so that means TD may have processed it after close of business on Thursday and CIBC would have received it on Friday, so CIBC would process it Friday night.  Unfortunately, this is a Saturday, so it is very highly probable that because CIBC's computers don’t appear to work on weekends, it’s not going to show up on their ledger even if it was now at CIBC until Monday morning.  

I was quite confident that telling CIBC the circumstances would be the end of this.  Unless they’ve some distrust that I don’t know about with other Canadian financial institutions, you’d think that dates and reference numbers of payments would be sufficient proof of payment. After all, why give them out if they're not the equivalent of a receipt?  Next, CIBC then asked for the last 4 digits of my wife’s TD bank account.  

Hell no.  

This is the Bell Canada of banking, and they obviously thought I'd not been poked with the CIBC stick enough.  The lady went on to put the burden on payment on the customer.  Apparently, we customers are now responsible for finding out why CIBC couldn’t see the money.  

I pushed back (I’m not a bank).  
CIBC pushed again.
I asked three times to be escalated.
After not being escalated my patience ran out.  It’s hard to resolve a situation when one party isn’t listening.

Then I finally got escalated.

The new lady that took over also tried to put the burden back on me to find out why my wife’s bank had not sent money from TD.  As things got more heated, she was stating that CIBC as a financial institution cannot do traces on payments initiated by another bank.   The conversation then went like this:

CIBC:  And I’d like to just remind you sir that this conversation is being recorded.
ME:  Good, because I’d love to know why the last lady just asked about the bank account digits at TD?
CIBC?  Err. What? We just told you we can’t trace payments at another institution.
ME: So why the hell are you asking for information that you’re now claiming is of no use to you?  Something is fishy here!

It ended with me irately telling them to check their reports on Monday as there’s sweet nothing that I can do this late on a Saturday.

I’ve stated numerous times that the trust level between CIBC and me is very, very low.  The legitimacy of anything that I hear from them is constantly eroded by foul-ups, conflicting information and a continued sense that they’re just screwing me over.  Today was just another episode in a long and painful journey.

Look at the straight facts of what can happen:
  • CIBC will ask you for reference numbers, stating they are required to prove something is paid for.
  • CIBC now says that it can’t trace payments at other banks.

That right there is conflict in logic, so one of those is clearly a lie.  Banks should not lie.

CIBC overstepped the mark in asking for the TD account info (I’m looking into the privacy rules on this, as I think it’s not supposed to happen under the Canadian charter that the banks have to follow), but CIBC definitely shot themselves in the foot over reference numbers.  

Someone is lying to me, and I’d love to know which is the correct answer.