ReactOS  0.4.12-dev-721-g03c3dd5
licence.c
Go to the documentation of this file.
1 /* -*- c-basic-offset: 8 -*-
2  rdesktop: A Remote Desktop Protocol client.
3  RDP licensing negotiation
4  Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
5  Copyright (C) Thomas Uhle <thomas.uhle@mailbox.tu-dresden.de> 2011
6  Copyright (C) Henrik Andersson <henrik.andersson@cendio.com> 2014
7 
8 
9  This program is free software: you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  (at your option) any later version.
13 
14  This program is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22 
23 #include "precomp.h"
24 
25 void *
27 void
28 rdssl_rc4_info_delete(void * rc4_info);
29 void
30 rdssl_rc4_set_key(void * rc4_info, char * key, int len);
31 void
32 rdssl_rc4_crypt(void * rc4_info, char * in_data, char * out_data, int len);
33 int
34 rdssl_mod_exp(char* out, int out_len, char* in, int in_len,
35  char* mod, int mod_len, char* exp, int exp_len);
36 
37 extern char g_username[256];
38 extern char g_hostname[256];
40 
41 static uint8 g_licence_key[16];
43 
46 
47 /* Generate a session key and RC4 keys, given client and server randoms */
48 static void
49 licence_generate_keys(uint8 * client_random, uint8 * server_random, uint8 * pre_master_secret)
50 {
51  uint8 master_secret[48];
52  uint8 key_block[48];
53 
54  /* Generate master secret and then key material */
55  sec_hash_48(master_secret, pre_master_secret, client_random, server_random, 'A');
56  sec_hash_48(key_block, master_secret, server_random, client_random, 'A');
57 
58  /* Store first 16 bytes of session key as MAC secret */
59  memcpy(g_licence_sign_key, key_block, 16);
60 
61  /* Generate RC4 key from next 16 bytes */
62  sec_hash_16(g_licence_key, &key_block[16], client_random, server_random);
63 }
64 
65 static void
67 {
68  buf_out_uint32(hwid, 2);
69  strncpy((char *) (hwid + 4), g_hostname, LICENCE_HWID_SIZE - 4);
70 }
71 
72 /* Send a lincece info packet to server */
73 static void
74 licence_info(uint8 * client_random, uint8 * rsa_data,
75  uint8 * licence_data, int licence_size, uint8 * hwid, uint8 * signature)
76 {
77  uint32 sec_flags = SEC_LICENSE_PKT;
78  uint16 length =
81  STREAM s;
82 
83  s = sec_init(sec_flags, length + 2);
84 
86  out_uint8(s, ((g_rdp_version >= RDP_V5) ? 3 : 2)); /* version */
88 
89  out_uint32_le(s, 1);
90  out_uint16(s, 0);
91  out_uint16_le(s, 0x0201);
92 
93  out_uint8p(s, client_random, SEC_RANDOM_SIZE);
94  out_uint16_le(s, 2);
96  out_uint8p(s, rsa_data, SEC_MODULUS_SIZE);
98 
99  out_uint16_le(s, 1);
100  out_uint16_le(s, licence_size);
101  out_uint8p(s, licence_data, licence_size);
102 
103  out_uint16_le(s, 1);
106 
107  out_uint8p(s, signature, LICENCE_SIGNATURE_SIZE);
108 
109  s_mark_end(s);
110  sec_send(s, sec_flags);
111 }
112 
113 /* Send a new licence request packet */
114 static void
115 licence_send_new_licence_request(uint8 * client_random, uint8 * rsa_data, char *user, char *host)
116 {
117  uint32 sec_flags = SEC_LICENSE_PKT;
118  uint16 userlen = strlen(user) + 1;
119  uint16 hostlen = strlen(host) + 1;
120  uint16 length =
121  24 + SEC_RANDOM_SIZE + SEC_MODULUS_SIZE + SEC_PADDING_SIZE + userlen + hostlen;
122  STREAM s;
123 
124  s = sec_init(sec_flags, length + 2);
125 
127  out_uint8(s, ((g_rdp_version >= RDP_V5) ? 3 : 2)); /* version */
129 
130  out_uint32_le(s, 1); // KEY_EXCHANGE_ALG_RSA
131  out_uint16(s, 0);
132  out_uint16_le(s, 0xff01);
133 
134  out_uint8p(s, client_random, SEC_RANDOM_SIZE);
135  out_uint16_le(s, 2);
137  out_uint8p(s, rsa_data, SEC_MODULUS_SIZE);
139 
140  /* Username LICENSE_BINARY_BLOB */
142  out_uint16_le(s, userlen);
143  out_uint8p(s, user, userlen);
144 
145  /* Machinename LICENSE_BINARY_BLOB */
147  out_uint16_le(s, hostlen);
148  out_uint8p(s, host, hostlen);
149 
150  s_mark_end(s);
151  sec_send(s, sec_flags);
152 }
153 
154 /* Process a licence request packet */
155 static void
157 {
158  uint8 null_data[SEC_MODULUS_SIZE];
159  uint8 *server_random;
160  uint8 signature[LICENCE_SIGNATURE_SIZE];
161  uint8 hwid[LICENCE_HWID_SIZE];
162  uint8 *licence_data;
163  int licence_size;
164  void * crypt_key;
165 
166  /* Retrieve the server random from the incoming packet */
167  in_uint8p(s, server_random, SEC_RANDOM_SIZE);
168 
169  /* We currently use null client keys. This is a bit naughty but, hey,
170  the security of licence negotiation isn't exactly paramount. */
171  memset(null_data, 0, sizeof(null_data));
172  licence_generate_keys(null_data, server_random, null_data);
173 
174  licence_size = load_licence(&licence_data);
175  if (licence_size > 0)
176  {
177  /* Generate a signature for the HWID buffer */
178  licence_generate_hwid(hwid);
179  sec_sign(signature, 16, g_licence_sign_key, 16, hwid, sizeof(hwid));
180 
181  /* Now encrypt the HWID */
182  crypt_key = rdssl_rc4_info_create();
183  rdssl_rc4_set_key(crypt_key, (char *)g_licence_key, 16);
184  rdssl_rc4_crypt(crypt_key, (char *)hwid, (char *)hwid, sizeof(hwid));
185  rdssl_rc4_info_delete(crypt_key);
186 
187 #if WITH_DEBUG
188  DEBUG(("Sending licensing PDU (message type 0x%02x)\n", LICENCE_TAG_LICENCE_INFO));
189 #endif
190  licence_info(null_data, null_data, licence_data, licence_size, hwid, signature);
191 
192  xfree(licence_data);
193  return;
194  }
195 
196 #if WITH_DEBUG
197  DEBUG(("Sending licensing PDU (message type 0x%02x)\n", LICENCE_TAG_NEW_LICENCE_REQUEST));
198 #endif
200 }
201 
202 /* Send a platform challenge response packet */
203 static void
205 {
206  uint32 sec_flags = SEC_LICENSE_PKT;
207  uint16 length = 58;
208  STREAM s;
209 
210  s = sec_init(sec_flags, length + 2);
211 
213  out_uint8(s, ((g_rdp_version >= RDP_V5) ? 3 : 2)); /* version */
215 
216  out_uint16_le(s, 1);
219 
220  out_uint16_le(s, 1);
222  out_uint8p(s, crypt_hwid, LICENCE_HWID_SIZE);
223 
224  out_uint8p(s, signature, LICENCE_SIGNATURE_SIZE);
225 
226  s_mark_end(s);
227  sec_send(s, sec_flags);
228 }
229 
230 /* Parse a platform challenge request packet */
231 static RD_BOOL
233 {
234  uint16 tokenlen;
235 
236  in_uint8s(s, 6); /* unknown: f8 3d 15 00 04 f6 */
237 
238  in_uint16_le(s, tokenlen);
239  if (tokenlen != LICENCE_TOKEN_SIZE)
240  {
241  error("token len %d\n", tokenlen);
242  return False;
243  }
244 
245  in_uint8p(s, *token, tokenlen);
246  in_uint8p(s, *signature, LICENCE_SIGNATURE_SIZE);
247 
248  return s_check_end(s);
249 }
250 
251 /* Process a platform challenge packet */
252 static void
254 {
255  uint8 *in_token = NULL, *in_sig;
256  uint8 out_token[LICENCE_TOKEN_SIZE], decrypt_token[LICENCE_TOKEN_SIZE];
257  uint8 hwid[LICENCE_HWID_SIZE], crypt_hwid[LICENCE_HWID_SIZE];
258  uint8 sealed_buffer[LICENCE_TOKEN_SIZE + LICENCE_HWID_SIZE];
259  uint8 out_sig[LICENCE_SIGNATURE_SIZE];
260  void * crypt_key;
261 
262  /* Parse incoming packet and save the encrypted token */
263  licence_parse_platform_challenge(s, &in_token, &in_sig);
264  memcpy(out_token, in_token, LICENCE_TOKEN_SIZE);
265 
266  /* Decrypt the token. It should read TEST in Unicode. */
267  crypt_key = rdssl_rc4_info_create();
268  rdssl_rc4_set_key(crypt_key, (char *)g_licence_key, 16);
269  rdssl_rc4_crypt(crypt_key, (char *)in_token, (char *)decrypt_token, LICENCE_TOKEN_SIZE);
270  rdssl_rc4_info_delete(crypt_key);
271 
272  /* Generate a signature for a buffer of token and HWID */
273  licence_generate_hwid(hwid);
274  memcpy(sealed_buffer, decrypt_token, LICENCE_TOKEN_SIZE);
275  memcpy(sealed_buffer + LICENCE_TOKEN_SIZE, hwid, LICENCE_HWID_SIZE);
276  sec_sign(out_sig, 16, g_licence_sign_key, 16, sealed_buffer, sizeof(sealed_buffer));
277 
278  /* Now encrypt the HWID */
279  crypt_key = rdssl_rc4_info_create();
280  rdssl_rc4_set_key(crypt_key, (char *)g_licence_key, 16);
281  rdssl_rc4_crypt(crypt_key, (char *)hwid, (char *)crypt_hwid, LICENCE_HWID_SIZE);
282 
283  licence_send_platform_challenge_response(out_token, crypt_hwid, out_sig);
284 }
285 
286 /* Process a new licence packet */
287 static void
289 {
290  void * crypt_key;
291  uint32 length;
292  int i;
293 
294  in_uint8s(s, 2); // Skip license binary blob type
296  if (!s_check_rem(s, length))
297  return;
298 
299  crypt_key = rdssl_rc4_info_create();
300  rdssl_rc4_set_key(crypt_key, (char *)g_licence_key, 16);
301  rdssl_rc4_crypt(crypt_key, (char *)s->p, (char *)s->p, length);
302  rdssl_rc4_info_delete(crypt_key);
303 
304  /* Parse NEW_LICENSE_INFO block */
305  in_uint8s(s, 4); // skip dwVersion
306 
307  /* Skip strings, Scope, CompanyName and ProductId to get
308  to the LicenseInfo which we store in license blob. */
309  length = 0;
310  for (i = 0; i < 4; i++)
311  {
312  in_uint8s(s, length);
314  if (!s_check_rem(s, length))
315  return;
316  }
317 
319  save_licence(s->p, length);
320 }
321 
322 /* process a licence error alert packet */
323 void
325 {
327  uint32 state_transition;
328  uint32 error_info;
330  in_uint32(s, state_transition);
331  in_uint32(s, error_info);
332 
333  /* There is a special case in the error alert handling, when licensing is all good
334  and the server is not sending a license to client, a "Server License Error PDU -
335  Valid Client" packet is sent which means, every thing is ok.
336 
337  Therefor we should flag that everything is ok with license here.
338  */
339  if (error_code == 0x07)
340  {
342  return;
343  }
344 
345  /* handle error codes, for now, just report them */
346  switch (error_code)
347  {
348  case 0x6: // ERR_NO_LICENSE_SERVER
349  warning("License error alert from server: No license server\n");
350  break;
351 
352  case 0x8: // ERR_INVALID_CLIENT
353  warning("License error alert from server: Invalid client\n");
354  break;
355 
356  case 0x4: // ERR_INVALID_SCOPE
357  case 0xb: // ERR_INVALID_PRODUCTID
358  case 0xc: // ERR_INVALID_MESSAGE_LENGTH
359  default:
360  warning("License error alert from server: code %u, state transition %u\n",
361  error_code, state_transition);
362  break;
363  }
364 
365  /* handle error codes, for now, just report them */
366  switch (error_info)
367  {
368  default:
369  break;
370  }
371 
373 }
374 
375 
376 /* Process a licence packet */
377 void
379 {
380  uint8 tag;
381 
382  in_uint8(s, tag);
383  in_uint8s(s, 3); /* version, length */
384 
385 #if WITH_DEBUG
386  DEBUG(("Received licensing PDU (message type 0x%02x)\n", tag));
387 #endif
388 
389  switch (tag)
390  {
391  case LICENCE_TAG_REQUEST:
393  break;
394 
397  break;
398 
401  /* we can handle new and upgrades of licences the same way. */
403  break;
404 
407  break;
408 
409  default:
410  unimpl("licence tag 0x%02x\n", tag);
411  }
412 }
#define out_uint16_le(s, v)
Definition: parse.h:58
void save_licence(unsigned char *data, int length)
#define out_uint8p(s, v, n)
Definition: parse.h:93
static void licence_process_new_license(STREAM s)
Definition: licence.c:288
#define error(str)
Definition: mkdosfs.c:1605
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
void sec_hash_48(uint8 *out, uint8 *in, uint8 *salt1, uint8 *salt2, uint8 salt)
Definition: secure.c:155
unsigned int uint32
Definition: types.h:32
char * strncpy(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:427
static uint8 g_licence_key[16]
Definition: licence.c:41
STREAM sec_init(uint32 flags, int maxlen)
Definition: secure.c:419
char * host
Definition: whois.c:55
#define LICENCE_TAG_NEW_LICENCE
Definition: constants.h:147
#define out_uint32_le(s, v)
Definition: parse.h:59
#define s_check_rem(s, n)
Definition: parse.h:43
Definition: ecma_167.h:138
#define out_uint16(s, v)
Definition: parse.h:84
RDP_VERSION g_rdp_version
Definition: uimain.c:74
void rdssl_rc4_crypt(void *rc4_info, char *in_data, char *out_data, int len)
Definition: ssl_calls.c:173
#define in_uint8p(s, v, n)
Definition: parse.h:89
#define LICENCE_SIGNATURE_SIZE
Definition: constants.h:143
void licence_process_error_alert(STREAM s)
Definition: licence.c:324
static void licence_generate_keys(uint8 *client_random, uint8 *server_random, uint8 *pre_master_secret)
Definition: licence.c:49
void sec_hash_16(uint8 *out, uint8 *in, uint8 *salt1, uint8 *salt2)
Definition: secure.c:187
void rdssl_rc4_set_key(void *rc4_info, char *key, int len)
Definition: ssl_calls.c:123
#define out_uint8(s, v)
Definition: parse.h:92
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat token
Definition: glfuncs.h:210
#define LICENCE_TOKEN_SIZE
Definition: constants.h:141
#define BB_CLIENT_MACHINE_NAME_BLOB
Definition: constants.h:155
static void licence_info(uint8 *client_random, uint8 *rsa_data, uint8 *licence_data, int licence_size, uint8 *hwid, uint8 *signature)
Definition: licence.c:74
static int error_code[8]
Definition: odbccp32.c:62
static RD_BOOL licence_parse_platform_challenge(STREAM s, uint8 **token, uint8 **signature)
Definition: licence.c:232
smooth NULL
Definition: ftsmooth.c:416
#define SEC_LICENSE_PKT
Definition: constants.h:105
#define in_uint8s(s, n)
Definition: parse.h:91
void buf_out_uint32(uint8 *buffer, uint32 value)
Definition: secure.c:304
int RD_BOOL
Definition: types.h:21
#define out_uint8s(s, n)
Definition: parse.h:95
int load_licence(unsigned char **data)
#define LICENCE_TAG_UPGRADE_LICENCE
Definition: constants.h:148
#define s_check_end(s)
Definition: parse.h:44
static void licence_send_platform_challenge_response(uint8 *token, uint8 *crypt_hwid, uint8 *signature)
Definition: licence.c:204
#define SEC_MODULUS_SIZE
Definition: constants.h:92
static void licence_send_new_licence_request(uint8 *client_random, uint8 *rsa_data, char *user, char *host)
Definition: licence.c:115
#define True
Definition: types.h:24
#define False
Definition: types.h:25
int rdssl_mod_exp(char *out, int out_len, char *in, int in_len, char *mod, int mod_len, char *exp, int exp_len)
Definition: ssl_calls.c:1485
void xfree(void *mem)
Definition: uimain.c:758
#define LICENCE_TAG_REQUEST
Definition: constants.h:145
Definition: types.h:44
void rdssl_rc4_info_delete(void *rc4_info)
Definition: ssl_calls.c:90
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
#define LICENCE_TAG_PLATFORM_CHALLANGE
Definition: constants.h:146
#define SEC_RANDOM_SIZE
Definition: constants.h:91
static FILE * out
Definition: regtests2xml.c:44
unsigned char uint8
Definition: types.h:28
static uint8 g_licence_sign_key[16]
Definition: licence.c:42
#define LICENCE_TAG_LICENCE_INFO
Definition: constants.h:149
#define in_uint32(s, v)
Definition: parse.h:83
#define BB_CLIENT_USER_NAME_BLOB
Definition: constants.h:154
#define LICENCE_TAG_PLATFORM_CHALLANGE_RESPONSE
Definition: constants.h:151
Definition: parse.h:22
#define SEC_PADDING_SIZE
Definition: constants.h:94
enum _RDP_VERSION RDP_VERSION
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
GLdouble s
Definition: gl.h:2039
void sec_send(STREAM s, uint32 flags)
Definition: secure.c:472
static void licence_process_platform_challenge(STREAM s)
Definition: licence.c:253
GLuint in
Definition: glext.h:9616
unsigned short uint16
Definition: types.h:30
RD_BOOL g_licence_error_result
Definition: licence.c:45
#define in_uint8(s, v)
Definition: parse.h:88
void * rdssl_rc4_info_create(void)
Definition: ssl_calls.c:51
void sec_sign(uint8 *signature, int siglen, uint8 *session_key, int keylen, uint8 *data, int datalen)
Definition: secure.c:314
static void licence_process_request(STREAM s)
Definition: licence.c:156
char g_hostname[256]
Definition: uimain.c:26
static void licence_generate_hwid(uint8 *hwid)
Definition: licence.c:66
DWORD exp
Definition: msg.c:15681
char g_username[256]
Definition: uimain.c:25
#define LICENCE_HWID_SIZE
Definition: constants.h:142
void unimpl(char *format,...)
Definition: uimain.c:801
#define LICENCE_TAG_NEW_LICENCE_REQUEST
Definition: constants.h:150
#define DEBUG(args)
Definition: rdesktop.h:129
#define s_mark_end(s)
Definition: parse.h:41
#define LICENCE_TAG_ERROR_ALERT
Definition: constants.h:152
#define in_uint32_le(s, v)
Definition: parse.h:56
#define memset(x, y, z)
Definition: compat.h:39
void user(int argc, const char *argv[])
Definition: cmds.c:1350
void licence_process(STREAM s)
Definition: licence.c:378
#define warning(s)
Definition: debug.h:71
#define in_uint16_le(s, v)
Definition: parse.h:55
Definition: path.c:42
static int mod
Definition: i386-dis.c:1273
char * tag
Definition: main.c:59
RD_BOOL g_licence_issued
Definition: licence.c:44