首页 > 系统相关 >Linux系统中软件简单License的实现

Linux系统中软件简单License的实现

时间:2023-05-17 10:25:47浏览次数:33  
标签:addr license int ifc ifr License Linux 软件 x86

Linux系统中软件简单License的实现

概述

       目前,很多商用应用系统是运行在Linux系统之上的,为了维护开发者利益,有必要为软件添加license功能,防止软件被盗用和挪用。本文探讨如何在Linux软件中添加license功能,用到的算法是MD5算法。

 

关键字: MD5

 

一 目的和思路

       设置License就是要将软件和运行该软件的机器进行简单“绑定”,该软件只能在某台指定机器上使用,如果将该软件挪动到其他机器上则无法运行。

       根据以上目的,那么思路就很清晰,则我们需要读取该指定机器的某些特征,这里我们只抓取两个特征,即CPU特征和机器MAC地址。

这样,我们需要一个获得机器特征的程序,一个生成license的程序以及在所要加license的程序中嵌入检查license的代码。生成license程序可以是在windows操作系统下编写,也可以在Linux系统下编写,本文只讨论后面一种。

 

二 关键技术

       这里的三个关键技术是获得本机的CPU信息、获得网卡MAC地址信息以及MD5加密。

1.       获得CPU信息

兼容x86的CPU的信息存储在数据结构:

 

 

struct cpuinfo_x86 {

__u8 x86;        /* CPU family */

__u8 x86_vendor; /* CPU vendor */

__u8 x86_model;

__u8 x86_mask;

char wp_works_ok;    /* It doesn't on 386's */

char hlt_works_ok;    /* Problems on some 486Dx4's and old 386's */

char hard_math;

char rfu;

       int cpuid_level; /* Maximum supported CPUID level, -1=no CPUID */

unsigned long x86_capability[7];

char x86_vendor_id[16];

char x86_model_id[64];

int x86_cache_size;  /* in KB - valid for CPUS which support this

                   call  */

int x86_cache_alignment; /* In bytes */

int fdiv_bug;

int f00f_bug;

int coma_bug;

unsigned long loops_per_jiffy;

unsigned char x86_num_cores;

};

中,对于我们来说,只要获得x86_vendor_id和x86_model_id两项信息即可,前者记录的是CPU的制造商的信息,后者记录CPU的记录信息。在Linux下,可以通过以下代码获得:

 

static inline void

cpuid(int op, unsigned int *eax, unsigned int *ebx,

                      unsigned int *ecx, unsigned int *edx)

{

       __asm__("cpuid"

              : "=a" (*eax),

                "=b" (*ebx),

                "=c" (*ecx),

                "=d" (*edx)

              : "0" (op));

}

 

static unsigned int

get_cpu_id()

{

       unsigned int *v;

 

       cpuid(0x00000000, &cpu_info.cpuid_level,

             (int *)&cpu_info.x86_vendor_id[0],

             (int *)&cpu_info.x86_vendor_id[8],

             (int *)&cpu_info.x86_vendor_id[4]);

 

       v = (unsigned int *) cpu_info.x86_model_id;

       cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]);

       cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);

       cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);

 

       return 0;

}

 

       这样,CPU的信息就存储在cpu_info中。

 

2.       获得MAC地址

网卡信息是存储在数据结构:

struct ifconf ifc;

中,该结构包含在头文件

#include <net/if.h>

中,在编写代码时需要将它包含。获得MAC地址的代买如下:

 

#define IFRSIZE      ( ( int )( size * sizeof( struct ifreq ) ) )

 

static int

get_mac_addr(void)

