30
29
package body Keys is
32
31
Key_List_Initial_Size : constant Positive := 200;
32
Key_Head_Length : constant Positive := 72;
34
subtype Key_Head is String(1..Key_Head_Length);
35
package Key_Head_Array_Package
36
is new Expanding_Array (Item => Key_Head);
37
package KHA renames Key_Head_Array_Package;
39
subtype Key_Head_Array is Key_Head_Array_Package.Big_Array;
34
41
type Menu_Array_Ptr is access all Keylist_Menus.MNA;
43
function Match_PR (KP : Key_Properties;
44
KR : Key_Roles) return Boolean is
47
when Any => return True;
48
when Encrypter => return KP(Encrypter);
49
when Signer => return KP(Signer);
50
when Both => return KP(Encrypter) and KP(Signer);
55
function Usable (KP : Key_Properties) return Boolean is
57
return not (KP(Invalid) or KP(Disabled) or KP(Revoked) or KP(Expired));
60
-- Given a line from Listkey, return a processed version.
61
procedure Process_Key (L : in String;
63
KP : out Key_Properties) is
64
LS : UBS_Array := Split_GPG_Colons(L);
65
use Ada.Strings.Fixed;
68
KP := Key_Properties'(others => False);
70
and then ToStr(LS(LS'First)) = "pub" then
71
if LS'Length >= 2 then
73
S : constant String := ToStr(LS(LS'First+1));
75
if Count(S, "i") = 1 then
78
if Count(S, "d") = 1 then
81
if Count(S, "r") = 1 then
84
if Count(S, "e") = 1 then
89
if LS'Length >= 12 then
91
S : constant String := ToStr(LS(LS'First+11));
93
if Count(S, "D") = 1 then
96
if Count(S, "E") = 1 then
97
KP(Encrypter) := True;
99
if Count(S, "S") = 1 then
108
P := P & ToUBS("[Invalid]");
111
P := P & ToUBS("[Disabled]");
114
P := P & ToUBS("[Revoked]");
117
P := P & ToUBS("[Expired]");
119
if LS'Length >= 5 then
120
-- Append the last eight characters of the key ID.
122
KS : constant String := ToStr(LS(LS'First+4));
129
P := P & KS(F..KS'Last);
132
if LS'Length >= 6 then
133
-- Append the start date.
134
P := P & ToUBS(" ") & LS(LS'First+5);
136
if LS'Length >= 10 then
137
-- Append the user name.
138
P := P & ToUBS(" ") & LS(LS'First+9);
142
P := ToUBS("??:" & L);
146
Ada.Text_IO.Put_Line(Ada.Text_IO.Standard_Error,
147
"Exception raised in Keys.Process_Key");
36
151
-- Add a key to the list....
37
152
procedure Add_Key (Key : in UBS;
38
List : in out Key_List) is
39
Match : Boolean := False;
153
List : in out Key_List;
154
Role : in Key_Roles) is
155
Match : Boolean := False;
156
Key_Filename : constant String := Temp_File_Name("addkey");
159
File_Handle : Ada.Text_IO.File_Type;
43
Debug("Add_Key: Checking for duplicates");
162
Debug("+Add_Key: `" & ToStr(Key) & "'");
163
-- Puke if this is not a fingerprint....
165
KS : constant String := ToStr(Key);
166
use Ada.Strings.Maps;
47
Debug("Add_Key: Approaching duplicates loop");
48
for I in 1..List.Count loop
49
Debug("Add_Key: In duplicates loop");
50
Match := Match or Key = UAP.Value(List.KA, I);
168
for I in KS'Range loop
170
Ada.Strings.Maps.Constants.Hexadecimal_Digit_Set) then
171
Ada.Text_IO.Put_Line(Ada.Text_IO.Standard_Error,
172
"Expected fingerprint, but working on `"&
174
raise Fingerprint_Expected;
55
Debug("Add_Key: Adding a key");
56
List.Count := List.Count + 1;
57
UAP.Set(List.KA, List.Count, Key);
58
Debug("Add_Key: Done adding a key");
178
-- Is this key usable?
179
Externals.GPG.Listkey(Key => ToStr(Key), Target => Key_Filename);
180
Ada.Text_IO.Open(File => File_Handle,
181
Mode => Ada.Text_IO.In_File,
182
Name => Key_Filename);
183
First_Line := Unbounded_Get_Line(File_Handle);
184
Ada.Text_IO.Close(File_Handle);
185
Process_Key(ToStr(First_Line), P, KP);
186
if not Usable(KP) then
188
Ada.Text_IO.Put_Line("Key " & ToStr(Key) & " is not usable!");
189
elsif not Match_PR(KP, Role) then
190
-- Doesn't match role.
191
Ada.Text_IO.Put_Line("Key " & ToStr(Key) & " has wrong role!");
193
-- Is it a duplicate?
194
Debug("Add_Key: Checking for duplicates");
198
Debug("Add_Key: Approaching duplicates loop");
199
for I in 1..List.Count loop
200
Debug("Add_Key: In duplicates loop");
201
Match := Match or Key = UAP.Value(List.KA, I);
206
Debug("Add_Key: Adding a key");
207
List.Count := List.Count + 1;
208
UAP.Set(List.KA, List.Count, Key);
209
Debug("Add_Key: Done adding a key");
67
219
-- Remove a key. We then shuffle the array down.
68
220
-- It will only remove the last key if there are multiple instances.
69
procedure Remove_Key (Key : in UBS;
70
List : in out Key_List) is
72
Key_Found : Boolean := False;
221
-- The nastiness here is that we might be working with short
222
-- fingerprints. So choose the right hand end of the fingerprint.
223
procedure Remove_Key (Key : in UBS;
224
List : in out Key_List;
225
Exception_If_Missing : in Boolean := False) is
227
Key_Found : Boolean := False;
228
KS : constant String := ToStr(Key);
229
Key_Length : constant Natural := KS'Length;
75
231
for I in 1..List.Count loop
76
if Key = UAP.Value(List.KA, I) then
233
-- Get this string...
234
TK : constant String := ToStr(UAP.Value(List.KA, I));
238
TK_Start := TK'First;
239
if TK'Length > Key_Length then
240
-- Advance TK_Start so that we've got matching lengths.
241
TK_Start := TK'Last - Key_Length + 1;
243
if KS = TK(TK_Start..TK'Last) then
82
250
-- Shuffle the array over it.
114
284
-- Get key fingerprint(s) for a key. Add them.
115
285
procedure Add_Keys_By_Fingerprint (Key_In : in UBS;
116
286
List : in out Key_List;
117
288
Found : out Boolean) is
118
K : String := ToStr(Key_In);
119
Tempfile : String := Temp_File_Name("findkey-akbf");
289
K : constant String := ToStr(Key_In);
290
Tempfile : constant String := Temp_File_Name("findkey-akbf");
120
291
TFH : Ada.Text_IO.File_Type;
122
293
Match : Boolean := False;
124
295
Debug("Add_Keys_By_Fingerprint (A): starting...");
125
296
-- First, try finding some keys for this Key_In.
126
GPG.Findkey(Key => K,
297
Externals.GPG.Findkey(Key => K,
127
298
Target => Tempfile);
128
Debug("Add_Keys_By_Fingerprint (A): GPG.Findkey returned okay");
299
Debug("Add_Keys_By_Fingerprint (A): Externals.GPG.Findkey returned okay");
129
300
-- Now, open the file, and read in each line as a key for Add_Key.
130
301
Ada.Text_IO.Open(File => TFH,
131
302
Mode => Ada.Text_IO.In_File,
167
339
-- Add the secret keys to this key list.
168
340
procedure Add_Secret_Keys (Key_In : in UBS;
169
List : in out Key_List) is
170
K : String := ToStr(Key_In);
171
Tempfile : String := Temp_File_Name("findkey-ask");
341
List : in out Key_List;
342
Role : in Key_Roles) is
343
K : constant String := ToStr(Key_In);
344
Tempfile : constant String := Temp_File_Name("findkey-ask");
172
345
TFH : Ada.Text_IO.File_Type;
174
Match : Boolean := False;
176
348
-- First, try finding some _secret_ keys for this Key_In.
177
GPG.Findkey_Secret(Key => K,
349
Externals.GPG.Findkey_Secret(Key => K,
178
350
Target => Tempfile);
179
351
-- Now, open the file, and read in each line as a key for
180
352
-- Add_Keys_By_Fingerprint (so we don't need to go hunting for the
203
374
end Add_Secret_Keys;
376
procedure Generate_Key_List (List : in out Key_List;
377
Key_Heads : in out Key_Head_Array;
378
Key_Menu : in out Menu_Array_Ptr) is
381
Debug("+Generate_Key_List");
382
-- First, we generate a current list of info files for the keys.
383
for I in 1..List.Count loop
385
Key_File_Name : constant String
386
:= Temp_File_Name("key"
387
& Trim_Leading_Spaces(Integer'Image(I)));
389
Externals.GPG.Listkey(Key => ToStr(UAP.Value(List.KA, I)),
390
Target => Key_File_Name);
391
-- Now, dump into our `head' array the first line of each.
393
File_Handle : Ada.Text_IO.File_Type;
397
Ada.Text_IO.Open(File => File_Handle,
398
Mode => Ada.Text_IO.In_File,
399
Name => Key_File_Name);
400
First_Line := Unbounded_Get_Line(File_Handle);
401
Ada.Text_IO.Close(File_Handle);
402
Process_Key(ToStr(First_Line), P, KP);
403
-- if Usable(KP) then
406
FL : constant String := ToStr(P);
407
use Ada.Strings.Fixed;
409
if FL'Length >= Key_Head_Length then
410
KHA.Set(Key_Heads, I, FL(FL'First..
411
FL'First+Key_Head_Length-1));
413
KHA.Set(Key_Heads, I, FL
414
& (Key_Head_Length - FL'Length) * ' ');
421
-- Now, create a menu with those key_heads.
422
Key_Menu := new Keylist_Menus.MNA(1..C);
424
Key_Menu(I) := ToUBS(KHA.Value(Key_Heads, I));
426
Debug("-Generate_Key_List");
429
Ada.Text_IO.Put_Line(Ada.Text_IO.Standard_Error,
430
"Exception raised in Keys.Generate_Key_List");
432
end Generate_Key_List;
205
434
-- List the keys and edit them as appropriate (include removing a key
206
435
-- from that list, and adding one from the keyring.
207
436
procedure List_Keys (List : in out Key_List) is
208
Key_Head_Length : constant Positive := 65;
209
subtype Key_Head is String(1..Key_Head_Length);
210
package Key_Head_Array_Package
211
is new Expanding_Array (Item => Key_Head);
212
package KHA renames Key_Head_Array_Package;
214
subtype Key_Head_Array is Key_Head_Array_Package.Big_Array;
216
Key_Heads : Key_Head_Array;
218
Key_Menu : Menu_Array_Ptr;
220
procedure Generate_Key_List is
222
Debug("+Generate_Key_List");
223
-- First, we generate a current list of info files for the keys.
224
for I in 1..List.Count loop
226
Key_File_Name : String
227
:= Temp_File_Name("key"
228
& Trim_Leading_Spaces(Integer'Image(I)));
230
GPG.Listkey(Key => ToStr(UAP.Value(List.KA, I)),
231
Target => Key_File_Name);
232
-- Now, dump into our `head' array the first line of each.
234
File_Handle : Ada.Text_IO.File_Type;
237
Ada.Text_IO.Open(File => File_Handle,
238
Mode => Ada.Text_IO.In_File,
239
Name => Key_File_Name);
240
First_Line := Unbounded_Get_Line(File_Handle);
241
Ada.Text_IO.Close(File_Handle);
243
FL : String := ToStr(First_Line);
244
use Ada.Strings.Fixed;
246
if FL'Length >= Key_Head_Length then
247
KHA.Set(Key_Heads, I, FL(FL'First..
248
FL'First+Key_Head_Length-1));
250
KHA.Set(Key_Heads, I, FL
251
& (Key_Head_Length - FL'Length) * ' ');
257
-- Now, create a menu with those key_heads.
258
Key_Menu := new Keylist_Menus.MNA(1..List.Count);
259
for I in 1..List.Count loop
260
Key_Menu(I) := ToUBS("Details: " & KHA.Value(Key_Heads, I));
262
Debug("-Generate_Key_List");
265
Ada.Text_IO.Put_Line(Ada.Text_IO.Standard_Error,
266
"Exception raised in Keys.List_Keys.Generate_Key_List");
268
end Generate_Key_List;
437
Key_Heads : Key_Head_Array;
438
Key_Menu : Menu_Array_Ptr;
270
439
Selection : Keylist_Menus.CLM_Return;
271
440
Selected : Integer;
272
441
SK_Selection : Specific_Key_Index;
274
443
Debug("+List_Keys");
275
444
KHA.Create(Key_Heads, Key_List_Initial_Size);
445
Generate_Key_List(List, Key_Heads, Key_Menu);
448
Ada.Text_IO.New_Line(5);
449
Ada.Text_IO.Put_Line("** Key list menu:");
450
Ada.Text_IO.Put_Line(Integer'Image(Keys.Count(List))
451
& " key(s) in key list ");
279
452
Selection := Keylist_Menu(Key_Menu.all);
280
453
if not Selection.Is_Num then
281
454
case Selection.I is
354
529
procedure Select_Key_From_List (List : in out Key_List;
355
530
The_Fingerprint : out UBS;
356
531
Aborted : out Boolean) is
357
Key_Head_Length : constant Positive := 65;
358
subtype Key_Head is String(1..Key_Head_Length);
359
package Key_Head_Array_Package
360
is new Expanding_Array (Item => Key_Head);
361
package KHA renames Key_Head_Array_Package;
363
subtype Key_Head_Array is Key_Head_Array_Package.Big_Array;
365
Key_Heads : Key_Head_Array;
367
Key_Menu : Menu_Array_Ptr;
369
procedure Generate_Key_List is
371
Debug("+Generate_Key_List");
372
-- First, we generate a current list of info files for the keys.
373
for I in 1..List.Count loop
375
Key_File_Name : String
376
:= Temp_File_Name("key"
377
& Trim_Leading_Spaces(Integer'Image(I)));
379
GPG.Listkey(Key => ToStr(UAP.Value(List.KA, I)),
380
Target => Key_File_Name);
381
-- Now, dump into our `head' array the first line of each.
383
File_Handle : Ada.Text_IO.File_Type;
386
Ada.Text_IO.Open(File => File_Handle,
387
Mode => Ada.Text_IO.In_File,
388
Name => Key_File_Name);
389
First_Line := Unbounded_Get_Line(File_Handle);
390
Ada.Text_IO.Close(File_Handle);
392
FL : String := ToStr(First_Line);
393
use Ada.Strings.Fixed;
395
if FL'Length >= Key_Head_Length then
396
KHA.Set(Key_Heads, I, FL(FL'First..
397
FL'First+Key_Head_Length-1));
399
KHA.Set(Key_Heads, I, FL
400
& (Key_Head_Length - FL'Length) * ' ');
406
-- Now, create a menu with those key_heads.
407
Key_Menu := new Keylist_Menus.MNA(1..List.Count);
408
for I in 1..List.Count loop
409
Key_Menu(I) := ToUBS("Details: " & KHA.Value(Key_Heads, I));
411
Debug("-Generate_Key_List");
414
Ada.Text_IO.Put_Line(Ada.Text_IO.Standard_Error,
415
"Exception raised in Keys.Select_Key_From_List.Generate_Key_List");
417
end Generate_Key_List;
532
Key_Heads : Key_Head_Array;
533
Key_Menu : Menu_Array_Ptr;
419
534
Selection : Keylist_Menus.CLM_Return;
420
535
Selected : Integer;
421
536
SK_Selection : Specific_Key_Index;