1 /***********************************************************************/
2 /* Open Visualization Data Explorer                                    */
3 /* (C) Copyright IBM Corp. 1989,1999                                   */
4 /* ALL RIGHTS RESERVED                                                 */
5 /* This code licensed under the                                        */
6 /*    "IBM PUBLIC LICENSE - Open Visualization Data Explorer"          */
7 /***********************************************************************/
8 
9 #include <dxconfig.h>
10 #include "../base/defines.h"
11 
12 
13 #if defined(DXD_LICENSED_VERSION)
14 
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <ctype.h>
18 #include <sys/time.h>
19 #include <time.h>
20 #ifndef DXD_DO_NOT_REQ_UNISTD_H
21 #include <unistd.h>
22 #endif
23 
24 
25 #if defined(ibm6000)
26 extern "C" void gettimer (int, struct timestruc_t* );
27 #endif
28 
29 #include "DXStrings.h"
30 
31 #if defined(aviion) || defined(solaris) || defined(sgi)
32 #include <crypt.h>
33 #endif
34 
35 #if defined(ibm6000) || defined(hp700)
36 #include <sys/utsname.h>
37 #if defined(ibm6000) && !defined(_AIX41)
38 extern "C" const char *crypt(const char* , const char*);
39 #else
40 extern "C" char *crypt(const char* , const char*);
41 #endif
42 #endif
43 
44 #if defined(aviion) || defined(solaris) || defined(sgi)
45 #include <sys/systeminfo.h>
46 #endif
47 #if defined(sgi) && !( __mips > 1)
48 extern "C" unsigned sysid(unsigned char *id);
49 #endif
50 #if defined(aviion)
51 extern "C" long sysinfo (int , char *, long );
52 #endif
53 #if defined(aviion)
54 extern "C" int gettimeofday(struct timeval *);
55 #endif
56 
57 #if defined(sun4)
58 extern "C" long gethostid();
59 #endif
60 
61 #ifdef alphax
62 #include <crypt.h>
63 int getdtablesize();
64 #include <stdio.h>              /* standard I/O */
65 #include <errno.h>              /* error numbers */
66 
67 #if defined(windows) && defined(HAVE_WINSOCK_H)
68 #include <winsock.h>
69 #elif defined(HAVE_CYGWIN_SOCKET_H)
70 #include <cygwin/socket.h>
71 #elif defined(HAVE_SYS_SOCKET_H)
72 #include <sys/socket.h>
73 #endif
74 
75 #include <sys/ioctl.h>          /* ioctls */
76 #include <net/if.h>             /* generic interface structures */
77 #include <sys/systeminfo.h>  /* maybe someday this will be implemented...arg! */
78 extern "C"   int select(int , fd_set *, fd_set *, fd_set *, struct timeval *) ;
79 #endif
80 
81 #include "TemporaryLicense.h"
82 
83 
84 const char *
MakeKey(enum Arkh arch,char * hostId,int months,int days,time_t * newTime,enum DxType type)85 TemporaryLicense::MakeKey
86     (enum Arkh arch, char *hostId, int months, int days,
87 	time_t *newTime, enum DxType type)
88 {
89     char               host[9];
90 #if defined(ibm6000)
91     struct timestruc_t sysTime;
92 #else
93     timeval sysTime;
94 #endif
95     struct tm          timeStruct;
96     char	       cryptHost[301];
97     char	       cryptTime[301];
98     int                i;
99     static char	      key[100];
100 
101 
102     if (strlen(hostId) > 8 ||
103 	arch == IBM6000 ||
104 	arch == HP700 ||
105 	arch == SGI)
106 	strncpy(host, hostId+2, 8);
107     else
108 	strncpy(host, hostId, 8);
109     host[8] = '\0';
110 
111 #if defined(aviion)
112     gettimeofday(&sysTime);
113 #else
114 #if defined(ibm6000)
115     gettimer(TIMEOFDAY, &sysTime);
116 #else
117     gettimeofday(&sysTime, NULL);
118 #endif
119 #endif
120 #if defined(ibm6000) || defined(hp700)
121     time_t tvs = sysTime.tv_sec;
122     timeStruct = *localtime(&tvs);
123     sysTime.tv_sec = (unsigned long)tvs;
124 #else
125     timeStruct = *localtime(&sysTime.tv_sec);
126 #endif
127     timeStruct.tm_mday += days;
128     timeStruct.tm_mon  += timeStruct.tm_mday / 30;
129     timeStruct.tm_mday  = timeStruct.tm_mday % 30;
130     timeStruct.tm_mon  += months;
131     timeStruct.tm_year += timeStruct.tm_mon / 12;
132     timeStruct.tm_mon   = timeStruct.tm_mon % 12;
133 
134 #if defined(sun4)
135     *newTime = timelocal(&timeStruct);
136 #else
137     *newTime = mktime(&timeStruct);
138 #endif
139 
140     *newTime ^= XOR_KEY;
141 
142     if (type == UP)
143       sprintf(cryptTime, "As%08x95D", *newTime);
144     else if (type == SMP)
145       sprintf(cryptTime, "Am%08x9lD", *newTime);
146 
147     *newTime ^= XOR_KEY;
148 
149     strcpy(cryptHost, crypt(host, KEY1));
150 
151     for (i = 0; i < strlen(cryptHost); ++i) {
152 	key[2*i] = cryptHost[i];
153 	key[2*i+1] = cryptTime[i];
154     }
155     key[2*i] = '\0';
156 
157     return key;
158 }
159 
160 
161 
162 //
163 // Warn the user that we're about to go away.  Set a timer.  When the timer
164 // goes off, bye bye.
165 //
LostLicense(XtPointer,int * fid,XtInputId *)166 static void LostLicense(XtPointer , int* fid, XtInputId*)
167 {
168     //
169     // As of 3.1.4, we're going to try to read from the file descriptor.
170     // If there is any byte at all we're going to just keep
171     // on running.  If we see error, or eof, then we'll assume that
172     // dxshadow died and that we should die also.
173     //
174     char buff[256];
175     int bread;
176     bread = read(*fid, buff, 256);
177     if (bread > 0) {
178         while (bread == 256)
179             bread = read(*fid, buff, 256);
180     } else {
181 	exit(1);
182     }
183 }
184 
185 void
determineUILicense(LicenseTypeEnum * app,LicenseTypeEnum * func)186 TemporaryLicense::determineUILicense(LicenseTypeEnum *app, LicenseTypeEnum *func)
187 {
188     *app = Unlicensed;
189     UIGetLicense(this->getRootDir(), LostLicense, app,func);
190 }
191 
192 
initialize()193 void TemporaryLicense::initialize()
194 {
195 
196     //
197     // Find out what we've got for a license.
198     //
199     LicenseTypeEnum app_lic, func_lic;
200     app_lic = TimedLicense;
201     func_lic = Unlicensed;
202     if (getenv("DXTRIALKEY")) {
203     } else {
204 	this->determineUILicense(&app_lic, &func_lic);
205 
206 	//
207 	// Problems:
208 	// - A UP license on an SMP machine gets full smp ability because
209 	// the trial key I'm generating is using the SMP flag.
210 	// - If the user replaces the dxui executable with something of his own
211 	// which simply prints out the environment, then he'll get to see his
212 	// trial key which will give him full developer, multi-user, smp
213 	// capability.
214 	// - If the user edits the dx.workerscript, he could thwart my attempt
215 	// to limit the functioning of dxui since I'm just passing cmd line args
216 	// to the script when I use DXLStartDX().
217 	//
218 
219 	//
220 	// If we got a floating developer license, then we'll go ahead an unleash
221 	// full use of the product.  If the license is runtime or nodelocked, then
222 	// the product has to be restricted:
223 	// 1) to prevent the user from reconnecting to a remote exec which
224 	// would effectively allow unlimited use since you can run any number
225 	// of dxui's on one machine if the dxexec's are remote.
226 	// 2) to prevent editor access which turns a runtime into a developer license.
227 	//
228 	if ((func_lic == DeveloperLicense) && (getenv("DXTEST_RUNTIME") == NUL(char*)) &&
229 	    ((app_lic == NodeLockedLicense) || (app_lic == ConcurrentLicense)) ) {
230 	    if (app_lic == NodeLockedLicense) {
231 		//
232 		// If you want to add something special for the case of nodelocked
233 		// developer license, this is the place.  I originally used
234 		// -noConnectionMenus so that the user would be unable to send
235 		// the trial key to another machine which would effectively allow
236 		// unlimited use of the produce.  Now, that trial key won't work
237 		// on another host, so -noConn isn't needed.
238 		//
239 		//this->setDxuiArgs(" -noConnectionMenus ");
240 		//this->limited_use = TRUE;
241 	    }
242 	} else {
243 	    this->setDxuiArgs(this->getLimitedArgs());
244 	    this->limited_use = TRUE;
245 	}
246 
247 	if (func_lic != Unlicensed) {
248 
249 	    //
250 	    // If we got a good license, then put a trial key into the environment
251 	    // I think a reasonable alternative to the trial key would be encrypting
252 	    // the time.  Then the child app could do the same.  (Excluding seconds)
253 	    // Then if we gave the child app our encrypted time, she could compare
254 	    // and know (authenticate) that the parent is in fact startup.  Then
255 	    // no licensing would be required.
256 	    //
257 	    // Security problems: If someone replaces the dxui executable, it would
258 	    // be simple to print out the environment and obtain the trial key we're
259 	    // using.
260 	    //
261 	    char host[64];
262 
263 	    // S G I     S G I     S G I     S G I     S G I     S G I     S G I
264 #	if defined(sgi)
265 #	if ( __mips > 1)
266 	    sysinfo (SI_HW_SERIAL, host, sizeof(host));
267 #	else
268             // this should really be an unsigned int because that's what sysid
269 	    // returns, but it HAS to be long to be compatible with the UI and exec
270 	    long name = (long)sysid(NULL);
271 	    sprintf (host, "%d", name);
272 	    strcpy (host, host+2);
273 #	endif
274 #	endif
275 
276 	    // H P 7 0 0     H P 7 0 0     H P 7 0 0     H P 7 0 0     H P 7 0 0
277 #	if defined(hp700)
278 	    struct utsname name;
279 	    uname (&name);
280 	    name.idnumber[10] = '\0';
281 	    strcpy (host, name.idnumber+2);
282 #	endif
283 
284 	    // S O L A R I S     S O L A R I S     S O L A R I S     S O L A R I S
285 #	if defined(solaris)
286 	    sysinfo(SI_HW_SERIAL,host,301);
287 	    sprintf(host, "%x", atol(host));
288 #	endif
289 
290 	    // A V I I O N     A V I I O N     A V I I O N     A V I I O N
291 #	if defined(aviion)
292 	    sysinfo(SI_HW_SERIAL,host,301);
293 #	endif
294 
295 	    // I B M 6 0 0 0     I B M 6 0 0 0     I B M 6 0 0 0     I B M 6 0 0 0
296 #	if defined(ibm6000)
297 	    struct utsname name;
298 	    uname (&name);
299 	    name.machine[10] = '\0';
300 	    strcpy (host, name.machine+2);
301 #	endif
302 
303 	    // S U N 4     S U N 4     S U N 4     S U N 4     S U N 4     S U N 4
304 #	if defined(sun4)
305 	    sprintf (host, "%x", gethostid());
306 #	endif
307 
308 	    // A L P H A X     A L P H A X     A L P H A X     A L P H A X
309 #	if defined(alphax)
310 	    {
311 		char *dflt_devices[] = {"tu0","ln0", NULL };
312 		char *device;
313 		int found, s,i        /* On Alpha OSF/1 we use ethernet */;
314 
315 		/* Get a socket */
316 		s = socket(AF_INET,SOCK_DGRAM,0);
317 		if (s < 0) {
318 		    perror("socket");
319 		    exit(1);
320 		}
321 		for (found=i=0, device=(char*)getenv("DXKEYDEVICE"); dflt_devices[i]; i++) {
322 		    static struct ifdevea devea; /* MAC address from and ioctl()   */
323 		    char *dev, buf[32];
324 		    if (!device)
325 			dev = dflt_devices[i];
326 		    else
327 			dev = device;
328 		    strcpy(devea.ifr_name,dev);
329 		    if (ioctl(s,SIOCRPHYSADDR,&devea) >= 0)  {
330 			strcpy(host,"");
331 			for (i = 2; i < 6; i++){
332 			    sprintf(buf,"%x", devea.default_pa[i] );
333 			    strcat(host,buf);
334 			}
335 			found = 1;
336 			break;
337 		    }
338 		    if (device) break;
339 		}
340 		if (!found)  {
341 		    fprintf(stderr,"Could not find ethernet device.\n");
342 		    strcpy(host,"UNKNOWN");
343 		}
344 		close(s);
345 	    }
346 
347 #	endif
348 
349 	    time_t tim;
350 	    //
351 	    // The use of ANY right here doesn't mean anything.  It isn't an
352 	    // "any" key, it's still nodelocked.  We're just passing ANY because
353 	    // the hostid has already been munged and MakeKey does not need to
354 	    // munge it further as it would in the expire program.
355 	    //
356 	    const char* key = TemporaryLicense::MakeKey(ANY, host, 0, 1, &tim, SMP);
357 
358 	    char* cp = "DXTRIALKEY=";
359 	    char *envsetting = new char[strlen(cp) + strlen(key) + 1];
360 	    sprintf (envsetting, "%s%s", cp,key);
361 	    putenv (envsetting);
362 	    cp = "DXSTARTUP=1";
363 	    envsetting = new char[strlen(cp) + 1];
364 	    strcpy (envsetting, cp);
365 	    putenv (envsetting);
366 	}
367     }
368 
369 }
370 
setDxuiArgs(const char * a)371 void TemporaryLicense::setDxuiArgs(const char* a)
372 {
373     if (dxui_args) delete dxui_args;
374     if (a) dxui_args = DuplicateString(a);
375     else dxui_args = NUL(char*);
376 }
377 
getLimitedArgs()378 const char* TemporaryLicense::getLimitedArgs()
379 {
380     return " -noConnectionMenus -noEditorAccess ";
381 }
382 
383 #endif // DO NOT ADD ANYTHING AFTER THIS ENDIF
384