Remmina - The GTK+ Remote Desktop Client  v1.4.33
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-2023 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 #ifdef HAVE_LIBGCRYPT
39 #include <gcrypt.h>
40 #endif
41 #include "remmina_pref.h"
42 #include "remmina_crypt.h"
44 
45 #ifdef HAVE_LIBGCRYPT
46 
47 static gboolean remmina_crypt_init(gcry_cipher_hd_t *phd)
48 {
49  TRACE_CALL(__func__);
50  guchar* secret;
51  gcry_error_t err;
52  gsize secret_len;
53 
54  secret = g_base64_decode(remmina_pref.secret, &secret_len);
55 
56  if (secret_len < 32) {
57  g_debug("secret corrupted\n");
58  g_free(secret);
59  return FALSE;
60  }
61 
62  err = gcry_cipher_open(phd, GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC, 0);
63 
64  if (err) {
65  g_debug("gcry_cipher_open failure: %s\n", gcry_strerror(err));
66  g_free(secret);
67  return FALSE;
68  }
69 
70  err = gcry_cipher_setkey((*phd), secret, 24);
71 
72  if (err) {
73  g_debug("gcry_cipher_setkey failure: %s\n", gcry_strerror(err));
74  g_free(secret);
75  gcry_cipher_close((*phd));
76  return FALSE;
77  }
78 
79  err = gcry_cipher_setiv((*phd), secret + 24, 8);
80 
81  if (err) {
82  g_debug("gcry_cipher_setiv failure: %s\n", gcry_strerror(err));
83  g_free(secret);
84  gcry_cipher_close((*phd));
85  return FALSE;
86  }
87 
88  g_free(secret);
89 
90  return TRUE;
91 }
92 
93 gchar* remmina_crypt_encrypt(const gchar *str)
94 {
95  TRACE_CALL(__func__);
96  guchar* buf;
97  gint buf_len;
98  gchar* result;
99  gcry_error_t err;
100  gcry_cipher_hd_t hd;
101 
102  if (!str || str[0] == '\0')
103  return NULL;
104 
105  if (!remmina_crypt_init(&hd))
106  return NULL;
107 
108  buf_len = strlen(str);
109  /* Pack to 64bit block size, and make sure it’s always 0-terminated */
110  buf_len += 8 - buf_len % 8;
111  buf = (guchar*)g_malloc(buf_len);
112  memset(buf, 0, buf_len);
113  memcpy(buf, str, strlen(str));
114 
115  err = gcry_cipher_encrypt(hd, buf, buf_len, NULL, 0);
116 
117  if (err) {
118  g_debug("gcry_cipher_encrypt failure: %s/%s\n",
119  gcry_strsource(err),
120  gcry_strerror(err));
121  g_free(buf);
122  gcry_cipher_close(hd);
123  return NULL;
124  }
125 
126  result = g_base64_encode(buf, buf_len);
127 
128  g_free(buf);
129  gcry_cipher_close(hd);
130 
131  return result;
132 }
133 
134 gchar* remmina_crypt_decrypt(const gchar *str)
135 {
136  TRACE_CALL(__func__);
137  guchar* buf;
138  gsize buf_len;
139  gcry_error_t err;
140  gcry_cipher_hd_t hd;
141 
142  if (!str || str[0] == '\0')
143  return NULL;
144 
145  if (!remmina_crypt_init(&hd))
146  return NULL;
147 
148  buf = g_base64_decode(str, &buf_len);
149 
150 #if 0
151  g_debug ("%s base64 encoded as %p with length %lu",
152  str,
153  &buf,
154  buf_len);
155 #endif
156 
157  err = gcry_cipher_decrypt(
158  hd, // gcry_cipher_hd_t
159  buf, // guchar
160  buf_len, // gsize
161  NULL, // NULL and 0 -> in place decrypt
162  0);
163 
164  if (err) {
165  g_debug("gcry_cipher_decrypt failure: %s/%s\n",
166  gcry_strsource(err),
167  gcry_strerror(err));
168  g_free(buf);
169  gcry_cipher_close(hd);
170  //return NULL;
171  return g_strdup(str);
172  }
173 
174  gcry_cipher_close(hd);
175 
176  /* Just in case */
177  if (buf_len > 0)
178  buf[buf_len - 1] = '\0';
179 
180  return (gchar*)buf;
181 }
182 
183 #else
184 
185 gchar* remmina_crypt_encrypt(const gchar *str)
186 {
187  TRACE_CALL(__func__);
188  return NULL;
189 }
190 
191 gchar* remmina_crypt_decrypt(const gchar *str)
192 {
193  TRACE_CALL(__func__);
194  return NULL;
195 }
196 
197 #endif
198 
gchar * remmina_crypt_decrypt(const gchar *str)
gchar * secret
Definition: remmina_pref.h:231
gchar * remmina_crypt_encrypt(const gchar *str)
Definition: remmina_crypt.c:93
static gboolean remmina_crypt_init(gcry_cipher_hd_t *phd)
Definition: remmina_crypt.c:47
RemminaPref remmina_pref
Definition: rcw.c:79