PHP Classes

File: app/class.license.app.php

Recommend this page to a friend!
  Classes of Oliver Lillie   PADL (PHP Application Distribution License System)   app/class.license.app.php   Download  
File: app/class.license.app.php
Role: Class source
Content type: text/plain
Description: Subclass Source
Class: PADL (PHP Application Distribution License System)
Generate PHP application license keys
Author: By
Last change: Important Security and Consistency updates
Date: 18 years ago
Size: 17,907 bytes
 

Contents

Class file image Download
<?php /** * Project: Distrubution License Class * File: class.license.app.php * * Copyright (C) 2005 Oliver Lillie * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * @link http://www.buggedcom.co.uk/ * @link http://www.phpclasses.org/browse/package/2298.html * @author Oliver Lillie, buggedcom <publicmail at buggedcom dot co dot uk> * @history--------------------------------------------- * see CHANGELOG */ class license_application extends padl { /** * The number of allowed differences between the $_SERVER vars and the vars * stored in the key * * @var number */ var $_ALLOWED_SERVER_DIFS = 0; /** * The number of allowed differences between the $ip vars in the key and the ip * vars collected from the server * * @var number */ var $_ALLOWED_IP_DIFS = 0; /** * the path of the license key file, remember this would be relative to the * include path of the class file. */ var $_LICENSE_PATH; /** * Constructor * * @access public * @param $use_mcrypt boolean Determines if mcrypt encryption is used or not (defaults to true, * however if mcrypt is not available, it is set to false) * @param $use_time boolean Sets if time binding should be used in the key (defaults to true) * @param $use_server boolean Sets if server binding should be used in the key (defaults to true) * @param $allow_local boolean Sets if server binding is in use then localhost servers are valid (defaults to false) **/ function license_application($license_path='license.dat', $use_mcrypt=true, $use_time=true, $use_server=true, $allow_local=false) { # check to see if the class has been secured $this->_check_secure(); $this->_LICENSE_PATH = $license_path; $this->init($use_mcrypt, $use_time, $use_server, $allow_local); if($this->USE_SERVER) { $this->_MAC = $this->_get_mac_address(); } } /** * set_server_vars * * to protect against spoofing you should copy the $_SERVER vars into a * seperate array right at the first line of your script so parameters can't * be changed in unencoded php files. This doesn't have to be set. If it is * not set then the $_SERVER is copied when _get_server_info (private) function * is called. * * @access public * @param $array array The copied $_SERVER array **/ function set_server_vars($array) { # check to see if the class has been secured $this->_check_secure(); $this->_SERVER_VARS = $array; # some of the ip data is dependant on the $_SERVER vars, so update them # after the vars have been set $this->_IPS = $this->_get_ip_address(); # update the server info $this->_SERVER_INFO = $this->_get_server_info(); } /** * _get_os_var * * gets various vars depending on the os type * * @access private * @return string various values **/ function _get_os_var($var_name, $os) { $var_name = strtolower($var_name); # switch between the os's switch($os) { # not sure if the string is correct for FreeBSD # not tested case 'freebsd' : # not sure if the string is correct for NetBSD # not tested case 'netbsd' : # not sure if the string is correct for Solaris # not tested case 'solaris' : # not sure if the string is correct for SunOS # not tested case 'sunos' : # darwin is mac os x # tested only on the client os case 'darwin' : # switch the var name switch($var_name) { case 'conf' : $var = '/sbin/ifconfig'; break; case 'mac' : $var = 'ether'; break; case 'ip' : $var = 'inet '; break; } break; # linux variation # tested on server case 'linux' : # switch the var name switch($var_name) { case 'conf' : $var = '/sbin/ifconfig'; break; case 'mac' : $var = 'HWaddr'; break; case 'ip' : $var = 'inet addr:'; break; } break; } return $var; } /** * _get_config * * gets the server config file and returns it. tested on Linux, * Darwin (Mac OS X), and Win XP. It may work with others as some other * os's have similar ifconfigs to Darwin but they haven't been tested * * @access private * @return string config file data **/ function _get_config() { # check to see if the class has been secured $this->_check_secure(); if(ini_get('safe_mode')) { # returns invalid because server is in safe mode thus not allowing # sbin reads but will still allow it to open. a bit weird that one. return 'SAFE_MODE'; } # if anyone has any clues for windows environments # or other server types let me know $os = strtolower(PHP_OS); if(substr($os, 0, 3)=='win') { # this windows version works on xp running apache # based server. it has not been tested with anything # else, however it should work with NT, and 2000 also # execute the ipconfig @exec('ipconfig/all', $lines); # count number of lines, if none returned return MAC_404 # thanks go to Gert-Rainer Bitterlich <bitterlich -at- ima-dresden -dot- de> if(count($lines) == 0) return 'ERROR_OPEN'; # $path the lines together $conf = implode($this->_LINEBREAK, $lines); } else { # get the conf file name $os_file = $this->_get_os_var('conf', $os); # open the ipconfig $fp = @popen($os_file, "rb"); # returns invalid, cannot open ifconfig if (!$fp) return 'ERROR_OPEN'; # read the config $conf = @fread($fp, 4096); @pclose($fp); } return $conf; } /** * _get_ip_address * * Used to get the MAC address of the host server. It works with Linux, * Darwin (Mac OS X), and Win XP. It may work with others as some other * os's have similar ifconfigs to Darwin but they haven't been tested * * @access private * @return array IP Address(s) if found (Note one machine may have more than one ip) * @return string ERROR_OPEN means config can't be found and thus not opened * @return string IP_404 means ip adress doesn't exist in the config file and can't be found in the $_SERVER * @return string SAFE_MODE means server is in safe mode so config can't be read **/ function _get_ip_address() { $ips = array(); # get the cofig file $conf = $this->_get_config(); # if the conf has returned and error return it if($conf != 'SAFE_MODE' && $conf != 'ERROR_OPEN') { # if anyone has any clues for windows environments # or other server types let me know $os = strtolower(PHP_OS); if(substr($os, 0, 3)=='win') { # anyone any clues on win ip's } else { # explode the conf into seperate lines for searching $lines = explode($this->_LINEBREAK, $conf); # get the ip delim $ip_delim = $this->_get_os_var('ip', $os); # ip pregmatch $num = "(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])"; # seperate the lines foreach ($lines as $key=>$line) { # check for the ip signature in the line if(!preg_match("/^$num\\.$num\\.$num\\.$num$/", $line) && strpos($line, $ip_delim)) { # seperate out the ip $ip = substr($line, strpos($line, $ip_delim)+strlen($ip_delim)); $ip = trim(substr($ip, 0, strpos($ip, " "))); # add the ip to the collection if(!isset($ips[$ip])) $ips[$ip] = $ip; } } } } # if the conf has returned nothing # attempt to use the $_SERVER data if(isset($this->_SERVER_VARS['SERVER_NAME'])) { $ip = gethostbyname ($this->_SERVER_VARS['SERVER_NAME']); if(!isset($ips[$ip])) $ips[$ip] = $ip; } if(isset($this->_SERVER_VARS['SERVER_ADDR'])) { $name = gethostbyaddr ($this->_SERVER_VARS['SERVER_ADDR']); $ip = gethostbyname ($name); if(!isset($ips[$ip])) $ips[$ip] = $ip; # if the $_SERVER addr is not the same as the returned ip include it aswell if($addr != $this->_SERVER_VARS['SERVER_ADDR']) { if(!isset($ips[$this->_SERVER_VARS['SERVER_ADDR']])) $ips[$this->_SERVER_VARS['SERVER_ADDR']] = $this->_SERVER_VARS['SERVER_ADDR']; } } # count return ips and return if found if(count($ips) > 0) return $ips; # failed to find an ip check for conf error or return 404 if($conf == 'SAFE_MODE' || $conf == 'ERROR_OPEN') return $conf; return 'IP_404'; } /** * _get_mac_address * * Used to get the MAC address of the host server. It works with Linux, * Darwin (Mac OS X), and Win XP. It may work with others as some other * os's have similar ifconfigs to Darwin but they haven't been tested * * @access private * @return string Mac address if found * @return string ERROR_OPEN means config can't be found and thus not opened * @return string MAC_404 means mac adress doesn't exist in the config file * @return string SAFE_MODE means server is in safe mode so config can't be read **/ function _get_mac_address() { # open the config file $conf = $this->_get_config(); # if anyone has any clues for windows environments # or other server types let me know $os = strtolower(PHP_OS); if(substr($os, 0, 3)=='win') { # explode the conf into lines to search for the mac $lines = explode($this->_LINEBREAK, $conf); # seperate the lines for analysis foreach ($lines as $key=>$line) { # check for the mac signature in the line # originally the check was checking for the existence of string 'physical address' # however Gert-Rainer Bitterlich pointed out this was for english language # based servers only. preg_match updated by Gert-Rainer Bitterlich. Thanks if(preg_match("/([0-9a-f][0-9a-f][-:]){5}([0-9a-f][0-9a-f])/i", $line)) { $trimmed_line = trim($line); # take of the mac addres and return return trim(substr($trimmed_line, strrpos($trimmed_line, " "))); } } } else { # get the mac delim $mac_delim = $this->_get_os_var('mac', $os); # get the pos of the os_var to look for $pos = strpos($conf, $mac_delim); if($pos) { # seperate out the mac address $str1 = trim(substr($conf, ($pos+strlen($mac_delim)))); return trim(substr($str1, 0, strpos($str1, "\n"))); } } # failed to find the mac address return 'MAC_404'; } /** * _get_server_info * * used to generate the server binds when server binding is needed. * * @access private * @return array server bindings * @return boolean false means that the number of bindings failed to * meet the required number **/ function _get_server_info() { if(empty($this->_SERVER_VARS)) { $this->set_server_vars($_SERVER); } # get the server specific uris $a = array(); if(isset($this->_SERVER_VARS['SERVER_ADDR']) && (!strrpos($this->_SERVER_VARS['SERVER_ADDR'], '127.0.0.1') || $this->ALLOW_LOCAL)) { $a['SERVER_ADDR'] = $this->_SERVER_VARS['SERVER_ADDR']; } # corrected by Gert-Rainer Bitterlich <bitterlich -at- ima-dresden -dot- de>, Thanks if(isset($this->_SERVER_VARS['HTTP_HOST']) && (!strrpos($this->_SERVER_VARS['HTTP_HOST'], '127.0.0.1') || $this->ALLOW_LOCAL)) { $a['HTTP_HOST'] = $this->_SERVER_VARS['HTTP_HOST']; } if(isset($this->_SERVER_VARS['SERVER_NAME'])) { $a['SERVER_NAME'] = $this->_SERVER_VARS['SERVER_NAME']; } if(isset($this->_SERVER_VARS['PATH_TRANSLATED'])) { $a['PATH_TRANSLATED'] = substr($this->_SERVER_VARS['PATH_TRANSLATED'], 0, strrpos($this->_SERVER_VARS['PATH_TRANSLATED'], '/')); } else if(isset($this->_SERVER_VARS['SCRIPT_FILENAME'])) { $a['SCRIPT_FILENAME'] = substr($this->_SERVER_VARS['SCRIPT_FILENAME'], 0, strrpos($this->_SERVER_VARS['SCRIPT_FILENAME'], '/')); } if(isset($_SERVER['SCRIPT_URI'])) { $a['SCRIPT_URI'] = substr($this->_SERVER_VARS['SCRIPT_URI'], 0, strrpos($this->_SERVER_VARS['SCRIPT_URI'], '/')); } # if the number of different uris is less than the required amount, # fail the request if(count($a) < $this->REQUIRED_URIS) { return 'SERVER_FAILED'; } return $a; } /** * validate * * validates the server key and returns a data array. * * @access public * @return array Main object in array is 'RESULT', it contains the result * of the validation. * OK - key is valid * CORRUPT - key has been tampered with * TMINUS - the key is being used before the valid start date * EXPIRED - the key has expired * ILLEGAL - the key is not on the same server the license was registered to * ILLEGAL_LOCAL - the key is not allowed to be installed on a local machine * INVALID - the the encryption key used to encrypt the key differs or the key is not complete * EMPTY - the the key is empty * 404 - the the key is missing **/ function validate($str=false, $dialhome=false, $dialhost="", $dialpath="", $dialport="80") { # check to see if the class has been secured $this->_check_secure(); # get the dat string $dat_str = (!$str) ? @file_get_contents($this->_LICENSE_PATH) : $str; if(strlen($dat_str)>0) { # decrypt the data $DATA = $this->_unwrap_license($dat_str); if(is_array($DATA)) { # missing / incorrect id therefore it has been tampered with if($DATA['ID'] != md5($this->ID1)) { $DATA['RESULT'] = 'CORRUPT'; } if($this->USE_TIME) { # the license is being used before it's official start if($DATA['DATE']['START'] > time()+$this->START_DIF) { $DATA['RESULT'] = 'TMINUS'; } # the license has expired if($DATA['DATE']['END']-time() < 0 && $DATA['DATE']['SPAN'] != 'NEVER') { $DATA['RESULT'] = 'EXPIRED'; } $DATA['DATE']['HUMAN']['START'] = date($this->DATE_STRING, $DATA['DATE']['START']); $DATA['DATE']['HUMAN']['END'] = date($this->DATE_STRING, $DATA['DATE']['END']); } if($this->USE_SERVER) { $mac = $DATA['SERVER']['MAC'] == $this->_MAC; $path = count(array_diff($this->_SERVER_INFO, $DATA['SERVER']['PATH'])) <= $this->_ALLOWED_SERVER_DIFS; $domain = $this->_compare_domain_ip($DATA['SERVER']['DOMAIN'], $this->_IPS); $ip = count(array_diff($this->_IPS, $DATA['SERVER']['IP'])) <= $this->_ALLOWED_IP_DIFS; # the server details if(!$mac || !$path || !$domain || !$ip) { $DATA['RESULT'] = 'ILLEGAL'; } # check if local $local = $this->ALLOW_LOCAL && (in_array('127.0.0.1', $DATA['SERVER']['IP']) || $DATA['PATH']['SERVER_ADDR'] == '127.0.0.1' || $DATA['PATH']['HTTP_HOST'] == '127.0.0.1'); if(!$local) { $DATA['RESULT'] = 'ILLEGAL_LOCAL'; } } # passed all current test so license is ok if(!isset($DATA['RESULT'])) { # dial to home server if required if($dialhome) { # create the details to send to the home server $stuff_to_send = array(); $stuff_to_send['LICENSE_DATA'] = $DATA; $stuff_to_send['LICENSE_DATA']['KEY'] = md5($dat_str); # dial home $DATA['RESULT'] = $this->_call_home($stuff_to_send, $dialhost, $dialpath, $dialport); } else { # result is ok all test passed, license is legal $DATA['RESULT'] = 'OK'; } } /* */ # data is returned for use return $DATA; } else { # the are two reason that mean a invalid return # 1 - the other hash key is different # 2 - the key has been tampered with return array('RESULT'=>'INVALID'); } } # returns empty because there is nothing in the dat_string return array('RESULT'=>'EMPTY'); } /** * _call_home * * calls the dial home server (your server) andvalidates the clients license * with the info in the mysql db * * @access private * @param $data array Array that contains the info to be validated * @param $dialhost string Host name of the server to be contacted * @param $dialpath string Path of the script for the data to be sent to * @param $dialport number Port Number to send the data through * @return string Returns: the encrypted server validation result from the dial home call * : SOCKET_FAILED => socket failed to connect to the server **/ function _call_home($data, $dialhost, $dialpath, $dialport) { # post the data home $data = $this->_post_data($dialhost, $dialpath, $data, $dialport); return (empty($data['RESULT'])) ? 'SOCKET_FAILED' : $data['RESULT']; } } ?>