/[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 10 by matty, Tue Aug 15 10:23:24 2000 UTC revision 320 by astrand, Mon Feb 10 13:05:40 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    static 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    static 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, (unsigned int) data + length);
102                            return;
103                    }
104            }
105            in_uint32(s_ptr, len);
106            if (s_ptr->p + len > data + length)
107            {
108                    printf("Error in parsing licence key.\n");
109                    printf("End of licence %x > supplied length (%x)\n",
110                           (unsigned int) s_ptr->p + len, (unsigned int) data + length);
111                    return;
112            }
113    
114            home = getenv("HOME");
115            if (home == NULL)
116                    return;
117    
118            /* set and create the directory -- if it doesn't exist. */
119            fpath = xmalloc(strlen(home) + 11);
120            STRNCPY(fpath, home, strlen(home) + 1);
121    
122            sprintf(fpath, "%s/.rdesktop", fpath);
123            if (mkdir(fpath, 0700) == -1 && errno != EEXIST)
124            {
125                    perror("mkdir");
126                    exit(1);
127            }
128    
129            /* set the real licence filename, and put a write lock on it. */
130            fname = xmalloc(strlen(fpath) + strlen(hostname) + 10);
131            sprintf(fname, "%s/licence.%s", fpath, hostname);
132            fnfd = open(fname, O_RDONLY);
133            if (fnfd != -1)
134            {
135                    fnfl.l_type = F_WRLCK;
136                    fnfl.l_whence = SEEK_SET;
137                    fnfl.l_start = 0;
138                    fnfl.l_len = 1;
139                    fcntl(fnfd, F_SETLK, &fnfl);
140            }
141    
142            /* create a temporary licence file */
143            fnamewrk = xmalloc(strlen(fname) + 12);
144            for (y = 0;; y++)
145            {
146                    sprintf(fnamewrk, "%s.%lu", fname, (long unsigned int) y);
147                    fnwrkfd = open(fnamewrk, O_WRONLY | O_CREAT | O_EXCL, 0600);
148                    if (fnwrkfd == -1)
149                    {
150                            if (errno == EINTR || errno == EEXIST)
151                                    continue;
152                            perror("create");
153                            exit(1);
154                    }
155                    break;
156            }
157            /* write to the licence file */
158            for (y = 0; y < len;)
159            {
160                    do
161                    {
162                            wlen = write(fnwrkfd, s_ptr->p + y, len - y);
163                    }
164                    while (wlen == -1 && errno == EINTR);
165                    if (wlen < 1)
166                    {
167                            perror("write");
168                            unlink(fnamewrk);
169                            exit(1);
170                    }
171                    y += wlen;
172            }
173    
174            /* close the file and rename it to fname */
175            if (close(fnwrkfd) == -1)
176            {
177                    perror("close");
178                    unlink(fnamewrk);
179                    exit(1);
180            }
181            if (rename(fnamewrk, fname) == -1)
182            {
183                    perror("rename");
184                    unlink(fnamewrk);
185                    exit(1);
186            }
187            /* close the file lock on fname */
188            if (fnfd != -1)
189            {
190                    fnfl.l_type = F_UNLCK;
191                    fnfl.l_whence = SEEK_SET;
192                    fnfl.l_start = 0;
193                    fnfl.l_len = 1;
194                    fcntl(fnfd, F_SETLK, &fnfl);
195                    close(fnfd);
196            }
197    
198    }
199    
200  /* Generate a session key and RC4 keys, given client and server randoms */  /* Generate a session key and RC4 keys, given client and server randoms */
201  void licence_generate_keys(uint8 *client_key, uint8 *server_key,  static void
202                             uint8 *client_rsa)  licence_generate_keys(uint8 * client_key, uint8 * server_key, uint8 * client_rsa)
203  {  {
204          uint8 session_key[48];          uint8 session_key[48];
205          uint8 temp_hash[48];          uint8 temp_hash[48];
206    
207          /* Generate session key - two rounds of sec_hash_48 */          /* Generate session key - two rounds of sec_hash_48 */
208          sec_hash_48(temp_hash,   client_rsa, client_key, server_key, 65);          sec_hash_48(temp_hash, client_rsa, client_key, server_key, 65);
209          sec_hash_48(session_key, temp_hash,  server_key, client_key, 65);          sec_hash_48(session_key, temp_hash, server_key, client_key, 65);
210    
211          /* Store first 16 bytes of session key, for generating signatures */          /* Store first 16 bytes of session key, for generating signatures */
212          memcpy(licence_sign_key, session_key, 16);          memcpy(licence_sign_key, session_key, 16);
213    
214          /* Generate RC4 key */          /* Generate RC4 key */
215          sec_hash_16(licence_key, &session_key[16], client_key, server_key);          sec_hash_16(licence_key, &session_key[16], client_key, server_key);
216  }  }
217    
218    static void
219    licence_generate_hwid(uint8 * hwid)
220    {
221            buf_out_uint32(hwid, 2);
222            strncpy((char *) (hwid + 4), hostname, LICENCE_HWID_SIZE - 4);
223    }
224    
225    /* Present an existing licence to the server */
226    static void
227    licence_present(uint8 * client_random, uint8 * rsa_data,
228                    uint8 * licence_data, int licence_size, uint8 * hwid, uint8 * signature)
229    {
230            uint32 sec_flags = SEC_LICENCE_NEG;
231            uint16 length =
232                    16 + SEC_RANDOM_SIZE + SEC_MODULUS_SIZE + SEC_PADDING_SIZE +
233                    licence_size + LICENCE_HWID_SIZE + LICENCE_SIGNATURE_SIZE;
234            STREAM s;
235    
236            s = sec_init(sec_flags, length + 4);
237    
238            out_uint16_le(s, LICENCE_TAG_PRESENT);
239            out_uint16_le(s, length);
240    
241            out_uint32_le(s, 1);
242            out_uint16(s, 0);
243            out_uint16_le(s, 0x0201);
244    
245            out_uint8p(s, client_random, SEC_RANDOM_SIZE);
246            out_uint16(s, 0);
247            out_uint16_le(s, (SEC_MODULUS_SIZE + SEC_PADDING_SIZE));
248            out_uint8p(s, rsa_data, SEC_MODULUS_SIZE);
249            out_uint8s(s, SEC_PADDING_SIZE);
250    
251            out_uint16_le(s, 1);
252            out_uint16_le(s, licence_size);
253            out_uint8p(s, licence_data, licence_size);
254    
255            out_uint16_le(s, 1);
256            out_uint16_le(s, LICENCE_HWID_SIZE);
257            out_uint8p(s, hwid, LICENCE_HWID_SIZE);
258    
259            out_uint8p(s, signature, LICENCE_SIGNATURE_SIZE);
260    
261            s_mark_end(s);
262            sec_send(s, sec_flags);
263    }
264    
265  /* Send a licence request packet */  /* Send a licence request packet */
266  static void licence_send_request(uint8 *client_random, uint8 *rsa_data,  static void
267                                          char *user, char *host)  licence_send_request(uint8 * client_random, uint8 * rsa_data, char *user, char *host)
268  {  {
269          uint32 sec_flags = SEC_LICENCE_NEG;          uint32 sec_flags = SEC_LICENCE_NEG;
270          uint16 userlen = strlen(user) + 1;          uint16 userlen = strlen(user) + 1;
271          uint16 hostlen = strlen(host) + 1;          uint16 hostlen = strlen(host) + 1;
272          uint16 length = 120 + userlen + hostlen;          uint16 length = 128 + userlen + hostlen;
273          STREAM s;          STREAM s;
274    
275          s = sec_init(sec_flags, length + 2);          s = sec_init(sec_flags, length + 2);
# Line 62  static void licence_send_request(uint8 * Line 278  static void licence_send_request(uint8 *
278          out_uint16_le(s, length);          out_uint16_le(s, length);
279    
280          out_uint32_le(s, 1);          out_uint32_le(s, 1);
281          out_uint32_le(s, 0xff010000);          out_uint16(s, 0);
282            out_uint16_le(s, 0xff01);
283    
284          out_uint8p(s, client_random, SEC_RANDOM_SIZE);          out_uint8p(s, client_random, SEC_RANDOM_SIZE);
285          out_uint16(s, 0);          out_uint16(s, 0);
# Line 83  static void licence_send_request(uint8 * Line 300  static void licence_send_request(uint8 *
300  }  }
301    
302  /* Process a licence demand packet */  /* Process a licence demand packet */
303  static void licence_process_demand(STREAM s)  static void
304    licence_process_demand(STREAM s)
305  {  {
306          uint8 null_data[SEC_MODULUS_SIZE];          uint8 null_data[SEC_MODULUS_SIZE];
307          uint8 *server_random;          uint8 *server_random;
308            uint8 signature[LICENCE_SIGNATURE_SIZE];
309            uint8 hwid[LICENCE_HWID_SIZE];
310            uint8 *licence_data;
311            int licence_size;
312            RC4_KEY crypt_key;
313    
314          /* Retrieve the server random from the incoming packet */          /* Retrieve the server random from the incoming packet */
315          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 319  static void licence_process_demand(STREA
319          memset(null_data, 0, sizeof(null_data));          memset(null_data, 0, sizeof(null_data));
320          licence_generate_keys(null_data, server_random, null_data);          licence_generate_keys(null_data, server_random, null_data);
321    
322          /* Send a certificate request back to the server */          licence_size = load_licence(&licence_data);
323            if (licence_size != -1)
324            {
325                    /* Generate a signature for the HWID buffer */
326                    licence_generate_hwid(hwid);
327                    sec_sign(signature, 16, licence_sign_key, 16, hwid, sizeof(hwid));
328    
329                    /* Now encrypt the HWID */
330                    RC4_set_key(&crypt_key, 16, licence_key);
331                    RC4(&crypt_key, sizeof(hwid), hwid, hwid);
332    
333                    licence_present(null_data, null_data, licence_data, licence_size, hwid, signature);
334                    xfree(licence_data);
335                    return;
336            }
337    
338          licence_send_request(null_data, null_data, username, hostname);          licence_send_request(null_data, null_data, username, hostname);
339  }  }
340    
341  /* Send an authentication response packet */  /* Send an authentication response packet */
342  static void licence_send_authresp(uint8 *token, uint8 *crypt_hwid,  static void
343                                          uint8 *signature)  licence_send_authresp(uint8 * token, uint8 * crypt_hwid, uint8 * signature)
344  {  {
345          uint32 sec_flags = SEC_LICENCE_NEG;          uint32 sec_flags = SEC_LICENCE_NEG;
346          uint16 length = 58;          uint16 length = 58;
# Line 128  static void licence_send_authresp(uint8 Line 366  static void licence_send_authresp(uint8
366  }  }
367    
368  /* Parse an authentication request packet */  /* Parse an authentication request packet */
369  static BOOL licence_parse_authreq(STREAM s, uint8 **token, uint8 **signature)  static BOOL
370    licence_parse_authreq(STREAM s, uint8 ** token, uint8 ** signature)
371  {  {
372          uint16 tokenlen;          uint16 tokenlen;
373    
374          in_uint8s(s, 6); /* unknown: f8 3d 15 00 04 f6 */          in_uint8s(s, 6);        /* unknown: f8 3d 15 00 04 f6 */
375    
376          in_uint16_le(s, tokenlen);          in_uint16_le(s, tokenlen);
377          if (tokenlen != LICENCE_TOKEN_SIZE)          if (tokenlen != LICENCE_TOKEN_SIZE)
378          {          {
379                  ERROR("token len %d\n", tokenlen);                  error("token len %d\n", tokenlen);
380                  return False;                  return False;
381          }          }
382    
# Line 148  static BOOL licence_parse_authreq(STREAM Line 387  static BOOL licence_parse_authreq(STREAM
387  }  }
388    
389  /* Process an authentication request packet */  /* Process an authentication request packet */
390  static void licence_process_authreq(STREAM s)  static void
391    licence_process_authreq(STREAM s)
392  {  {
393          uint8 *in_token, *in_sig;          uint8 *in_token, *in_sig;
394          uint8 out_token[LICENCE_TOKEN_SIZE], decrypt_token[LICENCE_TOKEN_SIZE];          uint8 out_token[LICENCE_TOKEN_SIZE], decrypt_token[LICENCE_TOKEN_SIZE];
# Line 165  static void licence_process_authreq(STRE Line 405  static void licence_process_authreq(STRE
405          RC4_set_key(&crypt_key, 16, licence_key);          RC4_set_key(&crypt_key, 16, licence_key);
406          RC4(&crypt_key, LICENCE_TOKEN_SIZE, in_token, decrypt_token);          RC4(&crypt_key, LICENCE_TOKEN_SIZE, in_token, decrypt_token);
407    
         /* Construct HWID */  
         buf_out_uint32(hwid, 2);  
         strncpy(hwid + 4, hostname, LICENCE_HWID_SIZE - 4);  
   
408          /* Generate a signature for a buffer of token and HWID */          /* Generate a signature for a buffer of token and HWID */
409            licence_generate_hwid(hwid);
410          memcpy(sealed_buffer, decrypt_token, LICENCE_TOKEN_SIZE);          memcpy(sealed_buffer, decrypt_token, LICENCE_TOKEN_SIZE);
411          memcpy(sealed_buffer + LICENCE_TOKEN_SIZE, hwid, LICENCE_HWID_SIZE);          memcpy(sealed_buffer + LICENCE_TOKEN_SIZE, hwid, LICENCE_HWID_SIZE);
412          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));  
413    
414          /* Now encrypt the HWID */          /* Now encrypt the HWID */
415          RC4_set_key(&crypt_key, 16, licence_key);          RC4_set_key(&crypt_key, 16, licence_key);
# Line 187  static void licence_process_authreq(STRE Line 419  static void licence_process_authreq(STRE
419  }  }
420    
421  /* Process an licence issue packet */  /* Process an licence issue packet */
422  static void licence_process_issue(STREAM s)  static void
423    licence_process_issue(STREAM s)
424  {  {
425          RC4_KEY crypt_key;          RC4_KEY crypt_key;
426          uint32 length;          uint32 length;
427          uint16 check;          uint16 check;
428    
429          in_uint8s(s, 2); /* 3d 45 - unknown */          in_uint8s(s, 2);        /* 3d 45 - unknown */
430          in_uint16_le(s, length);          in_uint16_le(s, length);
431          if (!s_check_rem(s, length))          if (!s_check_rem(s, length))
432                  return;                  return;
# Line 205  static void licence_process_issue(STREAM Line 438  static void licence_process_issue(STREAM
438          if (check != 0)          if (check != 0)
439                  return;                  return;
440    
441          /* We should save the licence here */          licence_issued = True;
442          STATUS("Server issued licence.\n");          save_licence(s->p, length - 2);
443  }  }
444    
445  /* Process a licence packet */  /* Process a licence packet */
446  void licence_process(STREAM s)  void
447    licence_process(STREAM s)
448  {  {
449          uint16 tag;          uint16 tag;
450    
451          in_uint16_le(s, tag);          in_uint16_le(s, tag);
452          in_uint8s(s, 2); /* length */          in_uint8s(s, 2);        /* length */
453    
454          switch (tag)          switch (tag)
455          {          {
# Line 231  void licence_process(STREAM s) Line 465  void licence_process(STREAM s)
465                          licence_process_issue(s);                          licence_process_issue(s);
466                          break;                          break;
467    
468                    case LICENCE_TAG_REISSUE:
469                            break;
470    
471                  case LICENCE_TAG_RESULT:                  case LICENCE_TAG_RESULT:
472                          break;                          break;
473    
474                  default:                  default:
475                          NOTIMP("licence tag 0x%x\n", tag);                          unimpl("licence tag 0x%x\n", tag);
476          }          }
477  }  }

Legend:
Removed from v.10  
changed lines
  Added in v.320

  ViewVC Help
Powered by ViewVC 1.1.26