1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /* gkr-tool-import.c: Command line key/certificate import
3 
4    Copyright (C) 2008 Stefan Walter
5 
6    The Gnome Keyring Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Library General Public License as
8    published by the Free Software Foundation; either version 2 of the
9    License, or (at your option) any later version.
10 
11    The Gnome Keyring Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Library General Public License for more details.
15 
16    You should have received a copy of the GNU Library General Public
17    License along with the Gnome Library; see the file COPYING.LIB.  If not,
18    <http://www.gnu.org/licenses/>.
19 
20    Author: Stef Walter <stef@memberwebs.com>
21 */
22 
23 #include "config.h"
24 
25 #include "gkr-tool.h"
26 
27 #include <gck/gck.h>
28 #include <gcr/gcr.h>
29 
30 #include "egg/egg-hex.h"
31 
32 static gchar **import_files = NULL;
33 
34 static GOptionEntry import_entries[] = {
35 	GKR_TOOL_BASIC_OPTIONS
36 	{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &import_files, "Filename", NULL },
37 	{ NULL }
38 };
39 
40 static void
imported_fingerprint(const gchar * fingerprint,const gchar * destination)41 imported_fingerprint (const gchar *fingerprint,
42                       const gchar *destination)
43 {
44 	g_print ("%s: imported openpgp\n", destination);
45 	g_print ("\tfingerprint: %s\n", fingerprint);
46 }
47 
48 static void
imported_object(GckObject * object,const gchar * destination)49 imported_object (GckObject *object,
50                  const gchar *destination)
51 {
52 	gulong attr_types[3];
53 	GckAttributes *attrs;
54 	const GckAttribute *id;
55 	CK_OBJECT_CLASS klass;
56 	const gchar *message;
57 	GError *err = NULL;
58 	gchar *label, *hex;
59 
60 	attr_types[0] = CKA_LABEL;
61 	attr_types[1] = CKA_CLASS;
62 	attr_types[2] = CKA_ID;
63 
64 	attrs = gck_object_get_full (object, attr_types, G_N_ELEMENTS (attr_types), NULL, &err);
65 	if (attrs == NULL) {
66 		gkr_tool_handle_error (&err, "couldn't get imported object info");
67 		return;
68 	}
69 
70 	if (!gck_attributes_find_string (attrs, CKA_LABEL, &label))
71 		label = g_strdup ("unknown");
72 	if (!gck_attributes_find_ulong (attrs, CKA_CLASS, &klass))
73 		klass = CKO_DATA;
74 	id = gck_attributes_find (attrs, CKA_ID);
75 
76 	switch (klass) {
77 	case CKO_CERTIFICATE:
78 		message = "%s: imported certificate: %s\n";
79 		break;
80 	case CKO_DATA:
81 		message = "%s: imported data: %s\n";
82 		break;
83 	case CKO_PRIVATE_KEY:
84 		message = "%s: imported private key: %s\n";
85 		break;
86 	case CKO_PUBLIC_KEY:
87 		message = "%s: imported public key: %s\n";
88 		break;
89 	case CKO_SECRET_KEY:
90 		message = "%s: imported secret key: %s\n";
91 		break;
92 	default:
93 		message = "%s: imported object: %s\n";
94 		break;
95 	};
96 
97 	g_print (message, destination, label);
98 
99 	if (id) {
100 		hex = egg_hex_encode (id->value, id->length);
101 		g_print ("\tidentifier: %s\n", hex);
102 		g_free (hex);
103 	}
104 
105 	gck_attributes_unref (attrs);
106 	g_free (label);
107 }
108 
109 static void
imported_display(GcrImporter * importer)110 imported_display (GcrImporter *importer)
111 {
112 	GParamSpec *spec;
113 	gchar *label = NULL;
114 
115 	spec = g_object_class_find_property (G_OBJECT_GET_CLASS (importer), "imported");
116 	if (spec == NULL)
117 		return;
118 
119 	g_object_get (importer, "label", &label, NULL);
120 
121 	if (spec->value_type == GCK_TYPE_LIST) {
122 		GList *list, *l;
123 		g_object_get (importer, "imported", &list, NULL);
124 		for (l = list; l != NULL; l = g_list_next (l))
125 			imported_object (l->data, label);
126 		gck_list_unref_free (list);
127 
128 	} else if (spec->value_type == G_TYPE_STRV) {
129 		gchar **fingerprints;
130 		guint i;
131 		g_object_get (importer, "imported", &fingerprints, NULL);
132 		for (i = 0; fingerprints && fingerprints[i] != NULL; i++)
133 			imported_fingerprint (fingerprints[i], label);
134 		g_strfreev (fingerprints);
135 	}
136 }
137 
138 typedef struct {
139 	GList *importers;
140 	gboolean num_parsed;
141 } ImportClosure;
142 
143 static void
on_parser_parsed(GcrParser * parser,gpointer user_data)144 on_parser_parsed (GcrParser *parser,
145                   gpointer user_data)
146 {
147 	ImportClosure *closure = user_data;
148 	GcrParsed *parsed;
149 	GList *filtered;
150 
151 	parsed = gcr_parser_get_parsed (parser);
152 	if (closure->num_parsed == 0) {
153 		closure->importers = gcr_importer_create_for_parsed (parsed);
154 	} else {
155 		filtered = gcr_importer_queue_and_filter_for_parsed (closure->importers, parsed);
156 		gck_list_unref_free (closure->importers);
157 		closure->importers = filtered;
158 	}
159 
160 	closure->num_parsed++;
161 }
162 
163 int
gkr_tool_import(int argc,char * argv[])164 gkr_tool_import (int argc, char *argv[])
165 {
166 	GcrParser *parser;
167 	GError *error = NULL;
168 	GInputStream *input;
169 	ImportClosure *closure;
170 	GFile *file;
171 	gchar **imp;
172 	int ret = 0;
173 	GList *l;
174 
175 	ret = gkr_tool_parse_options (&argc, &argv, import_entries);
176 	if (ret != 0)
177 		return ret;
178 
179 	if(!import_files || !*import_files) {
180 		gkr_tool_handle_error (NULL, "specify files to import");
181 		return 2;
182 	}
183 
184 	if (!gcr_pkcs11_initialize (NULL, &error)) {
185 		gkr_tool_handle_error (&error, "couldn't initialize pkcs11 modules");
186 		return 1;
187 	}
188 
189 	parser = gcr_parser_new ();
190 	closure = g_new0 (ImportClosure, 1);
191 	g_signal_connect (parser, "parsed", G_CALLBACK (on_parser_parsed), closure);
192 
193 	for (imp = import_files; *imp; ++imp) {
194 		file = g_file_new_for_commandline_arg (*imp);
195 
196 		input = G_INPUT_STREAM (g_file_read (file, NULL, &error));
197 		g_object_unref (file);
198 		if (input == NULL) {
199 			gkr_tool_handle_error (&error, "couldn't read file: %s", *imp);
200 			ret = 1;
201 
202 		} else {
203 			if (!gcr_parser_parse_stream (parser, input, NULL, &error)) {
204 				if (error->code != GCR_ERROR_CANCELLED)
205 					gkr_tool_handle_error (&error, "couldn't parse: %s", *imp);
206 				ret = 1;
207 			}
208 
209 			g_object_unref (input);
210 		}
211 	}
212 
213 	if (closure->importers == NULL) {
214 		gkr_tool_handle_error (NULL, "couldn't find any place to import files");
215 		ret = 1;
216 	}
217 
218 	for (l = closure->importers; l != NULL; l = g_list_next (l)) {
219 		if (gcr_importer_import (l->data, NULL, &error)) {
220 			if (!gkr_tool_mode_quiet)
221 				imported_display (l->data);
222 		} else {
223 			if (error->code != GCR_ERROR_CANCELLED)
224 				gkr_tool_handle_error (&error, "couldn't import");
225 			ret = 1;
226 		}
227 	}
228 
229 	gck_list_unref_free (closure->importers);
230 	g_free (closure);
231 
232 	g_object_unref (parser);
233 	return ret;
234 }
235