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
14 * Szabo, Janos Zoltan – initial implementation
17 ******************************************************************************/
23 #include <sys/types.h>
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>
44 # include <openssl/md5.h>
48 # include <interix/interix.h>
49 # include <openssl/md5.h>
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
60 /* In official releases: */
61 #define TTCN3_VERSION_CHECK TTCN3_MAJOR * 10000 + TTCN3_MINOR * 100 + TTCN3_PATCHLEVEL
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
;
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 };
76 /** Big-endian decoding of a 4-byte integer */
77 static unsigned int decode_int(const unsigned char *from
)
79 return (unsigned int)from
[3]
80 | ((unsigned int)from
[2] << 8)
81 | ((unsigned int)from
[1] << 16)
82 | ((unsigned int)from
[0] << 24);
85 /** Extract a string from a fixed-length field.
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
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
)
100 for (i
= 0; i
< max_length
&& from
[i
] != '\0'; 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",
109 ptr
= (char*)Malloc(length
+ 1);
110 memcpy(ptr
, from
, length
);
115 static void decode_license(license_struct
*to
, const license_raw
*from
)
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
);
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
;
145 to
->limitation_type
= decode_int(from
->limitation_type
);
146 to
->max_ptcs
= decode_int(from
->max_ptcs
);
149 static void check_license_signature(license_raw
*lptr
)
151 unsigned char message_digest
[SHA_DIGEST_LENGTH
];
153 DSA
*dsa
= DSA_new();
156 SHA1_Update(&sha_ctx
, lptr
, sizeof(*lptr
) - sizeof(lptr
->dsa_signature
));
157 SHA1_Final(message_digest
, &sha_ctx
);
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
);
164 // calculate the right len of the signiture
165 DSA_SIG
*temp_sig
=DSA_SIG_new();
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
));
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
);
179 switch(DSA_verify(0, message_digest
, sizeof(message_digest
),
180 lptr
->dsa_signature
, siglen
, dsa
)) {
182 fputs("License file is corrupted: invalid DSA signature.\n", stderr
);
185 break; /* valid signature */
187 fprintf(stderr
, "License signature verification failed: %s\n",
188 ERR_error_string(ERR_get_error(), NULL
));
195 /** Read a PEM-encoded license from a file.
197 * @param [in] file_name string containing license file name
198 * @param [out] lptr filled with the decoded license information
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
)
206 unsigned char *data
= NULL
;
211 if (stat(file_name
, &buf
) != 0) {
212 fprintf(stderr
, "Cannot access license file `%s'. (%s)\n",
213 file_name
, strerror(errno
));
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
);
222 fp
= fopen(file_name
, "r");
224 fprintf(stderr
, "Cannot open license file `%s' for reading. (%s)\n",
225 file_name
, strerror(errno
));
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
));
234 if (strcmp(name
, "TTCN-3 LICENSE FILE") || strcmp(header
, "")) {
235 fputs("License file is corrupted: invalid header.\n", stderr
);
238 if (len
!= sizeof(*lptr
)) {
239 fputs("License file is corrupted: invalid length.\n", stderr
);
242 memcpy(lptr
, data
, sizeof(*lptr
));
244 OPENSSL_free(header
);
248 void load_license(license_struct
*lptr
)
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",
256 load_license_from_file(lptr
, file_name
);
259 void load_license_from_file(license_struct
*lptr
, const char *file_name
)
262 read_license(file_name
, &lraw
);
263 check_license_signature(&lraw
);
264 decode_license(lptr
, &lraw
);
265 lptr
->license_file
= mcopystr(file_name
);
268 void free_license(license_struct
*lptr
)
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
;
284 int verify_license(const license_struct
*lptr
)
286 time_t current_time
= time(NULL
);
289 if (current_time
< lptr
->valid_from
) {
290 fputs("The license key is not yet valid.\n", stderr
);
294 if (current_time
> lptr
->valid_until
) {
295 fputs("The license key has already expired.\n", stderr
);
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
);
310 if (lptr
->limitation_type
& LIMIT_USER
) {
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
);
321 fprintf(stderr
, "Getting the current user name failed when "
322 "verifying the license key. Windows error code: %d.\n",
323 (int)GetLastError());
327 uid_t process_uid
= getuid();
330 p
= getpwuid(process_uid
);
332 fprintf(stderr
, "The current user ID (%d) does not have login "
333 "name.\n", (int)process_uid
);
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
);
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
);
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" : "");
373 /* setpwent and getpwuid calls may use some system calls that fail.
374 * We should ignore these error codes in future error messages. */
379 unsigned int check_feature(const license_struct
*lptr
, unsigned int feature
)
381 return (lptr
->feature_list
& feature
) != 0;
384 void print_license(const license_struct
*lptr
)
387 "---------------------------------------------------------------\n"
388 "License file : %s\n"
395 lptr
->license_file
!= NULL
? lptr
->license_file
: "",
398 lptr
->licensee_email
,
399 lptr
->licensee_company
,
400 lptr
->licensee_department
,
401 ctime(&lptr
->valid_from
));
408 "Versions : from %d.%d.pl%d until %d.%d.pl%d\n"
410 "Encoders :%s%s%s%s%s\n"
411 "Applications :%s%s%s%s%s%s\n"
413 "---------------------------------------------------------------\n",
414 ctime(&lptr
->valid_until
),
415 lptr
->limitation_type
& LIMIT_HOST
? " HOST" : "",
416 lptr
->limitation_type
& LIMIT_USER
? " USER" : "",
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" : "",
437 void print_license_info()
441 fputs("License information:\n", stderr
);
444 print_license(&lstr
);
445 license_valid
= verify_license(&lstr
);
449 if (!license_valid
) {
453 fputs("The license key is valid.\n", stderr
);
458 if (!RAND_status()) {
459 time_t time_sec
= time(NULL
);
460 if (time_sec
== (time_t)-1) {
461 perror("time() system call failed");
464 RAND_seed(&time_sec
, sizeof(time_sec
));
466 while (!RAND_status()) {
469 GetSystemTimeAsFileTime(&filetime
);
470 RAND_seed(&filetime
.dwLowDateTime
, sizeof(filetime
.dwLowDateTime
));
473 if (gettimeofday(&tv
, NULL
) == -1) {
474 perror("gettimeofday() system call failed");
477 RAND_seed(&tv
.tv_usec
, sizeof(tv
.tv_usec
));
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. */
492 const char * openssl_version_str(void) {
493 return SSLeay_version(SSLEAY_VERSION
);
496 #if defined(WIN32) || defined(INTERIX)
499 #define INTERIX_PREFIX "\\Registry\\Machine\\"
501 #define INTERIX_PREFIX
504 static const char * const keys
[] = {
505 INTERIX_PREFIX
"Software\\Microsoft\\Windows\\CurrentVersion\\",
506 INTERIX_PREFIX
"Software\\Microsoft\\Windows NT\\CurrentVersion\\",
510 static const char * const values
[] = {
511 /* Product specific info */
516 "CurrentBuildNumber",
517 /* Unique identifiers */
521 /* User specific info */
523 "RegisteredOrganization",
524 /* Installation specific info */
526 "FirstInstallDateTime",
536 const char * const *subKey
;
538 unsigned char digest
[MD5_DIGEST_LENGTH
];
544 for (subKey
= keys
; *subKey
!= NULL
; subKey
++) {
546 const char * const *valueName
;
548 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE
, *subKey
,
549 0, KEY_QUERY_VALUE
, &hKey
) != ERROR_SUCCESS
)
552 for (valueName
= values
; *valueName
!= NULL
; valueName
++) {
554 unsigned char *buffer
;
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
)
561 MD5_Update(&context
, buffer
, length
);
567 MD5_Final(digest
, &context
);
568 for (i
= 0; i
< sizeof(hostid
); i
++) hostid
|= digest
[i
] << i
* 8;
579 const char * const *subKey
;
582 unsigned char digest
[MD5_DIGEST_LENGTH
];
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;
591 unsigned char *buffer
;
592 char * key
= mcopystr(*subKey
);
593 key
= mputstr(key
, *valueName
);
595 ret
= getreg(key
, &type
, 0, &size
); /* query the size; ret always -1 */
597 buffer
= Malloc(size
);
598 ret
= getreg(key
, &type
, buffer
, &size
);
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.
609 const unsigned char *from
= buffer
, *end
= buffer
+ size
;
610 unsigned char *to
= buffer
;
611 for (; from
< end
; ++from
) { /* Yes, from is incremented twice */
619 MD5_Update(&context
, buffer
, size
);
627 MD5_Final(digest
, &context
);
628 for (i
= 0; i
< sizeof(hostid
); i
++) hostid
|= digest
[i
] << (i
* 8);
This page took 0.055988 seconds and 5 git commands to generate.