1 /*
2 * e-source-security.c
3 *
4 * This library is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation.
7 *
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
11 * for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library. If not, see <http://www.gnu.org/licenses/>.
15 *
16 */
17
18 /**
19 * SECTION: e-source-security
20 * @include: libedataserver/libedataserver.h
21 * @short_description: #ESource extension for security settings
22 *
23 * The #ESourceSecurity extension tracks settings for establishing a
24 * secure connection with a remote server.
25 *
26 * Access the extension as follows:
27 *
28 * |[
29 * #include <libedataserver/libedataserver.h>
30 *
31 * ESourceSecurity *extension;
32 *
33 * extension = e_source_get_extension (source, E_SOURCE_EXTENSION_SECURITY);
34 * ]|
35 **/
36
37 #include "e-source-security.h"
38
39 #include <libedataserver/e-data-server-util.h>
40
41 #define SECURE_METHOD "tls"
42
43 struct _ESourceSecurityPrivate {
44 gchar *method;
45 };
46
47 enum {
48 PROP_0,
49 PROP_METHOD,
50 PROP_SECURE
51 };
52
G_DEFINE_TYPE_WITH_PRIVATE(ESourceSecurity,e_source_security,E_TYPE_SOURCE_EXTENSION)53 G_DEFINE_TYPE_WITH_PRIVATE (
54 ESourceSecurity,
55 e_source_security,
56 E_TYPE_SOURCE_EXTENSION)
57
58 static void
59 source_security_set_property (GObject *object,
60 guint property_id,
61 const GValue *value,
62 GParamSpec *pspec)
63 {
64 switch (property_id) {
65 case PROP_METHOD:
66 e_source_security_set_method (
67 E_SOURCE_SECURITY (object),
68 g_value_get_string (value));
69 return;
70
71 case PROP_SECURE:
72 e_source_security_set_secure (
73 E_SOURCE_SECURITY (object),
74 g_value_get_boolean (value));
75 return;
76 }
77
78 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
79 }
80
81 static void
source_security_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)82 source_security_get_property (GObject *object,
83 guint property_id,
84 GValue *value,
85 GParamSpec *pspec)
86 {
87 switch (property_id) {
88 case PROP_METHOD:
89 g_value_take_string (
90 value,
91 e_source_security_dup_method (
92 E_SOURCE_SECURITY (object)));
93 return;
94
95 case PROP_SECURE:
96 g_value_set_boolean (
97 value,
98 e_source_security_get_secure (
99 E_SOURCE_SECURITY (object)));
100 return;
101 }
102
103 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
104 }
105
106 static void
source_security_finalize(GObject * object)107 source_security_finalize (GObject *object)
108 {
109 ESourceSecurityPrivate *priv;
110
111 priv = E_SOURCE_SECURITY (object)->priv;
112
113 g_free (priv->method);
114
115 /* Chain up to parent's finalize() method. */
116 G_OBJECT_CLASS (e_source_security_parent_class)->finalize (object);
117 }
118
119 static void
e_source_security_class_init(ESourceSecurityClass * class)120 e_source_security_class_init (ESourceSecurityClass *class)
121 {
122 GObjectClass *object_class;
123 ESourceExtensionClass *extension_class;
124
125 object_class = G_OBJECT_CLASS (class);
126 object_class->set_property = source_security_set_property;
127 object_class->get_property = source_security_get_property;
128 object_class->finalize = source_security_finalize;
129
130 extension_class = E_SOURCE_EXTENSION_CLASS (class);
131 extension_class->name = E_SOURCE_EXTENSION_SECURITY;
132
133 g_object_class_install_property (
134 object_class,
135 PROP_METHOD,
136 g_param_spec_string (
137 "method",
138 "Method",
139 "Security method",
140 "none",
141 G_PARAM_READWRITE |
142 G_PARAM_CONSTRUCT |
143 G_PARAM_EXPLICIT_NOTIFY |
144 G_PARAM_STATIC_STRINGS |
145 E_SOURCE_PARAM_SETTING));
146
147 g_object_class_install_property (
148 object_class,
149 PROP_SECURE,
150 g_param_spec_boolean (
151 "secure",
152 "Secure",
153 "Secure the network connection",
154 FALSE,
155 G_PARAM_READWRITE |
156 G_PARAM_EXPLICIT_NOTIFY |
157 G_PARAM_STATIC_STRINGS));
158 }
159
160 static void
e_source_security_init(ESourceSecurity * extension)161 e_source_security_init (ESourceSecurity *extension)
162 {
163 extension->priv = e_source_security_get_instance_private (extension);
164 }
165
166 /**
167 * e_source_security_get_method:
168 * @extension: an #ESourceSecurity
169 *
170 * Returns the method used to establish a secure network connection to a
171 * remote account. There are no pre-defined method names; backends are
172 * free to set this however they wish. If a secure connection is not
173 * desired, the convention is to set #ESourceSecurity:method to "none".
174 *
175 * Returns: the method used to establish a secure network connection
176 *
177 * Since: 3.6
178 **/
179 const gchar *
e_source_security_get_method(ESourceSecurity * extension)180 e_source_security_get_method (ESourceSecurity *extension)
181 {
182 g_return_val_if_fail (E_IS_SOURCE_SECURITY (extension), NULL);
183
184 return extension->priv->method;
185 }
186
187 /**
188 * e_source_security_dup_method:
189 * @extension: an #ESourceSecurity
190 *
191 * Thread-safe variation of e_source_security_get_method().
192 * Use this function when accessing @extension from multiple threads.
193 *
194 * The returned string should be freed with g_free() when no longer needed.
195 *
196 * Returns: a newly-allocated copy of #ESourceSecurity:method
197 *
198 * Since: 3.6
199 **/
200 gchar *
e_source_security_dup_method(ESourceSecurity * extension)201 e_source_security_dup_method (ESourceSecurity *extension)
202 {
203 const gchar *protected;
204 gchar *duplicate;
205
206 g_return_val_if_fail (E_IS_SOURCE_SECURITY (extension), NULL);
207
208 e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
209
210 protected = e_source_security_get_method (extension);
211 duplicate = g_strdup (protected);
212
213 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
214
215 return duplicate;
216 }
217
218 /**
219 * e_source_security_set_method:
220 * @extension: an #ESourceSecurity
221 * @method: (nullable): security method, or %NULL
222 *
223 * Sets the method used to establish a secure network connection to a
224 * remote account. There are no pre-defined method names; backends are
225 * free to set this however they wish. If a secure connection is not
226 * desired, the convention is to set #ESourceSecurity:method to "none".
227 * In keeping with that convention, #ESourceSecurity:method will be set
228 * to "none" if @method is %NULL or an empty string.
229 *
230 * Since: 3.6
231 **/
232 void
e_source_security_set_method(ESourceSecurity * extension,const gchar * method)233 e_source_security_set_method (ESourceSecurity *extension,
234 const gchar *method)
235 {
236 GObject *object;
237
238 g_return_if_fail (E_IS_SOURCE_SECURITY (extension));
239
240 e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
241
242 if (e_util_strcmp0 (extension->priv->method, method) == 0) {
243 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
244 return;
245 }
246
247 g_free (extension->priv->method);
248 extension->priv->method = e_util_strdup_strip (method);
249
250 if (extension->priv->method == NULL)
251 extension->priv->method = g_strdup ("none");
252
253 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
254
255 object = G_OBJECT (extension);
256 g_object_freeze_notify (object);
257 g_object_notify (object, "method");
258 g_object_notify (object, "secure");
259 g_object_thaw_notify (object);
260 }
261
262 /**
263 * e_source_security_get_secure:
264 * @extension: an #ESourceSecurity
265 *
266 * This is a convenience function which returns whether a secure network
267 * connection is desired, regardless of the method used. This relies on
268 * the convention of setting #ESourceSecurity:method to "none" when a
269 * secure network connection is <emphasis>not</emphasis> desired.
270 *
271 * Returns: whether a secure network connection is desired
272 *
273 * Since: 3.6
274 **/
275 gboolean
e_source_security_get_secure(ESourceSecurity * extension)276 e_source_security_get_secure (ESourceSecurity *extension)
277 {
278 const gchar *method;
279
280 g_return_val_if_fail (E_IS_SOURCE_SECURITY (extension), FALSE);
281
282 method = e_source_security_get_method (extension);
283 g_return_val_if_fail (method != NULL, FALSE);
284
285 return (g_strcmp0 (method, "none") != 0);
286 }
287
288 /**
289 * e_source_security_set_secure:
290 * @extension: an #ESourceSecurity
291 * @secure: whether a secure network connection is desired
292 *
293 * This function provides a simpler way to set #ESourceSecurity:method
294 * when using a secure network connection is a yes or no option and the
295 * exact method name is unimportant. If @secure is %FALSE, the
296 * #ESourceSecurity:method property is set to "none". If @secure is
297 * %TRUE, the function assumes the backend will use Transport Layer
298 * Security and sets the #ESourceSecurity:method property to "tls".
299 *
300 * Since: 3.6
301 **/
302 void
e_source_security_set_secure(ESourceSecurity * extension,gboolean secure)303 e_source_security_set_secure (ESourceSecurity *extension,
304 gboolean secure)
305 {
306 const gchar *method;
307
308 g_return_if_fail (E_IS_SOURCE_SECURITY (extension));
309
310 method = secure ? SECURE_METHOD : "none";
311 e_source_security_set_method (extension, method);
312 }
313