/[rdesktop]/sourceforge.net/trunk/rdesktop/licence.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/trunk/rdesktop/licence.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 24 by matty, Sat Jan 6 03:12:10 2001 UTC revision 317 by astrand, Mon Feb 10 12:56:34 2003 UTC
# Line 1  Line 1 
1  /*  /*
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     RDP licensing negotiation     RDP licensing negotiation
4     Copyright (C) Matthew Chapman 1999-2000     Copyright (C) Matthew Chapman 1999-2002
5        
6     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.     (at your option) any later version.
10      
11     This program is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# Line 18  Line 18 
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */  */
20    
21    #include <sys/types.h>
22    #include <sys/stat.h>
23    #include <unistd.h>
24    #include <fcntl.h>
25    #include <errno.h>
26  #include "rdesktop.h"  #include "rdesktop.h"
27    
28    #ifdef WITH_OPENSSL
29    #include <openssl/rc4.h>
30    #else
31  #include "crypto/rc4.h"  #include "crypto/rc4.h"
32    #endif
33    
34  extern char username[16];  extern char username[16];
35  extern char hostname[16];  extern char hostname[16];
 extern BOOL licence;  
36    
37  static uint8 licence_key[16];  static uint8 licence_key[16];
38  static uint8 licence_sign_key[16];  static uint8 licence_sign_key[16];
39    
40    BOOL licence_issued = False;
41    
42    
43    int
44    load_licence(unsigned char **data)
45    {
46            char *path;
47            char *home;
48            struct stat st;
49            int fd;
50    
51            home = getenv("HOME");
52            if (home == NULL)
53                    return -1;
54    
55            path = xmalloc(strlen(home) + strlen(hostname) + 20);
56            sprintf(path, "%s/.rdesktop/licence.%s", home, hostname);
57    
58            fd = open(path, O_RDONLY);
59            if (fd == -1)
60                    return -1;
61    
62            if (fstat(fd, &st))
63                    return -1;
64    
65            *data = xmalloc(st.st_size);
66            return read(fd, *data, st.st_size);
67    }
68    
69    void
70    save_licence(unsigned char *data, int length)
71    {
72            char *fpath;            /* file path for licence */
73            char *fname, *fnamewrk; /* file name for licence .inkl path. */
74            char *home;
75            uint32 y;
76            struct flock fnfl;
77            int fnfd, fnwrkfd, i, wlen;
78            struct stream s, *s_ptr;
79            uint32 len;
80    
81            /* Construct a stream, so that we can use macros to extract the
82             * licence.
83             */
84            s_ptr = &s;
85            s_ptr->p = data;
86            /* Skip first two bytes */
87            in_uint16(s_ptr, len);
88    
89            /* Skip three strings */
90            for (i = 0; i < 3; i++)
91            {
92                    in_uint32(s_ptr, len);
93                    s_ptr->p += len;
94                    /* Make sure that we won't be past the end of data after
95                     * reading the next length value
96                     */
97                    if ((s_ptr->p) + 4 > data + length)
98                    {
99                            printf("Error in parsing licence key.\n");
100                            printf("Strings %d end value %x > supplied length (%x)\n", i,
101                                   (unsigned int)s_ptr->p,
102                                   (unsigned int)data + length);
103                            return;
104                    }
105            }
106            in_uint32(s_ptr, len);
107            if (s_ptr->p + len > data + length)
108            {
109                    printf("Error in parsing licence key.\n");
110                    printf("End of licence %x > supplied length (%x)\n",
111                           (unsigned int)s_ptr->p + len,
112                           (unsigned int)data + length);
113                    return;
114            }
115    
116            home = getenv("HOME");
117            if (home == NULL)
118                    return;
119    
120            /* set and create the directory -- if it doesn't exist. */
121            fpath = xmalloc(strlen(home) + 11);
122            STRNCPY(fpath, home, strlen(home) + 1);
123    
124            sprintf(fpath, "%s/.rdesktop", fpath);
125            if (mkdir(fpath, 0700) == -1 && errno != EEXIST)
126            {
127                    perror("mkdir");
128                    exit(1);
129            }
130    
131            /* set the real licence filename, and put a write lock on it. */
132            fname = xmalloc(strlen(fpath) + strlen(hostname) + 10);
133            sprintf(fname, "%s/licence.%s", fpath, hostname);
134            fnfd = open(fname, O_RDONLY);
135            if (fnfd != -1)
136            {
137                    fnfl.l_type = F_WRLCK;
138                    fnfl.l_whence = SEEK_SET;
139                    fnfl.l_start = 0;
140                    fnfl.l_len = 1;
141                    fcntl(fnfd, F_SETLK, &fnfl);
142            }
143    
144            /* create a temporary licence file */
145            fnamewrk = xmalloc(strlen(fname) + 12);
146            for (y = 0;; y++)
147            {
148                    sprintf(fnamewrk, "%s.%lu", fname, (long unsigned int)y);
149                    fnwrkfd = open(fnamewrk, O_WRONLY | O_CREAT | O_EXCL, 0600);
150                    if (fnwrkfd == -1)
151                    {
152                            if (errno == EINTR || errno == EEXIST)
153                                    continue;
154                            perror("create");
155                            exit(1);
156                    }
157                    break;
158            }
159            /* write to the licence file */
160            for (y = 0; y < len;)
161            {
162                    do
163                    {
164                            wlen = write(fnwrkfd, s_ptr->p + y, len - y);
165                    }
166                    while (wlen == -1 && errno == EINTR);
167                    if (wlen < 1)
168                    {
169                            perror("write");
170                            unlink(fnamewrk);
171                            exit(1);
172                    }
173                    y += wlen;
174            }
175    
176            /* close the file and rename it to fname */
177            if (close(fnwrkfd) == -1)
178            {
179                    perror("close");
180                    unlink(fnamewrk);
181                    exit(1);
182            }
183            if (rename(fnamewrk, fname) == -1)
184            {
185                    perror("rename");
186                    unlink(fnamewrk);
187                    exit(1);
188            }
189            /* close the file lock on fname */
190            if (fnfd != -1)
191            {
192                    fnfl.l_type = F_UNLCK;
193                    fnfl.l_whence = SEEK_SET;
194                    fnfl.l_start = 0;
195                    fnfl.l_len = 1;
196                    fcntl(fnfd, F_SETLK, &fnfl);
197                    close(fnfd);
198            }
199    
200    }
201    
202  /* Generate a session key and RC4 keys, given client and server randoms */  /* Generate a session key and RC4 keys, given client and server randoms */
203  void licence_generate_keys(uint8 *client_key, uint8 *server_key,  static void
204                             uint8 *client_rsa)  licence_generate_keys(uint8 * client_key, uint8 * server_key, uint8 * client_rsa)
205  {  {
206          uint8 session_key[48];          uint8 session_key[48];
207          uint8 temp_hash[48];          uint8 temp_hash[48];
# Line 46  void licence_generate_keys(uint8 *client Line 217  void licence_generate_keys(uint8 *client
217          sec_hash_16(licence_key, &session_key[16], client_key, server_key);          sec_hash_16(licence_key, &session_key[16], client_key, server_key);
218  }  }
219    
220    static void
221    licence_generate_hwid(uint8 * hwid)
222    {
223            buf_out_uint32(hwid, 2);
224            strncpy((char *) (hwid + 4), hostname, LICENCE_HWID_SIZE - 4);
225    }
226    
227    /* Present an existing licence to the server */
228    static void
229    licence_present(uint8 * client_random, uint8 * rsa_data,
230                    uint8 * licence_data, int licence_size, uint8 * hwid, uint8 * signature)
231    {
232            uint32 sec_flags = SEC_LICENCE_NEG;
233            uint16 length =
234                    16 + SEC_RANDOM_SIZE + SEC_MODULUS_SIZE + SEC_PADDING_SIZE +
235                    licence_size + LICENCE_HWID_SIZE + LICENCE_SIGNATURE_SIZE;
236            STREAM s;
237    
238            s = sec_init(sec_flags, length + 4);
239    
240            out_uint16_le(s, LICENCE_TAG_PRESENT);
241            out_uint16_le(s, length);
242    
243            out_uint32_le(s, 1);
244            out_uint16(s, 0);
245            out_uint16_le(s, 0x0201);
246    
247            out_uint8p(s, client_random, SEC_RANDOM_SIZE);
248            out_uint16(s, 0);
249            out_uint16_le(s, (SEC_MODULUS_SIZE + SEC_PADDING_SIZE));
250            out_uint8p(s, rsa_data, SEC_MODULUS_SIZE);
251            out_uint8s(s, SEC_PADDING_SIZE);
252    
253            out_uint16_le(s, 1);
254            out_uint16_le(s, licence_size);
255            out_uint8p(s, licence_data, licence_size);
256    
257            out_uint16_le(s, 1);
258            out_uint16_le(s, LICENCE_HWID_SIZE);
259            out_uint8p(s, hwid, LICENCE_HWID_SIZE);
260    
261            out_uint8p(s, signature, LICENCE_SIGNATURE_SIZE);
262    
263            s_mark_end(s);
264            sec_send(s, sec_flags);
265    }
266    
267  /* Send a licence request packet */  /* Send a licence request packet */
268  static void licence_send_request(uint8 *client_random, uint8 *rsa_data,  static void
269                                   char *user, char *host)  licence_send_request(uint8 * client_random, uint8 * rsa_data, char *user, char *host)
270  {  {
271          uint32 sec_flags = SEC_LICENCE_NEG;          uint32 sec_flags = SEC_LICENCE_NEG;
272          uint16 userlen = strlen(user) + 1;          uint16 userlen = strlen(user) + 1;
273          uint16 hostlen = strlen(host) + 1;          uint16 hostlen = strlen(host) + 1;
274          uint16 length = 120 + userlen + hostlen;          uint16 length = 128 + userlen + hostlen;
275          STREAM s;          STREAM s;
276    
277          s = sec_init(sec_flags, length + 2);          s = sec_init(sec_flags, length + 2);
# Line 62  static void licence_send_request(uint8 * Line 280  static void licence_send_request(uint8 *
280          out_uint16_le(s, length);          out_uint16_le(s, length);
281    
282          out_uint32_le(s, 1);          out_uint32_le(s, 1);
283          out_uint32_le(s, 0xff010000);          out_uint16(s, 0);
284            out_uint16_le(s, 0xff01);
285    
286          out_uint8p(s, client_random, SEC_RANDOM_SIZE);          out_uint8p(s, client_random, SEC_RANDOM_SIZE);
287          out_uint16(s, 0);          out_uint16(s, 0);
# Line 83  static void licence_send_request(uint8 * Line 302  static void licence_send_request(uint8 *
302  }  }
303    
304  /* Process a licence demand packet */  /* Process a licence demand packet */
305  static void licence_process_demand(STREAM s)  static void
306    licence_process_demand(STREAM s)
307  {  {
308          uint8 null_data[SEC_MODULUS_SIZE];          uint8 null_data[SEC_MODULUS_SIZE];
309          uint8 *server_random;          uint8 *server_random;
310            uint8 signature[LICENCE_SIGNATURE_SIZE];
311            uint8 hwid[LICENCE_HWID_SIZE];
312            uint8 *licence_data;
313            int licence_size;
314            RC4_KEY crypt_key;
315    
316          /* Retrieve the server random from the incoming packet */          /* Retrieve the server random from the incoming packet */
317          in_uint8p(s, server_random, SEC_RANDOM_SIZE);          in_uint8p(s, server_random, SEC_RANDOM_SIZE);
# Line 96  static void licence_process_demand(STREA Line 321  static void licence_process_demand(STREA
321          memset(null_data, 0, sizeof(null_data));          memset(null_data, 0, sizeof(null_data));
322          licence_generate_keys(null_data, server_random, null_data);          licence_generate_keys(null_data, server_random, null_data);
323    
324          /* Send a certificate request back to the server */          licence_size = load_licence(&licence_data);
325            if (licence_size != -1)
326            {
327                    /* Generate a signature for the HWID buffer */
328                    licence_generate_hwid(hwid);
329                    sec_sign(signature, 16, licence_sign_key, 16, hwid, sizeof(hwid));
330    
331                    /* Now encrypt the HWID */
332                    RC4_set_key(&crypt_key, 16, licence_key);
333                    RC4(&crypt_key, sizeof(hwid), hwid, hwid);
334    
335                    licence_present(null_data, null_data, licence_data, licence_size, hwid, signature);
336                    xfree(licence_data);
337                    return;
338            }
339    
340          licence_send_request(null_data, null_data, username, hostname);          licence_send_request(null_data, null_data, username, hostname);
341  }  }
342    
343  /* Send an authentication response packet */  /* Send an authentication response packet */
344  static void licence_send_authresp(uint8 *token, uint8 *crypt_hwid,  static void
345                                    uint8 *signature)  licence_send_authresp(uint8 * token, uint8 * crypt_hwid, uint8 * signature)
346  {  {
347          uint32 sec_flags = SEC_LICENCE_NEG;          uint32 sec_flags = SEC_LICENCE_NEG;
348          uint16 length = 58;          uint16 length = 58;
# Line 128  static void licence_send_authresp(uint8 Line 368  static void licence_send_authresp(uint8
368  }  }
369    
370  /* Parse an authentication request packet */  /* Parse an authentication request packet */
371  static BOOL licence_parse_authreq(STREAM s, uint8 **token, uint8 **signature)  static BOOL
372    licence_parse_authreq(STREAM s, uint8 ** token, uint8 ** signature)
373  {  {
374          uint16 tokenlen;          uint16 tokenlen;
375    
# Line 137  static BOOL licence_parse_authreq(STREAM Line 378  static BOOL licence_parse_authreq(STREAM
378          in_uint16_le(s, tokenlen);          in_uint16_le(s, tokenlen);
379          if (tokenlen != LICENCE_TOKEN_SIZE)          if (tokenlen != LICENCE_TOKEN_SIZE)
380          {          {
381                  ERROR("token len %d\n", tokenlen);                  error("token len %d\n", tokenlen);
382                  return False;                  return False;
383          }          }
384    
# Line 148  static BOOL licence_parse_authreq(STREAM Line 389  static BOOL licence_parse_authreq(STREAM
389  }  }
390    
391  /* Process an authentication request packet */  /* Process an authentication request packet */
392  static void licence_process_authreq(STREAM s)  static void
393    licence_process_authreq(STREAM s)
394  {  {
395          uint8 *in_token, *in_sig;          uint8 *in_token, *in_sig;
396          uint8 out_token[LICENCE_TOKEN_SIZE],          uint8 out_token[LICENCE_TOKEN_SIZE], decrypt_token[LICENCE_TOKEN_SIZE];
                 decrypt_token[LICENCE_TOKEN_SIZE];  
397          uint8 hwid[LICENCE_HWID_SIZE], crypt_hwid[LICENCE_HWID_SIZE];          uint8 hwid[LICENCE_HWID_SIZE], crypt_hwid[LICENCE_HWID_SIZE];
398          uint8 sealed_buffer[LICENCE_TOKEN_SIZE + LICENCE_HWID_SIZE];          uint8 sealed_buffer[LICENCE_TOKEN_SIZE + LICENCE_HWID_SIZE];
399          uint8 out_sig[LICENCE_SIGNATURE_SIZE];          uint8 out_sig[LICENCE_SIGNATURE_SIZE];
# Line 166  static void licence_process_authreq(STRE Line 407  static void licence_process_authreq(STRE
407          RC4_set_key(&crypt_key, 16, licence_key);          RC4_set_key(&crypt_key, 16, licence_key);
408          RC4(&crypt_key, LICENCE_TOKEN_SIZE, in_token, decrypt_token);          RC4(&crypt_key, LICENCE_TOKEN_SIZE, in_token, decrypt_token);
409    
         /* Construct HWID */  
         buf_out_uint32(hwid, 2);  
         strncpy(hwid + 4, hostname, LICENCE_HWID_SIZE - 4);  
   
410          /* Generate a signature for a buffer of token and HWID */          /* Generate a signature for a buffer of token and HWID */
411            licence_generate_hwid(hwid);
412          memcpy(sealed_buffer, decrypt_token, LICENCE_TOKEN_SIZE);          memcpy(sealed_buffer, decrypt_token, LICENCE_TOKEN_SIZE);
413          memcpy(sealed_buffer + LICENCE_TOKEN_SIZE, hwid, LICENCE_HWID_SIZE);          memcpy(sealed_buffer + LICENCE_TOKEN_SIZE, hwid, LICENCE_HWID_SIZE);
414          sec_sign(out_sig, licence_sign_key, 16,          sec_sign(out_sig, 16, licence_sign_key, 16, sealed_buffer, sizeof(sealed_buffer));
                  sealed_buffer, sizeof(sealed_buffer));  
   
         /* Deliberately break signature if licencing disabled */  
         if (!licence)  
                 memset(out_sig, 0, sizeof(out_sig));  
415    
416          /* Now encrypt the HWID */          /* Now encrypt the HWID */
417          RC4_set_key(&crypt_key, 16, licence_key);          RC4_set_key(&crypt_key, 16, licence_key);
# Line 188  static void licence_process_authreq(STRE Line 421  static void licence_process_authreq(STRE
421  }  }
422    
423  /* Process an licence issue packet */  /* Process an licence issue packet */
424  static void licence_process_issue(STREAM s)  static void
425    licence_process_issue(STREAM s)
426  {  {
427          RC4_KEY crypt_key;          RC4_KEY crypt_key;
428          uint32 length;          uint32 length;
# Line 206  static void licence_process_issue(STREAM Line 440  static void licence_process_issue(STREAM
440          if (check != 0)          if (check != 0)
441                  return;                  return;
442    
443          /* We should save the licence here */          licence_issued = True;
444          STATUS("Server issued licence.\n");          save_licence(s->p, length - 2);
445  }  }
446    
447  /* Process a licence packet */  /* Process a licence packet */
448  void licence_process(STREAM s)  void
449    licence_process(STREAM s)
450  {  {
451          uint16 tag;          uint16 tag;
452    
# Line 232  void licence_process(STREAM s) Line 467  void licence_process(STREAM s)
467                          licence_process_issue(s);                          licence_process_issue(s);
468                          break;                          break;
469    
470                    case LICENCE_TAG_REISSUE:
471                            break;
472    
473                  case LICENCE_TAG_RESULT:                  case LICENCE_TAG_RESULT:
474                          break;                          break;
475    
476                  default:                  default:
477                          NOTIMP("licence tag 0x%x\n", tag);                          unimpl("licence tag 0x%x\n", tag);
478          }          }
479  }  }
480    

Legend:
Removed from v.24  
changed lines
  Added in v.317

  ViewVC Help
Powered by ViewVC 1.1.26