1    	/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2    	/*
3    	 *
4    	 * This program is free software; you can redistribute it and/or modify
5    	 * it under the terms of the GNU General Public License as published by
6    	 * the Free Software Foundation; either version 2, or (at your option)
7    	 * any later version.
8    	 *
9    	 * This program is distributed in the hope that it will be useful,
10   	 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   	 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   	 * GNU General Public License for more details.
13   	 *
14   	 * You should have received a copy of the GNU General Public License along
15   	 * with this program; if not, write to the Free Software Foundation, Inc.,
16   	 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17   	 *
18   	 * Copyright (C) 2008 - 2011 Red Hat, Inc.
19   	 *
20   	 */
21   	
22   	#include <glib.h>
23   	#include <string.h>
24   	
25   	#include "nm-test-helpers.h"
26   	#include <nm-utils.h>
27   	
28   	#include "nm-setting-connection.h"
29   	#include "nm-setting-8021x.h"
30   	
31   	static void
32   	compare_blob_data (const char *test,
33   	                   const char *key_path,
34   	                   const GByteArray *key)
35   	{
36   		char *contents = NULL;
37   		gsize len = 0;
38   		GError *error = NULL;
39   		gboolean success;
40   	
41   		success = g_file_get_contents (key_path, &contents, &len, &error);
42   		ASSERT (success == TRUE,
43   		        test, "failed to read blob key file: %s", error->message);
44   	
45   		ASSERT (len > 0, test, "blob key file invalid (size 0)");
46   	
47   		ASSERT (len == key->len,
48   		        test, "blob key file (%d) and setting key data (%d) lengths don't match",
49   		        len, key->len);
50   	
51   		ASSERT (memcmp (contents, key->data, len) == 0,
52   		        test, "blob key file and blob key data don't match");
53   	
54   		g_free (contents);
55   	}
56   	
57   	#define SCHEME_PATH "file://"
58   	
59   	static void
60   	check_scheme_path (GByteArray *value, const char *path)
61   	{
62   		guint8 *p = value->data;
63   	
64   		g_assert (memcmp (p, SCHEME_PATH, strlen (SCHEME_PATH)) == 0);
65   		p += strlen (SCHEME_PATH);
66   		g_assert (memcmp (p, path, strlen (path)) == 0);
67   		p += strlen (path);
68   		g_assert (*p == '\0');
69   	}
70   	
71   	static void
72   	test_private_key_import (const char *path,
73   	                         const char *password,
74   	                         NMSetting8021xCKScheme scheme)
75   	{
76   		NMSetting8021x *s_8021x;
77   		gboolean success;
78   		NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
79   		NMSetting8021xCKFormat tmp_fmt;
80   		GError *error = NULL;
81   		GByteArray *tmp_key = NULL, *client_cert = NULL;
82   		const char *pw;
83   	
84   		s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
85   		ASSERT (s_8021x != NULL, "private-key-import", "setting was NULL");
86   	
87   		success = nm_setting_802_1x_set_private_key (s_8021x,
88   		                                             path,
89   		                                             password,
90   		                                             scheme,
91   		                                             &format,
92   		                                             &error);
93   		ASSERT (success == TRUE,
94   		        "private-key-import", "error reading private key: %s", error->message);
95   		ASSERT (format != NM_SETTING_802_1X_CK_FORMAT_UNKNOWN,
96   		        "private-key-import", "unexpected private key format (got %d)", format);
97   		tmp_fmt = nm_setting_802_1x_get_private_key_format (s_8021x);
98   		ASSERT (tmp_fmt == format,
99   		        "private-key-import", "unexpected re-read private key format (expected %d, got %d)",
100  		        format, tmp_fmt);
101  	
102  		/* Make sure the password is what we expect */
103  		pw = nm_setting_802_1x_get_private_key_password (s_8021x);
104  		ASSERT (pw != NULL,
105  		        "private-key-import", "failed to get previous private key password");
106  		ASSERT (strcmp (pw, password) == 0,
107  		        "private-key-import", "failed to compare private key password");
108  	
109  		if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
110  			tmp_key = (GByteArray *) nm_setting_802_1x_get_private_key_blob (s_8021x);
111  			ASSERT (tmp_key != NULL, "private-key-import", "missing private key blob");
112  			compare_blob_data ("private-key-import", path, tmp_key);
113  		} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) {
114  			g_object_get (s_8021x, NM_SETTING_802_1X_PRIVATE_KEY, &tmp_key, NULL);
115  			ASSERT (tmp_key != NULL, "private-key-import", "missing private key value");
116  			check_scheme_path (tmp_key, path);
117  			g_byte_array_free (tmp_key, TRUE);
118  		} else
119  			g_assert_not_reached ();
120  	
121  		/* If it's PKCS#12 ensure the client cert is the same value */
122  		if (format == NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
123  			g_object_get (s_8021x, NM_SETTING_802_1X_PRIVATE_KEY, &tmp_key, NULL);
124  			ASSERT (tmp_key != NULL, "private-key-import", "missing private key value");
125  	
126  			g_object_get (s_8021x, NM_SETTING_802_1X_CLIENT_CERT, &client_cert, NULL);
127  			ASSERT (client_cert != NULL, "private-key-import", "missing client certificate value");
128  	
129  			/* make sure they are the same */
130  			ASSERT (tmp_key->len == client_cert->len,
131  			        "private-key-import", "unexpected different private key and client cert lengths");
132  			ASSERT (memcmp (tmp_key->data, client_cert->data, tmp_key->len) == 0,
133  			        "private-key-import", "unexpected different private key and client cert data");
134  	
135  			g_byte_array_free (tmp_key, TRUE);
136  			g_byte_array_free (client_cert, TRUE);
137  		}
138  	
139  		g_object_unref (s_8021x);
140  	}
141  	
142  	static void
143  	test_phase2_private_key_import (const char *path,
144  	                                const char *password,
145  	                                NMSetting8021xCKScheme scheme)
146  	{
147  		NMSetting8021x *s_8021x;
148  		gboolean success;
149  		NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
150  		NMSetting8021xCKFormat tmp_fmt;
151  		GError *error = NULL;
152  		GByteArray *tmp_key = NULL, *client_cert = NULL;
153  		const char *pw;
154  	
155  		s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
156  		ASSERT (s_8021x != NULL, "phase2-private-key-import", "setting was NULL");
157  	
158  		success = nm_setting_802_1x_set_phase2_private_key (s_8021x,
159  		                                                    path,
160  		                                                    password,
161  		                                                    scheme,
162  		                                                    &format,
163  		                                                    &error);
164  		ASSERT (success == TRUE,
165  		        "phase2-private-key-import", "error reading private key: %s", error->message);
166  		ASSERT (format != NM_SETTING_802_1X_CK_FORMAT_UNKNOWN,
167  		        "phase2-private-key-import", "unexpected private key format");
168  		tmp_fmt = nm_setting_802_1x_get_phase2_private_key_format (s_8021x);
169  		ASSERT (tmp_fmt == format,
170  		        "phase2-private-key-import", "unexpected re-read private key format (expected %d, got %d)",
171  		        format, tmp_fmt);
172  	
173  		/* Make sure the password is what we expect */
174  		pw = nm_setting_802_1x_get_phase2_private_key_password (s_8021x);
175  		ASSERT (pw != NULL,
176  		        "phase2-private-key-import", "failed to get previous private key password");
177  		ASSERT (strcmp (pw, password) == 0,
178  		        "phase2-private-key-import", "failed to compare private key password");
179  	
180  		if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
181  			tmp_key = (GByteArray *) nm_setting_802_1x_get_phase2_private_key_blob (s_8021x);
182  			ASSERT (tmp_key != NULL, "phase2-private-key-import", "missing private key blob");
183  			compare_blob_data ("phase2-private-key-import", path, tmp_key);
184  		} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) {
185  			g_object_get (s_8021x, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, &tmp_key, NULL);
186  			ASSERT (tmp_key != NULL, "phase2-private-key-import", "missing private key value");
187  			check_scheme_path (tmp_key, path);
188  		} else
189  			g_assert_not_reached ();
190  	
191  		/* If it's PKCS#12 ensure the client cert is the same value */
192  		if (format == NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
193  			g_object_get (s_8021x, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, &tmp_key, NULL);
194  			ASSERT (tmp_key != NULL, "private-key-import", "missing private key value");
195  	
196  			g_object_get (s_8021x, NM_SETTING_802_1X_PHASE2_CLIENT_CERT, &client_cert, NULL);
197  			ASSERT (client_cert != NULL, "private-key-import", "missing client certificate value");
198  	
199  			/* make sure they are the same */
200  			ASSERT (tmp_key->len == client_cert->len,
201  			        "private-key-import", "unexpected different private key and client cert lengths");
202  			ASSERT (memcmp (tmp_key->data, client_cert->data, tmp_key->len) == 0,
203  			        "private-key-import", "unexpected different private key and client cert data");
204  	
205  			g_byte_array_free (tmp_key, TRUE);
206  			g_byte_array_free (client_cert, TRUE);
207  		}
208  	
209  		g_object_unref (s_8021x);
210  	}
211  	
212  	static void
213  	test_wrong_password_keeps_data (const char *path, const char *password)
214  	{
215  		NMSetting8021x *s_8021x;
216  		gboolean success;
217  		NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
218  		GError *error = NULL;
219  		const char *pw;
220  	
221  		s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
222  		ASSERT (s_8021x != NULL, "wrong-password-keeps-data", "setting was NULL");
223  	
224  		success = nm_setting_802_1x_set_private_key (s_8021x,
225  		                                             path,
226  		                                             password,
227  		                                             NM_SETTING_802_1X_CK_SCHEME_BLOB,
228  		                                             &format,
229  		                                             &error);
230  		ASSERT (success == TRUE,
231  		        "wrong-password-keeps-data", "error reading private key: %s", error->message);
232  		ASSERT (format != NM_SETTING_802_1X_CK_FORMAT_UNKNOWN,
233  		        "wrong-password-keeps-data", "unexpected private key format (got %d)", format);
234  	
235  		/* Now try to set it to something that's not a certificate */
236  		format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
237  		success = nm_setting_802_1x_set_private_key (s_8021x,
238  		                                             "Makefile.am",
239  		                                             password,
240  		                                             NM_SETTING_802_1X_CK_SCHEME_BLOB,
241  		                                             &format,
242  		                                             &error);
243  		ASSERT (success == FALSE,
244  		        "wrong-password-keeps-data", "unexpected success reading private key");
245  		ASSERT (error != NULL,
246  		        "wrong-password-keeps-data", "unexpected missing error");
247  		ASSERT (format == NM_SETTING_802_1X_CK_FORMAT_UNKNOWN,
248  		        "wrong-password-keeps-data", "unexpected success reading private key format");
249  	
250  		/* Make sure the password hasn't changed */
251  		pw = nm_setting_802_1x_get_private_key_password (s_8021x);
252  		ASSERT (pw != NULL,
253  		        "wrong-password-keeps-data", "failed to get previous private key password");
254  		ASSERT (strcmp (pw, password) == 0,
255  		        "wrong-password-keeps-data", "failed to compare private key password");
256  	
257  		g_object_unref (s_8021x);
258  	}
259  	
260  	static void
261  	test_clear_private_key (const char *path, const char *password)
262  	{
263  		NMSetting8021x *s_8021x;
264  		gboolean success;
265  		NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
266  		GError *error = NULL;
267  		const char *pw;
268  	
269  		s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
270  		ASSERT (s_8021x != NULL, "clear-private-key", "setting was NULL");
271  	
272  		success = nm_setting_802_1x_set_private_key (s_8021x,
273  		                                             path,
274  		                                             password,
275  		                                             NM_SETTING_802_1X_CK_SCHEME_BLOB,
276  		                                             &format,
277  		                                             &error);
278  		ASSERT (success == TRUE,
279  		        "clear-private-key", "error reading private key: %s", error->message);
280  		ASSERT (format != NM_SETTING_802_1X_CK_FORMAT_UNKNOWN,
281  		        "clear-private-key", "unexpected private key format (got %d)", format);
282  	
283  		/* Make sure the password is what we expect */
284  		pw = nm_setting_802_1x_get_private_key_password (s_8021x);
285  		ASSERT (pw != NULL,
286  		        "clear-private-key", "failed to get previous private key password");
287  		ASSERT (strcmp (pw, password) == 0,
288  		        "clear-private-key", "failed to compare private key password");
289  	
290  		/* Now clear it */
291  		success = nm_setting_802_1x_set_private_key (s_8021x,
292  		                                             NULL,
293  		                                             NULL,
294  		                                             NM_SETTING_802_1X_CK_SCHEME_BLOB,
295  		                                             NULL,
296  		                                             &error);
297  		ASSERT (success == TRUE,
298  		        "clear-private-key", "unexpected failure clearing private key");
299  		ASSERT (error == NULL,
300  		        "clear-private-key", "unexpected error clearing private key");
301  	
302  		/* Ensure the password is also now clear */
303  		ASSERT (nm_setting_802_1x_get_private_key_password (s_8021x) == NULL,
304  		        "clear-private-key", "unexpected private key password");
305  	
306  		g_object_unref (s_8021x);
307  	}
308  	
309  	static void
310  	test_wrong_phase2_password_keeps_data (const char *path, const char *password)
311  	{
312  		NMSetting8021x *s_8021x;
313  		gboolean success;
314  		NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
315  		GError *error = NULL;
316  		const char *pw;
317  	
318  		s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
319  		ASSERT (s_8021x != NULL, "wrong-phase2-password-keeps-data", "setting was NULL");
320  	
321  		success = nm_setting_802_1x_set_phase2_private_key (s_8021x,
322  		                                                    path,
323  		                                                    password,
324  		                                                    NM_SETTING_802_1X_CK_SCHEME_BLOB,
325  		                                                    &format,
326  		                                                    &error);
327  		ASSERT (success == TRUE,
328  		        "wrong-phase2-password-keeps-data", "error reading private key: %s", error->message);
329  		ASSERT (format != NM_SETTING_802_1X_CK_FORMAT_UNKNOWN,
330  		        "wrong-phase2-password-keeps-data", "unexpected private key format (got %d)", format);
331  	
332  		/* Now try to set it to something that's not a certificate */
333  		format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
334  		success = nm_setting_802_1x_set_phase2_private_key (s_8021x,
335  		                                                    "Makefile.am",
336  		                                                    password,
337  		                                                    NM_SETTING_802_1X_CK_SCHEME_BLOB,
338  		                                                    &format,
339  		                                                    &error);
340  		ASSERT (success == FALSE,
341  		        "wrong-phase2-password-keeps-data", "unexpected success reading private key");
342  		ASSERT (error != NULL,
343  		        "wrong-phase2-password-keeps-data", "unexpected missing error");
344  		ASSERT (format == NM_SETTING_802_1X_CK_FORMAT_UNKNOWN,
345  		        "wrong-phase2-password-keeps-data", "unexpected success reading private key format");
346  	
347  		/* Make sure the password hasn't changed */
348  		pw = nm_setting_802_1x_get_phase2_private_key_password (s_8021x);
349  		ASSERT (pw != NULL,
350  		        "wrong-phase2-password-keeps-data", "failed to get previous private key password");
351  		ASSERT (strcmp (pw, password) == 0,
352  		        "wrong-phase2-password-keeps-data", "failed to compare private key password");
353  	
354  		g_object_unref (s_8021x);
355  	}
356  	
357  	static void
358  	test_clear_phase2_private_key (const char *path, const char *password)
359  	{
360  		NMSetting8021x *s_8021x;
361  		gboolean success;
362  		NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
363  		GError *error = NULL;
364  		const char *pw;
365  	
366  		s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
367  		ASSERT (s_8021x != NULL, "clear-phase2-private-key", "setting was NULL");
368  	
369  		success = nm_setting_802_1x_set_phase2_private_key (s_8021x,
370  		                                                    path,
371  		                                                    password,
372  		                                                    NM_SETTING_802_1X_CK_SCHEME_BLOB,
373  		                                                    &format,
374  		                                                    &error);
375  		ASSERT (success == TRUE,
376  		        "clear-phase2-private-key", "error reading private key: %s", error->message);
377  		ASSERT (format != NM_SETTING_802_1X_CK_FORMAT_UNKNOWN,
378  		        "clear-phase2-private-key", "unexpected private key format (got %d)", format);
379  	
380  		/* Make sure the password is what we expect */
381  		pw = nm_setting_802_1x_get_phase2_private_key_password (s_8021x);
382  		ASSERT (pw != NULL,
383  		        "clear-phase2-private-key", "failed to get previous private key password");
384  		ASSERT (strcmp (pw, password) == 0,
385  		        "clear-phase2-private-key", "failed to compare private key password");
386  	
387  		/* Now clear it */
388  		success = nm_setting_802_1x_set_phase2_private_key (s_8021x,
389  		                                                    NULL,
390  		                                                    NULL,
391  		                                                    NM_SETTING_802_1X_CK_SCHEME_BLOB,
392  		                                                    NULL,
393  		                                                    &error);
394  		ASSERT (success == TRUE,
395  		        "clear-phase2-private-key", "unexpected failure clearing private key");
396  		ASSERT (error == NULL,
397  		        "clear-phase2-private-key", "unexpected error clearing private key");
398  	
399  		/* Ensure the password is also now clear */
400  		ASSERT (nm_setting_802_1x_get_phase2_private_key_password (s_8021x) == NULL,
401  		        "clear-phase2-private-key", "unexpected private key password");
402  	
403  		g_object_unref (s_8021x);
404  	}
405  	
406  	int main (int argc, char **argv)
407  	{
408  		GError *error = NULL;
409  		char *base;
410  	
411  		if (argc < 3)
412  			FAIL ("init", "need at least two arguments: <path> <password>");
413  	
414  		g_type_init ();
415  	
(6) Event example_checked: Example5: "nm_utils_init(&error)" has its value checked in "nm_utils_init(&error)".
Also see events: [check_return][example_checked][example_checked][example_checked][example_checked][unchecked_value]
416  		if (!nm_utils_init (&error))
417  			FAIL ("nm-utils-init", "failed to initialize libnm-util: %s", error->message);
418  	
419  		/* Test phase1 and phase2 path scheme */
420  		test_private_key_import (argv[1], argv[2], NM_SETTING_802_1X_CK_SCHEME_PATH);
421  		test_phase2_private_key_import (argv[1], argv[2], NM_SETTING_802_1X_CK_SCHEME_PATH);
422  	
423  		/* Test phase1 and phase2 blob scheme */
424  		test_private_key_import (argv[1], argv[2], NM_SETTING_802_1X_CK_SCHEME_BLOB);
425  		test_phase2_private_key_import (argv[1], argv[2], NM_SETTING_802_1X_CK_SCHEME_BLOB);
426  	
427  		/* Test that using a wrong password does not change existing data */
428  		test_wrong_password_keeps_data (argv[1], argv[2]);
429  		test_wrong_phase2_password_keeps_data (argv[1], argv[2]);
430  	
431  		/* Test clearing the private key */
432  		test_clear_private_key (argv[1], argv[2]);
433  		test_clear_phase2_private_key (argv[1], argv[2]);
434  	
435  		base = g_path_get_basename (argv[0]);
436  		fprintf (stdout, "%s: SUCCESS\n", base);
437  		g_free (base);
438  		return 0;
439  	}
440  	
441