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