I would be grateful for any suggestions on how to add license key enforcement or concurrent user limit enforcement to a (UNIX-based) software product that - while not explicitly open-source - the end-user nominally has source code to, or could, conceivably, obtain with relative ease because the servers running it are located on their premises, etc.
Obviously, I am neither seeking nor expecting a technique that cannot be circumvented by someone highly motivated to do so, and/or by 1337 h4x0rs that are just good like that. The point of such anti-piracy mechanisms isn't to prevent the user from doing something they really want to do, but just to make it annoying enough to do that it's not really worth the hassle as compared to the relative ease of just paying for another (cheap) license - at least, for an end-user of merely average abilities.
That calls for something more sophisticated than mere security by obscurity (which will also get you laughed at by users that may come across it, even inadvertently without the intent to modify the setting), but nothing close to what's required to guard a missile silo. Just enough of something to say, "Yes, this product really does limit the use to what you bought." Shouldn't be anything interesting enough to motivate someone seeking fame and fortune to post a blog entry about how to crack it either, ideally, although given how utterly niche the product is and how inexpensive it is, I don't see that as being a concern.
The only real technique I can think of is to compile some routine(s) that is functionally essential to the rest of the program into a static or dynamic binary reloadable object and, along with it, include the checks. It is necessary that the routine be critical in some inseparable respect, rather than an artificial check just for that particular condition, otherwise the user could just go and disable the call to the function. The idea is that disabling the call to the function has other unattractive consequences as well.
That's nothing a smart hacker can't disassemble, and, obviously, if the function is trivial enough to build into an otherwise purposeless binary, it is trivial enough to reimplement outside of it as well. But it's more effort than a typical end-user would bother going through. And of course, again, the point isn't to mechanically stop piracy, but just to put a little limit in place so that the product doesn't work purely on the honour system, though I'm sure that's sufficient for many corporate buyers in the US.
Is this a common approach? Are there better ones?