/[rdesktop]/sourceforge.net/tags/RDESKTOP-1-3-0/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/tags/RDESKTOP-1-3-0/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 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-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    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  static void  static void
204  licence_generate_keys(uint8 *client_key, uint8 *server_key, 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 49  licence_generate_keys(uint8 *client_key, Line 218  licence_generate_keys(uint8 *client_key,
218  }  }
219    
220  static void  static void
221  licence_generate_hwid(uint8 *hwid)  licence_generate_hwid(uint8 * hwid)
222  {  {
223          buf_out_uint32(hwid, 2);          buf_out_uint32(hwid, 2);
224          strncpy(hwid + 4, hostname, LICENCE_HWID_SIZE - 4);          strncpy((char *) (hwid + 4), hostname, LICENCE_HWID_SIZE - 4);
225  }  }
226    
227  /* Present an existing licence to the server */  /* Present an existing licence to the server */
228  static void  static void
229  licence_present(uint8 *client_random, uint8 *rsa_data,  licence_present(uint8 * client_random, uint8 * rsa_data,
230                  uint8 *licence_data, int licence_size,                  uint8 * licence_data, int licence_size, uint8 * hwid, uint8 * signature)
                 uint8 *hwid, uint8 *signature)  
231  {  {
232          uint32 sec_flags = SEC_LICENCE_NEG;          uint32 sec_flags = SEC_LICENCE_NEG;
233          uint16 length = 16 + SEC_RANDOM_SIZE + SEC_MODULUS_SIZE + SEC_PADDING_SIZE          uint16 length =
234                          + licence_size + LICENCE_HWID_SIZE + LICENCE_SIGNATURE_SIZE;                  16 + SEC_RANDOM_SIZE + SEC_MODULUS_SIZE + SEC_PADDING_SIZE +
235                    licence_size + LICENCE_HWID_SIZE + LICENCE_SIGNATURE_SIZE;
236          STREAM s;          STREAM s;
237    
238          s = sec_init(sec_flags, length + 4);          s = sec_init(sec_flags, length + 4);
# Line 97  licence_present(uint8 *client_random, ui Line 266  licence_present(uint8 *client_random, ui
266    
267  /* Send a licence request packet */  /* Send a licence request packet */
268  static void  static void
269  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)  
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 138  static void Line 306  static void
306  licence_process_demand(STREAM s)  licence_process_demand(STREAM s)
307  {  {
308          uint8 null_data[SEC_MODULUS_SIZE];          uint8 null_data[SEC_MODULUS_SIZE];
         uint8 hwid[LICENCE_HWID_SIZE];  
         uint8 signature[LICENCE_SIGNATURE_SIZE];  
309          uint8 *server_random;          uint8 *server_random;
310            uint8 signature[LICENCE_SIGNATURE_SIZE];
311            uint8 hwid[LICENCE_HWID_SIZE];
312          uint8 *licence_data;          uint8 *licence_data;
313          int licence_size;          int licence_size;
314          RC4_KEY crypt_key;          RC4_KEY crypt_key;
# Line 154  licence_process_demand(STREAM s) Line 322  licence_process_demand(STREAM s)
322          licence_generate_keys(null_data, server_random, null_data);          licence_generate_keys(null_data, server_random, null_data);
323    
324          licence_size = load_licence(&licence_data);          licence_size = load_licence(&licence_data);
325          if (licence_size == -1)          if (licence_size != -1)
326          {          {
327                  licence_send_request(null_data, null_data, username, hostname);                  /* 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;                  return;
338          }          }
339    
340          /* 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);  
341  }  }
342    
343  /* Send an authentication response packet */  /* Send an authentication response packet */
344  static void  static void
345  licence_send_authresp(uint8 *token, uint8 *crypt_hwid, 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 202  licence_send_authresp(uint8 *token, uint Line 369  licence_send_authresp(uint8 *token, uint
369    
370  /* Parse an authentication request packet */  /* Parse an authentication request packet */
371  static BOOL  static BOOL
372  licence_parse_authreq(STREAM s, uint8 **token, uint8 **signature)  licence_parse_authreq(STREAM s, uint8 ** token, uint8 ** signature)
373  {  {
374          uint16 tokenlen;          uint16 tokenlen;
375    
# Line 226  static void Line 393  static void
393  licence_process_authreq(STREAM s)  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 245  licence_process_authreq(STREAM s) Line 411  licence_process_authreq(STREAM s)
411          licence_generate_hwid(hwid);          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 280  licence_process_issue(STREAM s) Line 441  licence_process_issue(STREAM s)
441                  return;                  return;
442    
443          licence_issued = True;          licence_issued = True;
444          save_licence(s->p, length-2);          save_licence(s->p, length - 2);
445  }  }
446    
447  /* Process a licence packet */  /* Process a licence packet */
# Line 316  licence_process(STREAM s) Line 477  licence_process(STREAM s)
477                          unimpl("licence tag 0x%x\n", tag);                          unimpl("licence tag 0x%x\n", tag);
478          }          }
479  }  }
480    

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

  ViewVC Help
Powered by ViewVC 1.1.26