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