16

I am stumped by a request from my manager. I work for a small startup and we developed a web application for a fixed rate with a maintenance agreement for a MUCH larger company. Knowing horror stories about how large companies will only pay their bills to the last second we decided that we would like to protect ourselves by being able to license this web application in a way that if we don't get paid the software no longer works.

I have seen this done before for desktop applications however this will be a web application that they will host internally and will not be accessible from the Internet.

What is the best approach to do this, we would like it to have a small footprint and would like the ability to renew the license key that they have distributed.

Has anybody done something similar? Are we completely out of our minds? Does anybody have any better suggestions?

maple_shaft
  • 26,570

6 Answers6

11

There are many ways to implement something like this, but here's one that shouldn't be too hard to do:

You need a publicly-available website somewhere that hosts a file containing the hashes of license keys that have been blacklisted. How you manage this file is up to you, but the file itself need only have a hash per line.

Then, on a recurring basis, your software initiates a download of this file (most server-side languages provide for this) and then searches it for the hash of the installed license key. If it is found, then the application knows that it should die until the blacklist is removed.

MD5 or similar plus a secret should be sufficient for this. You could get fancier and have the application send the request to your site and you look it up in a database on the fly, but the file (for what I'm assuming would hopefully be a short list) would hopefully remain small and may be the easiest way.

The harder part is going to be keeping the application dead. After all, you've got to store this somewhere internally, which means if it is overly obvious it could be easily subverted, and even if it isn't overly obvious, it can be easily reverted by restoring the appropriate table(s)/file(s). Therefore I suggest a second method of protection as well.

This method would store "LIVE" or "DEAD" (or something sufficiently similar) in a table or a file, but again HASHed. This needs to be hashed with your salt AND a timestamp. Everytime a page on your application runs, check this value with a hashed version of "LIVE"+salt+timestamp and then permit for a valid range of timestamps (for example, one day, two days, one week, one month, etc. Keep in mind the larger the range the harder performance will take a hit.). As long as things match (or a match is found), the app is alive; otherwise, even if the value in the special file or table is "LIVE", it will still be dead if there is attempt to restore from backup because the timestamp will fall outside your threshold.

In summary (this does assume that you have some programatic method of checking the validity of a license key, such as some sort of checksum or other method):

  • CheckBlacklist
    • Convert License Key to hash with salt
    • Request blacklist file from server
    • Is my hash in the file?
    • If YES, then store hash of "DEAD" + salt + timestamp (truncated to day; no need to store hours+days+minutes)
    • If NO, then store hash of "LIVE" + salt + timestamp (trunc'd)
  • IsKeyAlive
    • Create hash from "LIVE" + salt + trunc'd timestamp
    • Load DeadAlive hash
    • Do they agree?
    • If YES, then we're alive; return TRUE.
    • If NO, then we're possibly dead, but we may still be within our timestamp window:
      • Subtract a day from the timestamp and repeat hash.
      • Do we agree now?
      • YES? Return TRUE
      • Add a day to the timestamp and repeat hash
      • Do we agree now?
      • YES? Return TRUE
    • At this point, we're out of the timestamp range with no match. Return FALSE. (Kill app)

Now, goodness knows there's a million and one ways this can fail. Consider all the possible ways and build a reliable system (including one that assumes the client is right if the blacklist file can't be downloaded). Test, test, test it, and then test some more before deploying, because if it goes wrong, you'll have lost your client's trust.

4

The other answers have already done a good job of covering the technical side. But please also consider the legal side.

Do you even have a right to block their app if they do not pay? If you did not mention this up front in the contract, you may not have the right to do it, even if payments lapse (like you are not necessarily entitled to repossess something you sold). Also, many countries have special laws forbidding "manipulation of computer programs" - what you do might be considered as such and could even expose you to criminal liability.

So I'd advise to discuss this with a lawyer first, to avoid getting yourself into hot water.

In the end, it might be better to just rely on the legal system. If they don't pay, negotiate, and if that doesnt help, just sue. In many countries, suing is relatively painless & cheap if the contract situation is clear (in Germany e.g. you can get a Mahnbescheid for less than 20 €).

sleske
  • 10,280
2

If they're hosting internally, how is this different from any other software you might ship them? Figure out what you'd do if you were shipping, say, a desktop inventory display application, and do that.

1

It depends on the system. Did you extend an existing framework like Magneto or did you write a whole application from scratch? If it is the later, building in a licensing requirement isn't too hard. You just deliver the application with a short term license, one that expires 45-days after you bill and then give a permanent one later.

This assumes that you aren't turning over the source as well. :)

Christopher Bibbs
  • 2,749
  • 16
  • 12
1

Given that the system is hosted internally, many of the solutions mentioned above involving communicating with a remote server may not work.

Why not instead include a license file within the project that includes an expiry date. Once the system clock exceeds the expiry date, the system ceases to function. To secure the file, encrypt the contents to prevent tampering. When the user does pay, or renews for an extra year, you send them a new license file.

Note that if you are using PHP, the code is readily available for the user to edit, so no matter what kind of security you put in place, the user can easily go in and remove it. If you are using ASP.NET or some other compiled language, this is not a concern as the code cannot be modified.

Gavin Coates
  • 1,054
1

(Disclosure - I work for Agilis Software, a provider of license manager systems).

The most effective solution is to use automated product activation with a license lease. Out of the box this allows you to:

  • Automatically activate the customer's license(s). At activation time each instance is automatically locked to your chosen parameters of the target system, and the license limits you set up for them will be enforced on your application( e.g. configuring features, setting an overall trial or subscription time limit).
  • Set a 'lease interval', which is the maximum validity period of any one activation event. For customers with suspect credit you can set this to, say two weeks, which means every two weeks your app will automatically 'phone home' in the background to revalidate the license. If they are overdue on payment you can disable their license in the hosted server and it will stop running on the next phone home.
  • If there is not a network connection from the target system there is a user self-service activation process via exchange of encrypted files at any web terminal. If your user is in this position then you may want to make the lease interval longer to balance the inconvenience to them with your need to get paid. Once they pay you can make the lease interval as long as you like, up to perpetual.
Dominic
  • 41
  • 2