indentation problem in the generated code
[deliverable/titan.core.git] / common / license.c
1 /******************************************************************************
2 * Copyright (c) 2000-2016 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * Baji, Laszlo
10 * Balasko, Jeno
11 * Beres, Szabolcs
12 * Cserveni, Akos
13 * Raduly, Csaba
14 * Szabo, Janos Zoltan – initial implementation
15 * Szalai, Gabor
16 *
17 ******************************************************************************/
18 #include <stdio.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <time.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <sys/time.h>
26 #ifndef MINGW
27 # include <pwd.h>
28 #endif
29 #include <errno.h>
30
31 #include <openssl/bn.h>
32 #include <openssl/sha.h>
33 #include <openssl/rand.h>
34 #include <openssl/dsa.h>
35 #include <openssl/pem.h>
36 #include <openssl/err.h>
37
38 #ifdef WIN32
39 # include <windows.h>
40 # include <winreg.h>
41 # ifdef MINGW
42 # include <lmcons.h>
43 # endif
44 # include <openssl/md5.h>
45 #endif
46
47 #ifdef INTERIX
48 # include <interix/interix.h>
49 # include <openssl/md5.h>
50 #endif
51
52 #include "memory.h"
53 #include "license.h"
54 #include "version.h"
55
56 #ifdef TTCN3_BUILDNUMBER
57 /* In pre-release builds: */
58 #define TTCN3_VERSION_CHECK TTCN3_MAJOR * 1000000 + TTCN3_MINOR * 10000 + TTCN3_PATCHLEVEL * 100 + TTCN3_BUILDNUMBER
59 #else
60 /* In official releases: */
61 #define TTCN3_VERSION_CHECK TTCN3_MAJOR * 10000 + TTCN3_MINOR * 100 + TTCN3_PATCHLEVEL
62 #endif
63
64 #if TTCN3_VERSION_CHECK != TTCN3_VERSION
65 #error TTCN3_VERSION in version.h does not match the value computed from TTCN3_MAJOR,TTCN3_MINOR,TTCN3_PATCHLEVEL,TTCN3_BUILDNUMBER
66 /* for debugging: these would appear in the preprocessed file */
67 static const int ttcn3_version = TTCN3_VERSION;
68 static const int ttcn3_version_check = TTCN3_VERSION_CHECK;
69 #endif
70
71 static const unsigned char dsa_p[] = { 0x90, 0x63, 0x82, 0xae, 0x72, 0x71, 0xac, 0x14, 0xec, 0x9c, 0x71, 0x38, 0x9f, 0xda, 0x8d, 0x52, 0xbd, 0xb1, 0xa7, 0x1a, 0x19, 0xd4, 0x5f, 0xe7, 0x37, 0x3d, 0x44, 0xef, 0xce, 0xa1, 0x99, 0xfa, 0x85, 0xb6, 0x49, 0x77, 0xf1, 0x98, 0x39, 0x6b, 0x71, 0xce, 0x2, 0x42, 0x64, 0x4b, 0xd, 0xad, 0x83, 0xb0, 0x6b, 0x76, 0xba, 0xdc, 0x4f, 0xe0, 0x19, 0xf9, 0xc2, 0x79, 0x6e, 0xbb, 0xc, 0xab, 0x16, 0xae, 0xec, 0x56, 0x75, 0xff, 0x82, 0xb, 0x74, 0xd8, 0x96, 0x42, 0x23, 0x68, 0xf, 0xad, 0x27, 0xee, 0x4c, 0xbf, 0xf2, 0xd4, 0x49, 0x77, 0x8b, 0x1e, 0xf1, 0xdc, 0x5c, 0x4d, 0xfd, 0xa6, 0xd8, 0x5a, 0x70, 0x3f, 0x13, 0xd2, 0xed, 0x3f, 0x59, 0x9, 0x62, 0x2b, 0xb2, 0x8f, 0xcd, 0x7a, 0xa9, 0x3e, 0x6c, 0xb1, 0xe8, 0x80, 0x9d, 0xd2, 0x74, 0xc, 0xc8, 0xdf, 0xa, 0x40, 0xc9, 0xb3 },
72 dsa_q[] = { 0xa3, 0xe2, 0x23, 0x73, 0xd3, 0x8a, 0x4b, 0x61, 0xd0, 0x60, 0x41, 0x21, 0x41, 0x6d, 0xc4, 0xf6, 0x8c, 0x5c, 0x89, 0x87 },
73 dsa_g[] = { 0x40, 0x6d, 0xfb, 0x6d, 0xb6, 0x6, 0x32, 0xcc, 0xf0, 0xe9, 0x84, 0x16, 0x1e, 0xe1, 0x21, 0xcd, 0x34, 0xe7, 0xbb, 0x6c, 0x98, 0xff, 0xa9, 0xb9, 0xae, 0xe4, 0x6a, 0x61, 0x51, 0xf8, 0x66, 0x83, 0xa4, 0x34, 0x63, 0x81, 0xc4, 0x5f, 0xee, 0x85, 0x74, 0xee, 0x2a, 0x63, 0x9d, 0xcf, 0x97, 0x50, 0xb8, 0x9f, 0x76, 0xd9, 0xe, 0x58, 0xab, 0xac, 0x2e, 0x23, 0xac, 0x95, 0xc3, 0xb7, 0x14, 0xd6, 0x69, 0xff, 0x36, 0xef, 0xa4, 0xa9, 0xe1, 0xd6, 0x7a, 0xfd, 0x9d, 0x68, 0x91, 0xcf, 0x2d, 0xcd, 0x98, 0xc5, 0xe6, 0xf4, 0x1e, 0xde, 0xf8, 0x65, 0x6b, 0xeb, 0x80, 0x41, 0xab, 0xc7, 0x97, 0xcb, 0xbb, 0xc5, 0x5, 0x7, 0x22, 0x81, 0x58, 0x63, 0xf9, 0x67, 0xd4, 0x7c, 0xb6, 0x21, 0x17, 0xea, 0x62, 0xe3, 0xe8, 0x3f, 0x60, 0xb1, 0x51, 0x51, 0x4, 0xf2, 0x6f, 0x5c, 0x47, 0x69, 0x6b, 0xc1 },
74 dsa_pub_key[] = { 0x76, 0xe, 0xf, 0x36, 0x77, 0x6, 0x9d, 0xb1, 0xf1, 0x4e, 0x9a, 0x95, 0xae, 0xc9, 0x39, 0xdf, 0x90, 0xd3, 0x94, 0x54, 0xf8, 0xf6, 0x89, 0xc8, 0x11, 0x8d, 0x2e, 0x92, 0x81, 0x6b, 0x2c, 0x37, 0x4, 0x9d, 0x97, 0x9a, 0x43, 0xa3, 0x2e, 0xed, 0x9a, 0x99, 0xb0, 0xcb, 0x9f, 0x4e, 0xea, 0x4f, 0xb7, 0xd5, 0x93, 0xc0, 0x86, 0x1b, 0xc7, 0x97, 0x5f, 0x5, 0xb4, 0xf1, 0xf9, 0xd6, 0x73, 0x97, 0x19, 0xe3, 0xc9, 0xda, 0xfc, 0x39, 0xe0, 0x37, 0xed, 0x7a, 0x62, 0xcb, 0xe3, 0x17, 0x9b, 0x64, 0x3c, 0x46, 0x86, 0x3f, 0x32, 0xec, 0x70, 0xab, 0x5b, 0x87, 0x5a, 0x6e, 0xc3, 0x37, 0xeb, 0x92, 0x58, 0x6c, 0x9e, 0x25, 0x1f, 0x37, 0x4b, 0xcd, 0xb5, 0x22, 0x62, 0x1d, 0x1b, 0x1c, 0xb1, 0x5d, 0xa1, 0xef, 0x50, 0xc3, 0x75, 0xff, 0x2, 0x24, 0x8c, 0xd7, 0x3b, 0x91, 0x77, 0xef, 0x94, 0x76 };
75
76 /** Big-endian decoding of a 4-byte integer */
77 static unsigned int decode_int(const unsigned char *from)
78 {
79 return (unsigned int)from[3]
80 | ((unsigned int)from[2] << 8)
81 | ((unsigned int)from[1] << 16)
82 | ((unsigned int)from[0] << 24);
83 }
84
85 /** Extract a string from a fixed-length field.
86 *
87 * @param from the beginning of the field
88 * @param max_length the size of the field
89 * @return a newly allocated string. The caller is responsible for
90 * calling Free()
91 *
92 * Verifies that the unused portion of the field is properly zeroed out
93 * (no non-NUL characters after the first NUL character). Terminates
94 * the program with EXIT_FAILURE if there is trailing garbage
95 * after the end of the string. */
96 static char *decode_string(const char *from, size_t max_length)
97 {
98 size_t i, length;
99 char *ptr;
100 for (i = 0; i < max_length && from[i] != '\0'; i++);
101 length = i;
102 /* Verify that the tail is properly zeroed (no junk). */
103 for (i++; i < max_length; i++)
104 if (from[i] != '\0') {
105 fputs("License file is corrupted: invalid string encoding\n",
106 stderr);
107 exit(EXIT_FAILURE);
108 }
109 ptr = (char*)Malloc(length + 1);
110 memcpy(ptr, from, length);
111 ptr[length] = '\0';
112 return ptr;
113 }
114
115 static void decode_license(license_struct *to, const license_raw *from)
116 {
117 to->license_file = NULL;
118 to->unique_id = decode_int(from->unique_id);
119 to->licensee_name = decode_string(from->licensee_name,
120 sizeof(from->licensee_name));
121 to->licensee_email = decode_string(from->licensee_email,
122 sizeof(from->licensee_email));
123 to->licensee_company = decode_string(from->licensee_company,
124 sizeof(from->licensee_company));
125 to->licensee_department = decode_string(from->licensee_department,
126 sizeof(from->licensee_department));
127 to->valid_from = decode_int(from->valid_from);
128 to->valid_until = decode_int(from->valid_until);
129 to->host_id = decode_int(from->host_id);
130 to->login_name = decode_string(from->login_name, sizeof(from->login_name));
131 to->from_major = decode_int(from->from_major);
132 to->from_minor = decode_int(from->from_minor);
133 to->from_patchlevel = decode_int(from->from_patchlevel);
134 to->to_major = decode_int(from->to_major);
135 to->to_minor = decode_int(from->to_minor);
136 to->to_patchlevel = decode_int(from->to_patchlevel);
137 to->feature_list = decode_int(from->feature_list);
138
139 /* Borrow the PER bit for this year */
140 /* 1262300400 is Fri Jan 1 00:00:00 2010 */
141 if((to->feature_list & FEATURE_PER) && (time(NULL) < 1262300400)) {
142 to->feature_list |= FEATURE_XER;
143 }
144
145 to->limitation_type = decode_int(from->limitation_type);
146 to->max_ptcs = decode_int(from->max_ptcs);
147 }
148
149 static void check_license_signature(license_raw *lptr)
150 {
151 unsigned char message_digest[SHA_DIGEST_LENGTH];
152 SHA_CTX sha_ctx;
153 DSA *dsa = DSA_new();
154
155 SHA1_Init(&sha_ctx);
156 SHA1_Update(&sha_ctx, lptr, sizeof(*lptr) - sizeof(lptr->dsa_signature));
157 SHA1_Final(message_digest, &sha_ctx);
158
159 dsa->p = BN_bin2bn(dsa_p, sizeof(dsa_p), NULL);
160 dsa->q = BN_bin2bn(dsa_q, sizeof(dsa_q), NULL);
161 dsa->g = BN_bin2bn(dsa_g, sizeof(dsa_g), NULL);
162 dsa->pub_key = BN_bin2bn(dsa_pub_key, sizeof(dsa_pub_key), NULL);
163
164 // calculate the right len of the signiture
165 DSA_SIG *temp_sig=DSA_SIG_new();
166 int siglen = -1;
167 const unsigned char *data =lptr->dsa_signature;
168 if (temp_sig == NULL || d2i_DSA_SIG(&temp_sig,&data,sizeof(lptr->dsa_signature)) == NULL){
169 fprintf(stderr, "License signature verification failed: %s\n",
170 ERR_error_string(ERR_get_error(), NULL));
171 exit(EXIT_FAILURE);
172 }
173 unsigned char *tmp_buff= NULL;
174 siglen = i2d_DSA_SIG(temp_sig, &tmp_buff);
175 OPENSSL_cleanse(tmp_buff, siglen);
176 OPENSSL_free(tmp_buff);
177 DSA_SIG_free(temp_sig);
178
179 switch(DSA_verify(0, message_digest, sizeof(message_digest),
180 lptr->dsa_signature, siglen, dsa)) {
181 case 0:
182 fputs("License file is corrupted: invalid DSA signature.\n", stderr);
183 exit(EXIT_FAILURE);
184 case 1:
185 break; /* valid signature */
186 default:
187 fprintf(stderr, "License signature verification failed: %s\n",
188 ERR_error_string(ERR_get_error(), NULL));
189 exit(EXIT_FAILURE);
190 }
191
192 DSA_free(dsa);
193 }
194
195 /** Read a PEM-encoded license from a file.
196 *
197 * @param [in] file_name string containing license file name
198 * @param [out] lptr filled with the decoded license information
199 *
200 * If the license information cannot be obtained (bad file name or wrong content),
201 * terminates the program with EXIT_FAILURE. */
202 static void read_license(const char *file_name, license_raw *lptr)
203 {
204 char *name = NULL;
205 char *header = NULL;
206 unsigned char *data = NULL;
207 long len = 0;
208 struct stat buf;
209 FILE *fp;
210
211 if (stat(file_name, &buf) != 0) {
212 fprintf(stderr, "Cannot access license file `%s'. (%s)\n",
213 file_name, strerror(errno));
214 exit(EXIT_FAILURE);
215 }
216 if (buf.st_mode & S_IFDIR) {
217 fprintf(stderr, "The environment variable TTCN3_LICENSE_FILE was set "
218 "to `%s', which is a directory. It must be set to the file that "
219 "contains the license key.\n", file_name);
220 exit(EXIT_FAILURE);
221 }
222 fp = fopen(file_name, "r");
223 if (fp == NULL) {
224 fprintf(stderr, "Cannot open license file `%s' for reading. (%s)\n",
225 file_name, strerror(errno));
226 exit(EXIT_FAILURE);
227 }
228 if (!PEM_read(fp, &name, &header, &data, &len)) {
229 fprintf(stderr, "License file is corrupted: %s\n",
230 ERR_error_string(ERR_get_error(), NULL));
231 exit(EXIT_FAILURE);
232 }
233 fclose(fp);
234 if (strcmp(name, "TTCN-3 LICENSE FILE") || strcmp(header, "")) {
235 fputs("License file is corrupted: invalid header.\n", stderr);
236 exit(EXIT_FAILURE);
237 }
238 if (len != sizeof(*lptr)) {
239 fputs("License file is corrupted: invalid length.\n", stderr);
240 exit(EXIT_FAILURE);
241 }
242 memcpy(lptr, data, sizeof(*lptr));
243 OPENSSL_free(name);
244 OPENSSL_free(header);
245 OPENSSL_free(data);
246 }
247
248 void load_license(license_struct *lptr)
249 {
250 const char *file_name = getenv("TTCN3_LICENSE_FILE");
251 if (file_name == NULL) {
252 fputs("TTCN3_LICENSE_FILE environment variable is not set.\n",
253 stderr);
254 exit(EXIT_FAILURE);
255 }
256 load_license_from_file(lptr, file_name);
257 }
258
259 void load_license_from_file(license_struct *lptr, const char *file_name)
260 {
261 license_raw lraw;
262 read_license(file_name, &lraw);
263 check_license_signature(&lraw);
264 decode_license(lptr, &lraw);
265 lptr->license_file = mcopystr(file_name);
266 }
267
268 void free_license(license_struct *lptr)
269 {
270 Free(lptr->license_file);
271 lptr->license_file = NULL;
272 Free(lptr->licensee_name);
273 lptr->licensee_name = NULL;
274 Free(lptr->licensee_email);
275 lptr->licensee_email = NULL;
276 Free(lptr->licensee_company);
277 lptr->licensee_company = NULL;
278 Free(lptr->licensee_department);
279 lptr->licensee_department = NULL;
280 Free(lptr->login_name);
281 lptr->login_name = NULL;
282 }
283
284 int verify_license(const license_struct *lptr)
285 {
286 time_t current_time = time(NULL);
287 int errflag = 0;
288
289 if (current_time < lptr->valid_from) {
290 fputs("The license key is not yet valid.\n", stderr);
291 errflag = 1;
292 }
293
294 if (current_time > lptr->valid_until) {
295 fputs("The license key has already expired.\n", stderr);
296 errflag = 1;
297 }
298
299 if (lptr->limitation_type & LIMIT_HOST) {
300 /* broken libc call gethostid() performs sign extension on some 64-bit
301 * Linux platforms, thus only the lowest 32 bits are considered */
302 unsigned long host_id = (unsigned long)gethostid() & 0xffffffffUL;
303 if (host_id != lptr->host_id) {
304 fprintf(stderr, "The license key is not valid for this host "
305 "(%08lx).\n", host_id);
306 errflag = 1;
307 }
308 }
309
310 if (lptr->limitation_type & LIMIT_USER) {
311 #ifdef MINGW
312 TCHAR user_name[UNLEN + 1];
313 DWORD buffer_size = sizeof(user_name);
314 if (GetUserName(user_name, &buffer_size)) {
315 if (strcmp(user_name, lptr->login_name)) {
316 fprintf(stderr, "The license key is not valid for this user "
317 "name (%s).\n", user_name);
318 errflag = 1;
319 }
320 } else {
321 fprintf(stderr, "Getting the current user name failed when "
322 "verifying the license key. Windows error code: %d.\n",
323 (int)GetLastError());
324 errflag = 1;
325 }
326 #else
327 uid_t process_uid = getuid();
328 struct passwd *p;
329 setpwent();
330 p = getpwuid(process_uid);
331 if (p == NULL) {
332 fprintf(stderr, "The current user ID (%d) does not have login "
333 "name.\n", (int)process_uid);
334 errflag = 1;
335 } else if (strcmp(p->pw_name, lptr->login_name)) {
336 /* First making a backup copy of the current login name because
337 * the subsequent getpwnam() call will overwrite it. */
338 char *login_name = mcopystr(p->pw_name);
339 /* Another chance: Trying to map the login name of the license key
340 * to a valid UID. Note that it is possible to associate several
341 * login names with the same UID. */
342 p = getpwnam(lptr->login_name);
343 if (p == NULL || p->pw_uid != process_uid) {
344 fprintf(stderr, "The license key is not valid for this login "
345 "name (%s).\n", login_name);
346 errflag = 1;
347 }
348 Free(login_name);
349 }
350 endpwent();
351 #endif
352 }
353
354 if (TTCN3_MAJOR < lptr->from_major ||
355 (TTCN3_MAJOR == lptr->from_major && (TTCN3_MINOR < lptr->from_minor ||
356 (TTCN3_MINOR == lptr->from_minor &&
357 TTCN3_PATCHLEVEL < lptr->from_patchlevel)))) {
358 /* Checking of to_{major,minor,patchlevel} removed when Titan moved
359 * to major version 2 (licenses were valid up to 1.99pl99 only) */
360 fputs("The license key is not valid for this version.\n", stderr);
361 errflag = 1;
362 }
363
364 if (errflag) {
365 return 0;
366 }
367
368 if (lptr->valid_until - current_time < EXPIRY_WARNING * 86400) {
369 time_t expiry_days = (lptr->valid_until - current_time) / 86400 + 1;
370 fprintf(stderr, "Warning: The license key will expire within %ld "
371 "day%s.\n", (long)expiry_days, expiry_days > 1 ? "s" : "");
372 }
373 /* setpwent and getpwuid calls may use some system calls that fail.
374 * We should ignore these error codes in future error messages. */
375 errno = 0;
376 return 1;
377 }
378
379 unsigned int check_feature(const license_struct *lptr, unsigned int feature)
380 {
381 return (lptr->feature_list & feature) != 0;
382 }
383
384 void print_license(const license_struct *lptr)
385 {
386 fprintf(stderr,
387 "---------------------------------------------------------------\n"
388 "License file : %s\n"
389 "Unique ID : %d\n"
390 "Licensee : %s\n"
391 "E-mail : %s\n"
392 "Company : %s\n"
393 "Department : %s\n"
394 "Valid from : %s",
395 lptr->license_file != NULL ? lptr->license_file : "",
396 lptr->unique_id,
397 lptr->licensee_name,
398 lptr->licensee_email,
399 lptr->licensee_company,
400 lptr->licensee_department,
401 ctime(&lptr->valid_from));
402
403 fprintf(stderr,
404 "Valid until : %s"
405 "Limitation :%s%s\n"
406 "Host ID : %08lx\n"
407 "Login name : %s\n"
408 "Versions : from %d.%d.pl%d until %d.%d.pl%d\n"
409 "Languages :%s%s\n"
410 "Encoders :%s%s%s%s%s\n"
411 "Applications :%s%s%s%s%s%s\n"
412 "Max PTCs : %d\n"
413 "---------------------------------------------------------------\n",
414 ctime(&lptr->valid_until),
415 lptr->limitation_type & LIMIT_HOST ? " HOST" : "",
416 lptr->limitation_type & LIMIT_USER ? " USER" : "",
417 lptr->host_id,
418 lptr->login_name,
419 lptr->from_major, lptr->from_minor, lptr->from_patchlevel,
420 lptr->to_major, lptr->to_minor, lptr->to_patchlevel,
421 lptr->feature_list & FEATURE_TTCN3 ? " TTCN3" : "",
422 lptr->feature_list & FEATURE_ASN1 ? " ASN1" : "",
423 lptr->feature_list & FEATURE_RAW ? " RAW" : "",
424 lptr->feature_list & FEATURE_TEXT ? " TEXT" : "",
425 lptr->feature_list & FEATURE_BER ? " BER" : "",
426 lptr->feature_list & FEATURE_PER ? " PER" : "",
427 lptr->feature_list & FEATURE_XER ? " XER" : "",
428 lptr->feature_list & FEATURE_CODEGEN ? " CODEGEN" : "",
429 lptr->feature_list & FEATURE_TPGEN ? " TPGEN" : "",
430 lptr->feature_list & FEATURE_SINGLE ? " SINGLE" : "",
431 lptr->feature_list & FEATURE_MCTR ? " MCTR" : "",
432 lptr->feature_list & FEATURE_HC ? " HC" : "",
433 lptr->feature_list & FEATURE_LOGFORMAT ? " LOGFORMAT" : "",
434 lptr->max_ptcs);
435 }
436
437 void print_license_info()
438 {
439 license_struct lstr;
440 int license_valid;
441 fputs("License information:\n", stderr);
442 init_openssl();
443 load_license(&lstr);
444 print_license(&lstr);
445 license_valid = verify_license(&lstr);
446 free_license(&lstr);
447 free_openssl();
448
449 if (!license_valid) {
450 exit(EXIT_FAILURE);
451 }
452
453 fputs("The license key is valid.\n", stderr);
454 }
455
456 void init_openssl()
457 {
458 if (!RAND_status()) {
459 time_t time_sec = time(NULL);
460 if (time_sec == (time_t)-1) {
461 perror("time() system call failed");
462 exit(EXIT_FAILURE);
463 }
464 RAND_seed(&time_sec, sizeof(time_sec));
465 }
466 while (!RAND_status()) {
467 #ifdef MINGW
468 FILETIME filetime;
469 GetSystemTimeAsFileTime(&filetime);
470 RAND_seed(&filetime.dwLowDateTime, sizeof(filetime.dwLowDateTime));
471 #else
472 struct timeval tv;
473 if (gettimeofday(&tv, NULL) == -1) {
474 perror("gettimeofday() system call failed");
475 exit(EXIT_FAILURE);
476 }
477 RAND_seed(&tv.tv_usec, sizeof(tv.tv_usec));
478 #endif
479 }
480 ERR_load_crypto_strings();
481 /* Random seeding in OpenSSL may use some system calls that fail.
482 * We should ignore these error codes in future error messages. */
483 errno = 0;
484 }
485
486 void free_openssl()
487 {
488 RAND_cleanup();
489 ERR_free_strings();
490 }
491
492 const char * openssl_version_str(void) {
493 return SSLeay_version(SSLEAY_VERSION);
494 }
495
496 #if defined(WIN32) || defined(INTERIX)
497
498 #ifdef INTERIX
499 #define INTERIX_PREFIX "\\Registry\\Machine\\"
500 #else
501 #define INTERIX_PREFIX
502 #endif
503
504 static const char * const keys[] = {
505 INTERIX_PREFIX "Software\\Microsoft\\Windows\\CurrentVersion\\",
506 INTERIX_PREFIX "Software\\Microsoft\\Windows NT\\CurrentVersion\\",
507 NULL
508 };
509
510 static const char * const values[] = {
511 /* Product specific info */
512 "ProductName",
513 "Version",
514 "CurrentVersion",
515 "VersionNumber",
516 "CurrentBuildNumber",
517 /* Unique identifiers */
518 "ProductKey",
519 "ProductId",
520 "DigitalProductId",
521 /* User specific info */
522 "RegisteredOwner",
523 "RegisteredOrganization",
524 /* Installation specific info */
525 "InstallDate",
526 "FirstInstallDateTime",
527 "SystemRoot",
528 NULL
529 };
530 #endif
531
532 #ifdef WIN32
533
534 long gethostid(void)
535 {
536 const char * const *subKey;
537 MD5_CTX context;
538 unsigned char digest[MD5_DIGEST_LENGTH];
539 long hostid = 0;
540 unsigned int i;
541
542 MD5_Init(&context);
543
544 for (subKey = keys; *subKey != NULL; subKey++) {
545 HKEY hKey;
546 const char * const *valueName;
547
548 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, *subKey,
549 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
550 continue;
551
552 for (valueName = values; *valueName != NULL; valueName++) {
553 DWORD length = 0;
554 unsigned char *buffer;
555
556 if (RegQueryValueEx(hKey, *valueName, NULL, NULL, NULL, &length)
557 != ERROR_SUCCESS) continue;
558 buffer = (unsigned char*)Malloc(length);
559 if (RegQueryValueEx(hKey, *valueName, NULL, NULL, buffer, &length)
560 == ERROR_SUCCESS) {
561 MD5_Update(&context, buffer, length);
562 }
563 Free(buffer);
564 }
565 RegCloseKey(hKey);
566 }
567 MD5_Final(digest, &context);
568 for (i = 0; i < sizeof(hostid); i++) hostid |= digest[i] << i * 8;
569 return hostid;
570 }
571
572 #endif
573
574 #ifdef INTERIX
575
576 long gethostid(void)
577 {
578 long hostid = 0;
579 const char * const *subKey;
580 size_t i;
581 MD5_CTX context;
582 unsigned char digest[MD5_DIGEST_LENGTH];
583
584 MD5_Init(&context);
585
586 for (subKey = keys; *subKey != NULL; subKey++) {
587 const char * const *valueName;
588 for (valueName = values; *valueName != NULL; valueName++) {
589 int ret = -13, type = -42;
590 size_t size = 0;
591 unsigned char *buffer;
592 char * key = mcopystr(*subKey);
593 key = mputstr(key, *valueName);
594
595 ret = getreg(key, &type, 0, &size); /* query the size; ret always -1 */
596 if (size > 0) {
597 buffer = Malloc(size);
598 ret = getreg(key, &type, buffer, &size);
599 if (ret == 0) {
600 switch (type) {
601 case WIN_REG_SZ:
602 case WIN_REG_EXPAND_SZ:
603 case WIN_REG_MULTI_SZ: {
604 /* getreg gave use _wide_ strings. Make them narrow.
605 FIXME this assumes everybody is american and uses US-ASCII.
606 It would be more correct to use iconv()
607 but we don't know which codepage to convert to.
608 */
609 const unsigned char *from = buffer, *end = buffer + size;
610 unsigned char *to = buffer;
611 for (; from < end; ++from) { /* Yes, from is incremented twice */
612 *to++ = *from++;
613 }
614 size /= 2;
615 break; }
616 default:
617 break;
618 }
619 MD5_Update(&context, buffer, size);
620 }
621 Free(buffer);
622 }
623 Free(key);
624 }
625 }
626
627 MD5_Final(digest, &context);
628 for (i = 0; i < sizeof(hostid); i++) hostid |= digest[i] << (i * 8);
629 return hostid;
630 }
631
632 #endif
This page took 0.045868 seconds and 5 git commands to generate.