Remmina - The GTK+ Remote Desktop Client  v1.4.2
Remmina is a remote desktop client written in GTK+, aiming to be useful for system administrators and travellers, who need to work with lots of remote computers in front of either large monitors or tiny netbooks. Remmina supports multiple network protocols in an integrated and consistent user interface. Currently RDP, VNC, NX, XDMCP and SSH are supported.
remmina_crypt.c
Go to the documentation of this file.
1 /*
2  * Remmina - The GTK+ Remote Desktop Client
3  * Copyright (C) 2009 - Vic Lee
4  * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo
5  * Copyright (C) 2016-2020 Antenore Gatta, Giovanni Panozzo
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  *
22  * In addition, as a special exception, the copyright holders give
23  * permission to link the code of portions of this program with the
24  * OpenSSL library under certain conditions as described in each
25  * individual source file, and distribute linked combinations
26  * including the two.
27  * You must obey the GNU General Public License in all respects
28  * for all of the code used other than OpenSSL. * If you modify
29  * file(s) with this exception, you may extend this exception to your
30  * version of the file(s), but you are not obligated to do so. * If you
31  * do not wish to do so, delete this exception statement from your
32  * version. * If you delete this exception statement from all source
33  * files in the program, then also delete it here.
34  *
35  */
36 
37 #include "config.h"
38 #include <glib.h>
39 #ifdef HAVE_LIBGCRYPT
40 #include <gcrypt.h>
41 #endif
42 #include "remmina_pref.h"
43 #include "remmina_crypt.h"
45 
46 #ifdef HAVE_LIBGCRYPT
47 
48 static gboolean remmina_crypt_init(gcry_cipher_hd_t *phd)
49 {
50  TRACE_CALL(__func__);
51  guchar* secret;
52  gcry_error_t err;
53  gsize secret_len;
54 
55  secret = g_base64_decode(remmina_pref.secret, &secret_len);
56 
57  if (secret_len < 32) {
58  g_debug("secret corrupted\n");
59  g_free(secret);
60  return FALSE;
61  }
62 
63  err = gcry_cipher_open(phd, GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC, 0);
64 
65  if (err) {
66  g_debug("gcry_cipher_open failure: %s\n", gcry_strerror(err));
67  g_free(secret);
68  return FALSE;
69  }
70 
71  err = gcry_cipher_setkey((*phd), secret, 24);
72 
73  if (err) {
74  g_debug("gcry_cipher_setkey failure: %s\n", gcry_strerror(err));
75  g_free(secret);
76  gcry_cipher_close((*phd));
77  return FALSE;
78  }
79 
80  err = gcry_cipher_setiv((*phd), secret + 24, 8);
81 
82  if (err) {
83  g_debug("gcry_cipher_setiv failure: %s\n", gcry_strerror(err));
84  g_free(secret);
85  gcry_cipher_close((*phd));
86  return FALSE;
87  }
88 
89  g_free(secret);
90 
91  return TRUE;
92 }
93 
94 gchar* remmina_crypt_encrypt(const gchar *str)
95 {
96  TRACE_CALL(__func__);
97  guchar* buf;
98  gint buf_len;
99  gchar* result;
100  gcry_error_t err;
101  gcry_cipher_hd_t hd;
102 
103  if (!str || str[0] == '\0')
104  return NULL;
105 
106  if (!remmina_crypt_init(&hd))
107  return NULL;
108 
109  buf_len = strlen(str);
110  /* Pack to 64bit block size, and make sure it’s always 0-terminated */
111  buf_len += 8 - buf_len % 8;
112  buf = (guchar*)g_malloc(buf_len);
113  memset(buf, 0, buf_len);
114  memcpy(buf, str, strlen(str));
115 
116  err = gcry_cipher_encrypt(hd, buf, buf_len, NULL, 0);
117 
118  if (err) {
119  g_debug("gcry_cipher_encrypt failure: %s/%s\n",
120  gcry_strsource(err),
121  gcry_strerror(err));
122  g_free(buf);
123  gcry_cipher_close(hd);
124  return NULL;
125  }
126 
127  result = g_base64_encode(buf, buf_len);
128 
129  g_free(buf);
130  gcry_cipher_close(hd);
131 
132  return result;
133 }
134 
135 gchar* remmina_crypt_decrypt(const gchar *str)
136 {
137  TRACE_CALL(__func__);
138  guchar* buf;
139  gsize buf_len;
140  gcry_error_t err;
141  gcry_cipher_hd_t hd;
142 
143  if (!str || str[0] == '\0')
144  return NULL;
145 
146  if (!remmina_crypt_init(&hd))
147  return NULL;
148 
149  buf = g_base64_decode(str, &buf_len);
150 
151  /*
152  g_debug ("%s base64 encoded as %p with length %lu",
153  str,
154  &buf,
155  buf_len);
156  */
157 
158  err = gcry_cipher_decrypt(
159  hd, // gcry_cipher_hd_t
160  buf, // guchar
161  buf_len, // gsize
162  NULL, // NULL and 0 -> in place decrypt
163  0);
164 
165  if (err) {
166  g_debug("gcry_cipher_decrypt failure: %s/%s\n",
167  gcry_strsource(err),
168  gcry_strerror(err));
169  g_free(buf);
170  gcry_cipher_close(hd);
171  return NULL;
172  }
173 
174  gcry_cipher_close(hd);
175 
176  /* Just in case */
177  buf[buf_len - 1] = '\0';
178 
179  return (gchar*)buf;
180 }
181 
182 #else
183 
184 gchar* remmina_crypt_encrypt(const gchar *str)
185 {
186  TRACE_CALL(__func__);
187  return NULL;
188 }
189 
190 gchar* remmina_crypt_decrypt(const gchar *str)
191 {
192  TRACE_CALL(__func__);
193  return NULL;
194 }
195 
196 #endif
197 
gchar * remmina_crypt_decrypt(const gchar *str)
gchar * secret
Definition: remmina_pref.h:192
gchar * remmina_crypt_encrypt(const gchar *str)
Definition: remmina_crypt.c:94
static gboolean remmina_crypt_init(gcry_cipher_hd_t *phd)
Definition: remmina_crypt.c:48
RemminaPref remmina_pref
Definition: rcw.c:73