/[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 39 by matthewc, Fri Apr 5 07:57:43 2002 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-2001     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;  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  static void  static void
202  licence_generate_keys(uint8 *client_key, uint8 *server_key, 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];
# Line 49  licence_generate_keys(uint8 *client_key, Line 216  licence_generate_keys(uint8 *client_key,
216  }  }
217    
218  static void  static void
219  licence_generate_hwid(uint8 *hwid)  licence_generate_hwid(uint8 * hwid)
220  {  {
221          buf_out_uint32(hwid, 2);          buf_out_uint32(hwid, 2);
222          strncpy(hwid + 4, hostname, LICENCE_HWID_SIZE - 4);          strncpy((char *) (hwid + 4), hostname, LICENCE_HWID_SIZE - 4);
223  }  }
224    
225  /* Present an existing licence to the server */  /* Present an existing licence to the server */
226  static void  static void
227  licence_present(uint8 *client_random, uint8 *rsa_data,  licence_present(uint8 * client_random, uint8 * rsa_data,
228                  uint8 *licence_data, int licence_size,                  uint8 * licence_data, int licence_size, uint8 * hwid, uint8 * signature)
                 uint8 *hwid, uint8 *signature)  
229  {  {
230          uint32 sec_flags = SEC_LICENCE_NEG;          uint32 sec_flags = SEC_LICENCE_NEG;
231          uint16 length = 16 + SEC_RANDOM_SIZE + SEC_MODULUS_SIZE + SEC_PADDING_SIZE          uint16 length =
232                          + licence_size + LICENCE_HWID_SIZE + LICENCE_SIGNATURE_SIZE;                  16 + SEC_RANDOM_SIZE + SEC_MODULUS_SIZE + SEC_PADDING_SIZE +
233                    licence_size + LICENCE_HWID_SIZE + LICENCE_SIGNATURE_SIZE;
234          STREAM s;          STREAM s;
235    
236          s = sec_init(sec_flags, length + 4);          s = sec_init(sec_flags, length + 4);
# Line 97  licence_present(uint8 *client_random, ui Line 264  licence_present(uint8 *client_random, ui
264    
265  /* Send a licence request packet */  /* Send a licence request packet */
266  static void  static void
267  licence_send_request(uint8 *client_random, uint8 *rsa_data,  licence_send_request(uint8 * client_random, uint8 * rsa_data, char *user, char *host)
                      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 138  static void Line 304  static void
304  licence_process_demand(STREAM s)  licence_process_demand(STREAM s)
305  {  {
306          uint8 null_data[SEC_MODULUS_SIZE];          uint8 null_data[SEC_MODULUS_SIZE];
         uint8 hwid[LICENCE_HWID_SIZE];  
         uint8 signature[LICENCE_SIGNATURE_SIZE];  
307          uint8 *server_random;          uint8 *server_random;
308            uint8 signature[LICENCE_SIGNATURE_SIZE];
309            uint8 hwid[LICENCE_HWID_SIZE];
310          uint8 *licence_data;          uint8 *licence_data;
311          int licence_size;          int licence_size;
312          RC4_KEY crypt_key;          RC4_KEY crypt_key;
# Line 154  licence_process_demand(STREAM s) Line 320  licence_process_demand(STREAM s)
320          licence_generate_keys(null_data, server_random, null_data);          licence_generate_keys(null_data, server_random, null_data);
321    
322          licence_size = load_licence(&licence_data);          licence_size = load_licence(&licence_data);
323          if (licence_size == -1)          if (licence_size != -1)
324          {          {
325                  licence_send_request(null_data, null_data, username, hostname);                  /* 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;                  return;
336          }          }
337    
338          /* Generate a signature for the HWID buffer */          licence_send_request(null_data, null_data, username, hostname);
         licence_generate_hwid(hwid);  
         sec_sign(signature, licence_sign_key, 16, hwid, sizeof(hwid));  
   
         /* Now encrypt the HWID */  
         RC4_set_key(&crypt_key, 16, licence_key);  
         RC4(&crypt_key, sizeof(hwid), hwid, hwid);  
   
         licence_present(null_data, null_data, licence_data, licence_size,  
                                         hwid, signature);  
         xfree(licence_data);  
339  }  }
340    
341  /* Send an authentication response packet */  /* Send an authentication response packet */
342  static void  static void
343  licence_send_authresp(uint8 *token, uint8 *crypt_hwid, 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 202  licence_send_authresp(uint8 *token, uint Line 367  licence_send_authresp(uint8 *token, uint
367    
368  /* Parse an authentication request packet */  /* Parse an authentication request packet */
369  static BOOL  static BOOL
370  licence_parse_authreq(STREAM s, uint8 **token, uint8 **signature)  licence_parse_authreq(STREAM s, uint8 ** token, uint8 ** signature)
371  {  {
372          uint16 tokenlen;          uint16 tokenlen;
373    
# Line 226  static void Line 391  static void
391  licence_process_authreq(STREAM s)  licence_process_authreq(STREAM s)
392  {  {
393          uint8 *in_token, *in_sig;          uint8 *in_token, *in_sig;
394          uint8 out_token[LICENCE_TOKEN_SIZE],          uint8 out_token[LICENCE_TOKEN_SIZE], decrypt_token[LICENCE_TOKEN_SIZE];
                 decrypt_token[LICENCE_TOKEN_SIZE];  
395          uint8 hwid[LICENCE_HWID_SIZE], crypt_hwid[LICENCE_HWID_SIZE];          uint8 hwid[LICENCE_HWID_SIZE], crypt_hwid[LICENCE_HWID_SIZE];
396          uint8 sealed_buffer[LICENCE_TOKEN_SIZE + LICENCE_HWID_SIZE];          uint8 sealed_buffer[LICENCE_TOKEN_SIZE + LICENCE_HWID_SIZE];
397          uint8 out_sig[LICENCE_SIGNATURE_SIZE];          uint8 out_sig[LICENCE_SIGNATURE_SIZE];
# Line 245  licence_process_authreq(STREAM s) Line 409  licence_process_authreq(STREAM s)
409          licence_generate_hwid(hwid);          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 280  licence_process_issue(STREAM s) Line 439  licence_process_issue(STREAM s)
439                  return;                  return;
440    
441          licence_issued = True;          licence_issued = True;
442          save_licence(s->p, length-2);          save_licence(s->p, length - 2);
443  }  }
444    
445  /* Process a licence packet */  /* Process a licence packet */

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

  ViewVC Help
Powered by ViewVC 1.1.26