{

       int                sockfd, size = 1;

 

       if (0 > (sockfd = socket( AF_INET, SOCK_DGRAM, IPPROTO_IP))) {

              logit(LOG_SYS, LEVEL_ERR, "get_mac_addr: cannot open socket.\n" );

              return -1;

       }

       ifc.ifc_req = NULL;

 

       do {

              ++size;

              /* realloc buffer size until no overflow occurs  */

              if (NULL == (ifc.ifc_req = realloc( ifc.ifc_req, IFRSIZE))) {

                     logit(LOG_SYS, LEVEL_ERR,  "get_mac_addr: out of memory.\n" );

                     return -1;

              }

              ifc.ifc_len = IFRSIZE;

              if (ioctl(sockfd, SIOCGIFCONF, &ifc)) {

                     logit(LOG_SYS, LEVEL_ERR, "get_mac_addr: ioctl SIOCFIFCONF");

                     return -1;

              }

       } while (IFRSIZE <= ifc.ifc_len);

 

       ifr = ifc.ifc_req;

       for (; ( char * )ifr < ( char * )ifc.ifc_req + ifc.ifc_len; ++ifr) {

              if (ifr->ifr_addr.sa_data == ( ifr + 1 )->ifr_addr.sa_data) {

                     continue;  /* duplicate, skip it */

              }

              if ( ioctl( sockfd, SIOCGIFFLAGS, ifr ) ) {

                     continue;  /* failed to get flags, skip it */

              }

/*           printf( "Interface:  %s\n", ifr->ifr_name );*/

              if ( 0 == ioctl( sockfd, SIOCGIFHWADDR, ifr)) {

                     switch ( ifr->ifr_hwaddr.sa_family ) {

                     case ARPHRD_NETROM:

                     case ARPHRD_ETHER:

                     case ARPHRD_PPP:

                     case ARPHRD_EETHER:

                     case ARPHRD_IEEE802:

                            break;

                     default:

/*                         printf( "\n" );*/

                            continue;

                     }

                     mac_addr = ( unsigned char * )&ifr->ifr_addr.sa_data;

                     if ( mac_addr[0] + mac_addr[1] + mac_addr[2] + mac_addr[3]

                            + mac_addr[4] + mac_addr[5] ) {

                            return 0;

                     } else {

                            return -1;

                     }

              }

/*          printf( "\n" ); */

       }  /* end of for */

       close(sockfd);

       return 0;

}

 

       这样,MAC地址就放在mac_addr中,mac_addr 的定义是:

unsigned char *mac_addr;

 

3.       MD5算法加密

MD5算法其实是一个用来产生随机数的算法,已经有了现成的源码(在RFC中有详细描述),它最主要的接口主要是函数:

UINT4B  md_32(char *string, int length)

该函数传入一串字符串,然后返回一个32字节的带符号位整型数。这里,字符串的内容可以是任意的,而一旦内容固定,那么返回的整型数就是唯一的。于是,我们就可以利用这个函数来验证输入的字符串的正确性。

 

四 流程

      

1.       生成license

首先是获得CPU信息,则通过上述代码,将CPU信息存入cpu_info。

其次是获得MAC地址,则通过上述代码,将MAC地址存入mac_addr中,

最后就是调用函数md_32,获得一个随机数,将该随机数写入到某个文件,可以称之为验证码,那么该文件即生成为license文件。

 

2.       验证license

验证license的一部分步骤和生成license是一模一样的,即验证时,也需要先读取CPU和MAC地址信息,然后也通过md_32函数生成一个验证码。此时,验证过程需要读入license文件中的数字,然后将两者进行比较,如果相同,则表示license正确,可以继续以下流程,如果不一样,则表明license出现问题,程序终止。

 

五 拓展

1.       加入其他限制

因为生成license的原理是通过一个字符串生成一个验证码,于是,这个字符串的内容是可以任意修改的。也就是说,可以根据需要加入一些限制条件。

例如,要限制某个程序的最大网络连接数为200,那么就可以加入200这个数字在字符串中,生成一个新的验证码,而在license文件中写入类似:max_conns = 200的内容。当验证license时,验证流程读入max_conns的值作为全局变量,同时再通过计算license的验证码是否正确。一旦正确,那么max_conns的值(200)就成为程序的一个全局变量,可以用它来限制最大连接数。如果有人修改了license文件,使得max_conns的值发生变化,那么验证过程根据新的max_conns值所得到的验证码就跟license文件的验证码不一样,这样验证不过关,表示license文件是错误的。

另外,在license中加入验证时间的有效性也是常用的方法。

 

2.       生成license文件的变化

上面讨论的生成license和验证license的过程,都是在Linux操作系统中生成的。在生成license时,因为CPU和MAC地址的关系,必须在同一台机器上操作,这样带来了很大不方面,而且不利于保密。

一个改进的办法是,将生成license文件的过程拆成两个步骤:

第一步,将获得的CPU和MAC地址信息放入一个文件;

第二步,将文件传递到某个平台,由该平台生成license文件。

这样的好处是,生成license文件的执行程序可以是Linux系统的,也可以是Windows系统下的,而且不需要在同一台机器上运行。

       附录的源码就是这样一个过程。

 

 (相关附录的源码放在http://laopang.vip.sina.com/articles/own/Tech/linux.license.rar)

标签:addr,license,int,ifc,ifr,License,Linux,软件,x86
From: https://www.cnblogs.com/lidabo/p/17407697.html

相关文章

  • 软件License设计思路与实现方案
     文章目录前言一、在License中保存配置1.有效期2.机器ID3.其他限制条件二、加密配置信息三、配置信息签名总结 前言       最近接到一个需求,需要给我们的软件系统增加一个License授权的机制,可以把软件系统部署到客户的服务器供客户试用,到期后系统......
  • Linux-用户和权限管理
    用户管理命令命令作用useradd创建用户usermod修改用户信息userdel删除用户及配置文件passwd修改用户密码chpasswd批量更新用户密码change修改用户密码属性id查看用户UID,GID,组信息su切换用户sudo用root身份执行命令visudo编辑sudoe......
  • 软件License设计
    如何保护软件版权,最常用的办法就是设计一套license验证框架。1、我们的常规需求如下:1.可以限制软件只能在一台机器上使用;目前很多软件都是一机一码的销售,软件换一台机器则不能使用,想要几台机器使用就得购买几个license;2.可以设置一个使用期限;试用版软件一般有几十天的免......
  • Linux下文本格式异常:with CRLF line terminators
    linux下在处理文本时,有时会遇到列打印或者显示异常:这是因为有些命令输出重写向到文本,会带入默认Windows文本格式,正常的linux文本中每行是以换行符(\n)结束,windows文本中每行是以回车+换行符(\r\n)结束,可以通过dos2unix工具进行转换:通过file文件名命令可以查看输出:linux文本格式为:A......
  • Linux- 环境变量和自定义配置
    环境变量查看查看当前用户的全部环境变量:env,可以结合env|grep筛选信息查看当前系统的全部环境变量:export查看指定环境变量:printenv$env_name或者echo$env_name清除指定环境变量的值:unset$env_name常用环境变量PATH可执行程序的搜索目录,可执行程序包括Linux......
  • Linux 中 shell 脚本实现根据gff统计每一个基因的转录本数目
     001、生成基因名称的列表awk-F"\t"'$3=="gene"&&$NF~/gene=/{print$NF}'chr1.gff|sed's/\(.*\)\(gene=[^;]\+\)\(.*\)/\2/'|sort|uniq>gene.list 002、 ......
  • DBeaver 22.3.0 Ultimate最新和谐版本(windows+linux)
    概述 DBeaver是一款流行的开源数据库管理工具,支持多种数据库,如MySQL、PostgreSQL、SQLite、Oracle、MicrosoftSQLServer等。它提供了一个统一的界面,使得用户能够方便地连接、管理和查询各种类型的数据库。功能支持多种数据库:DBeaver支持多种数据库引擎,如MySQL、PostgreSQL......
  • Rockchip RK3399 - linux内核移植
    ----------------------------------------------------------------------------------------------------------------------------开发板  :NanoPC-T4开发板eMMC  :16GBLPDDR3:4GB显示屏 :15.6英寸HDMI接口显示屏u-boot  :2017.09linux   :5.10.110-----------------......
  • 人件集 人性化的软件开发阅读笔记01
    《人件集:人性化的软件开发》第一部分团队开发第一章决策,决策讲述了中庸的风险以及轻度领导研究表明,集体的决策比从集体中的个体独立做选择更具有风险倾向。如果将这种决策模式应用于软件编程,我们可能会看到这样的结果:团队可能使用更奇特的数据结构、更古怪的算法或者更......
  • Linux gcc升级
    源码编译1.查看当前gcc版本#gcc--versiongcc(GCC)4.8.520150623(RedHat4.8.5-44)Copyright(C)2015FreeSoftwareFoundation,Inc.Thisisfreesoftware;seethesourceforcopyingconditions.ThereisNOwarranty;notevenforMERCHANTABILITYorFITNES......