Source

sks-keyserver-patches / CleanOption

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
# HG changeset patch
# Parent 5a15aab0027ae1686cad4be1d458d1b8e1017994
Add extended cleaning option (eclean)

diff -r 5a15aab0027a CHANGELOG
--- a/CHANGELOG	Sun Oct 28 21:50:46 2012 +0100
+++ b/CHANGELOG	Sun Oct 28 23:55:11 2012 +0100
@@ -3,6 +3,10 @@
     from self-signatures on the key's UIDs. In addition, instead of 8-digit
     key IDs, index entries now return the most specific key ID possible:
     16-digit key ID for V3 keys, and the full fingerprint for V4 keys.
+  - Added an extended clean (eclean) option (options=eclean) that affect
+    get and (v)index operations. If this option is enabled signatures in
+    unexpected locations (such as directly on a subkey) will not be shown. 
+    In addition this option clean expired signatures from various robo-signers. 
 
 1.1.4
   - Fix X-HKP-Results-Count so that limit=0 returns no results, but include
diff -r 5a15aab0027a Makefile
--- a/Makefile	Sun Oct 28 21:50:46 2012 +0100
+++ b/Makefile	Sun Oct 28 23:55:11 2012 +0100
@@ -80,11 +80,11 @@
 ROBJS=$(ROBJS.bc:.cmo=.cmx)
 
 OBJS.bc=packet.cmo parsePGP.cmo sStream.cmo bdbwrap.cmo \
-	key.cmo keyHash.cmo keyMerge.cmo fixkey.cmo \
+	key.cmo keyHash.cmo keyMerge.cmo \
 	fingerprint.cmo keydb.cmo armor.cmo \
 	dbMessages.cmo htmlTemplates.cmo wserver.cmo \
-	membership.cmo tester.cmo request.cmo \
-	stats.cmo index.cmo mRindex.cmo pTreeDB.cmo \
+	membership.cmo stats.cmo sigInfo.cmo fixkey.cmo tester.cmo request.cmo \
+	index.cmo mRindex.cmo pTreeDB.cmo \
 	sendmail.cmo recvmail.cmo mailsync.cmo \
 	clean_keydb.cmo build.cmo fastbuild.cmo pbuild.cmo merge_keyfiles.cmo \
 	sksdump.cmo incdump.cmo dbserver.cmo reconComm.cmo recoverList.cmo \
diff -r 5a15aab0027a dbserver.ml
--- a/dbserver.ml	Sun Oct 28 21:50:46 2012 +0100
+++ b/dbserver.ml	Sun Oct 28 23:55:11 2012 +0100
@@ -170,7 +170,13 @@
   (** returns list of keys readied for presentation *)
   let clean_keys request keys =
     if request.clean
-    then Utils.filter_map ~f:Fixkey.presentation_filter keys
+    then 
+     if request.extended_clean 
+      then Utils.filter_map 
+            ~f:Fixkey.presentation_filter_wrapper_extended_clean keys
+      else
+       Utils.filter_map 
+            ~f:Fixkey.presentation_filter_wrapper_no_extended_clean keys
     else keys
 
   (** return uid given keyid *)
@@ -272,7 +278,11 @@
           in
           let key =
             if request.clean then
-              match Fixkey.presentation_filter key with
+              let fkp = match request.extended_clean with
+                true -> Fixkey.presentation_filter_wrapper_extended_clean key
+               | false -> Fixkey.presentation_filter_wrapper_no_extended_clean key
+               in
+               match fkp with
                   None -> raise (Wserver.Misc_error "No valid key found for hash")
                 | Some key -> key
             else key
diff -r 5a15aab0027a fixkey.ml
--- a/fixkey.ml	Sun Oct 28 21:50:46 2012 +0100
+++ b/fixkey.ml	Sun Oct 28 23:55:11 2012 +0100
@@ -24,6 +24,7 @@
 open MoreLabels
 open Common
 open Packet
+open SigInfo
 
 module Map = PMap.Map
 
@@ -144,29 +145,90 @@
   try ignore (ParsePGP.parse_pubkey_info pack); true
   with e -> false
 
+let exclude_expired_robo_sig pack =
+ let today = Stats.round_up_to_day (Unix.gettimeofday ()) in
+ let siginfo = sig_to_siginfo pack in
+ let robo_signers = ["9710B89BCA57AD7C"; (* PGP Global Directory *)
+                     "D2BB0D0165D0FD58"; (* CA Cert *)
+                     "77AE7F129E2BD1F2"; (* CA Cert Low security *)
+                     "6EA7FB4DE0BB4BCD"; (* Tele.Ring Robo CA *)
+                     "10581685C521097E"  (* Toehold robot CA *)
+                     ] in 
+ match siginfo.keyid with
+  | Some i -> (match (siginfo.sig_creation_time, siginfo.sig_expiration_time) with 
+                          | (None, _)| (_, None) -> true
+                          | (Some x, Some y) -> 
+                          let keyid = Fingerprint.keyid_to_string ~short:false i in 
+                             if List.mem keyid robo_signers 
+                             then (if (Int64.to_float (Int64.add x y)) < today 
+                                     then false 
+                                     else true) 
+                             else true)
+  | None -> false
+
+let good_clean_signature pack =
+ let checksig = ParsePGP.parse_signature pack in
+ match checksig with
+  | V3sig s -> true
+  | V4sig s -> exclude_expired_robo_sig pack
+   
 let good_signature pack =
   try ignore (ParsePGP.parse_signature pack); true
   with e -> false
 
+let good_subkey_signature pack =
+   let checksig = ParsePGP.parse_signature pack in
+   let result = match checksig with 
+    | V3sig s -> false
+    | V4sig s -> match (int_to_sigtype s.v4s_sigtype) with 
+        | Subkey_Binding_Signature | Subkey_revocation_signature -> true
+        | _ -> false
+   in 
+   result
+
 let drop_bad_sigs packlist =
   List.filter ~f:good_signature packlist
 
+let sig_filter_clean_sigpair (pack,sigs) =
+  let sigs = List.filter ~f:good_clean_signature sigs in
+  if sigs = [] then None
+  else Some (pack,sigs)
+  
 let sig_filter_sigpair (pack,sigs) =
   let sigs = List.filter ~f:good_signature sigs in
   if sigs = [] then None
   else Some (pack,sigs)
 
-let presentation_filter key =
+let subkey_sig_filter_sigpair (pack,sigs) =
+  let sigs = List.filter ~f:good_subkey_signature sigs in
+  if sigs = [] then None
+  else Some (pack,sigs)
+  
+let presentation_filter extended_clean key =
   let pkey = key_to_pkey key in
   if not (good_key pkey.key)
   then None
   else
     let selfsigs = drop_bad_sigs pkey.selfsigs in
-    let subkeys = Utils.filter_map ~f:sig_filter_sigpair pkey.subkeys in
-    let uids = Utils.filter_map ~f:sig_filter_sigpair pkey.uids in
+    let subkeys =
+     (if extended_clean 
+      then Utils.filter_map ~f:subkey_sig_filter_sigpair pkey.subkeys
+      else Utils.filter_map ~f:sig_filter_sigpair pkey.subkeys) in
+    let uids =
+     (if extended_clean
+       then Utils.filter_map ~f:sig_filter_clean_sigpair pkey.uids
+       else Utils.filter_map ~f:sig_filter_sigpair pkey.uids)
+    in
     let subkeys = List.filter ~f:(fun (key,_) -> good_key key) subkeys in
+        
     Some (flatten { pkey with
                       selfsigs = selfsigs;
                       uids = uids;
                       subkeys = subkeys;
                   })
+
+let presentation_filter_wrapper_extended_clean key =
+ presentation_filter true key
+ 
+let presentation_filter_wrapper_no_extended_clean key =
+ presentation_filter false key
diff -r 5a15aab0027a fixkey.mli
--- a/fixkey.mli	Sun Oct 28 21:50:46 2012 +0100
+++ b/fixkey.mli	Sun Oct 28 23:55:11 2012 +0100
@@ -15,4 +15,8 @@
 val drop_bad_sigs : Packet.packet list -> Packet.packet list
 val sig_filter_sigpair :
   'a * Packet.packet list -> ('a * Packet.packet list) option
-val presentation_filter : Packet.packet list -> Packet.packet list option
+val presentation_filter_wrapper_extended_clean :
+  Packet.packet list -> Packet.packet list option
+val presentation_filter_wrapper_no_extended_clean :
+  Packet.packet list -> Packet.packet list option
+
diff -r 5a15aab0027a index.ml
--- a/index.ml	Sun Oct 28 21:50:46 2012 +0100
+++ b/index.ml	Sun Oct 28 23:55:11 2012 +0100
@@ -27,40 +27,12 @@
 open Packet
 open Request
 open Pstyle
+open SigInfo
 
 module Map = PMap.Map
 
 (********************************************************************)
 
-type siginfo = { mutable userid: string option;
-                 mutable policy_url: string option;
-                 mutable notation_data: (string * string) option;
-                 mutable revocation_key: string option;
-                 mutable is_primary_uid: bool;
-                 mutable keyid: string option;
-                 mutable sigtype: int;
-                 mutable sig_creation_time: int64 option;
-                 mutable sig_expiration_time: int64 option;
-                 mutable key_expiration_time: int64 option;
-               }
-
-(********************************************************************)
-
-let empty_siginfo () =
-  { userid = None;
-    policy_url = None;
-    notation_data = None;
-    revocation_key = None;
-    is_primary_uid = false;
-    keyid = None;
-    sigtype = 0;
-    sig_creation_time = None;
-    sig_expiration_time = None;
-    key_expiration_time = None;
-  }
-
-(********************************************************************)
-
 let keyinfo_header request =
   if request.kind = VIndex then
     "Type bits/keyID     cr. time   exp time   key expir"
@@ -69,84 +41,6 @@
 
 (********************************************************************)
 
-let sig_to_siginfo sign =
-  let siginfo = empty_siginfo () in
-  begin
-    match ParsePGP.parse_signature sign with
-      | V3sig s ->
-          siginfo.sigtype <- s.v3s_sigtype;
-          siginfo.keyid <- Some s.v3s_keyid;
-          siginfo.sig_creation_time <- Some s.v3s_ctime
-      | V4sig s ->
-          let update_siginfo ssp =
-            match ssp.ssp_type with
-
-              | 2 -> (* sign. expiration time *)
-                  if ssp.ssp_length = 4 then
-                    siginfo.sig_creation_time <-
-                    Some (ParsePGP.int64_of_string ssp.ssp_body)
-
-              | 3 -> (* sign. expiration time *)
-                  if ssp.ssp_length = 4 then
-                    siginfo.sig_expiration_time <-
-                    let exp = ParsePGP.int64_of_string ssp.ssp_body in
-                    if Int64.compare exp Int64.zero = 0
-                    then None else Some exp
-
-              | 9 -> (* key expiration time *)
-                  if ssp.ssp_length = 4 then
-                    siginfo.key_expiration_time <-
-                    let exp = ParsePGP.int64_of_string ssp.ssp_body in
-                    if Int64.compare exp Int64.zero = 0
-                    then None else Some exp
-
-              | 12 -> (* revocation key *)
-                  let cin = new Channel.string_in_channel ssp.ssp_body 0 in
-                  let _revclass = cin#read_int_size 1 in
-                  let _algid = cin#read_int_size 1 in
-                  let fingerprint = cin#read_string 20 in
-                  siginfo.revocation_key <- Some fingerprint
-
-              | 16 -> (* issuer keyid *)
-                  if ssp.ssp_length = 8 then
-                    siginfo.keyid <- Some ssp.ssp_body
-                  else
-                    printf "Argh!  that makes no sense: %d\n" ssp.ssp_length
-
-              | 20 -> (* notation data *)
-                  let cin = new Channel.string_in_channel ssp.ssp_body 0 in
-                  let flags = cin#read_string 4 in
-                  let name_len = cin#read_int_size 2 in
-                  let value_len = cin#read_int_size 2 in
-                  let name_data = cin#read_string name_len in
-                  let value_data = cin#read_string value_len in
-
-                  if Char.code flags.[0] = 0x80 then
-                    (* human-readable notation data *)
-                    siginfo.notation_data <- Some (name_data,value_data)
-
-              | 25 -> (* primary userid (bool) *)
-                  if ssp.ssp_length = 1 then
-                    let v = int_of_char ssp.ssp_body.[0] in
-                    siginfo.is_primary_uid <- v <> 0
-
-              | 26 -> (* policy URL *)
-                  siginfo.policy_url <- Some ssp.ssp_body
-
-              | 28 -> (* signer's userid *)
-                  siginfo.userid <- Some ssp.ssp_body
-
-              | _ -> (* miscellaneous other packet *)
-                  ()
-          in
-          siginfo.sigtype <- s.v4s_sigtype;
-          List.iter (s.v4s_hashed_subpackets @ s.v4s_unhashed_subpackets)
-            ~f:(fun ssp -> try update_siginfo ssp with End_of_file -> ())
-  end;
-  siginfo
-
-(********************************************************************)
-
 (** sort signatures in ascending time order *)
 let sort_siginfo_list list =
   List.stable_sort list
diff -r 5a15aab0027a index.mli
--- a/index.mli	Sun Oct 28 21:50:46 2012 +0100
+++ b/index.mli	Sun Oct 28 23:55:11 2012 +0100
@@ -1,42 +1,39 @@
-type siginfo
-val empty_siginfo : unit -> siginfo
 val keyinfo_header : Request.request -> string
-val sig_to_siginfo : Packet.packet -> siginfo
-val sort_siginfo_list : siginfo list -> siginfo list
-val is_selfsig : keyid:string -> siginfo -> bool
-val is_primary : keyid:string -> Packet.packet * siginfo list -> bool
-val max_selfsig_time : keyid:string -> 'a * siginfo list -> float
+val sort_siginfo_list : SigInfo.siginfo list -> SigInfo.siginfo list
+val is_selfsig : keyid:string -> SigInfo.siginfo -> bool
+val is_primary : keyid:string -> Packet.packet * SigInfo.siginfo list -> bool
+val max_selfsig_time : keyid:string -> 'a * SigInfo.siginfo list -> float
 val split_list : f:('a -> bool) -> 'a list -> 'a list * 'a list
 val move_primary_to_front :
   keyid:string ->
-  (Packet.packet * siginfo list) list -> (Packet.packet * siginfo list) list
-val convert_sigpair : 'a * Packet.packet list -> 'a * siginfo list
+  (Packet.packet * SigInfo.siginfo list) list -> (Packet.packet * SigInfo.siginfo list) list
+val convert_sigpair : 'a * Packet.packet list -> 'a * SigInfo.siginfo list
 val blank_datestr : string
 val no_datestr : string
 val datestr_of_int64 : int64 -> string
 val siginfo_to_lines :
   get_uid:(string -> string option) ->
   ?key_creation_time:int64 ->
-  Request.request -> string -> float -> siginfo -> string list
+  Request.request -> string -> float -> SigInfo.siginfo -> string list
 val selfsigs_to_lines :
   Request.request ->
   int64 -> string -> Packet.packet list -> float -> string list
 val uid_to_lines :
   get_uid:(string -> string option) ->
   Request.request ->
-  int64 -> string -> float -> Packet.packet * siginfo list -> string list
+  int64 -> string -> float -> Packet.packet * SigInfo.siginfo list -> string list
 val uids_to_lines :
   get_uid:(string -> string option) ->
   Request.request ->
   int64 ->
-  string -> (Packet.packet * siginfo list) list -> float -> string list
+  string -> (Packet.packet * SigInfo.siginfo list) list -> float -> string list
 val key_packet_to_line :
   is_subkey:bool -> Packet.pubkeyinfo -> string -> string * string
 val subkey_to_lines :
-  Request.request -> float -> Packet.packet * siginfo list -> string list
+  Request.request -> float -> Packet.packet * SigInfo.siginfo list -> string list
 val subkeys_to_lines :
   Request.request ->
-  (Packet.packet * siginfo list) list -> float -> string list
+  (Packet.packet * SigInfo.siginfo list) list -> float -> string list
 val extract : f:('a -> bool) -> 'a list -> 'a option * 'a list
 val move_to_front : f:('a -> bool) -> 'a list -> 'a list
 val get_uid :
@@ -47,7 +44,7 @@
 val key_to_lines_verbose :
   get_uids:(string -> (Packet.packet * Packet.packet list) list) ->
   Request.request -> Packet.packet list -> string -> string list
-val sig_is_revok : siginfo -> bool
+val sig_is_revok : SigInfo.siginfo -> bool
 val is_revoked : Packet.packet list -> bool
 val key_to_lines_normal :
   Request.request -> Packet.packet list -> string -> string list
diff -r 5a15aab0027a request.ml
--- a/request.ml	Sun Oct 28 21:50:46 2012 +0100
+++ b/request.ml	Sun Oct 28 23:55:11 2012 +0100
@@ -45,6 +45,7 @@
                  machine_readable: bool;
                  clean: bool;
                  limit: int;
+                 extended_clean: bool;
                }
 
 let default_request = { kind = Index;
@@ -55,6 +56,7 @@
                         machine_readable = false;
                         clean = true;
                         limit = (-1);
+                        extended_clean = false;
                       }
 
 let comma_rxp = Str.regexp ","
@@ -68,7 +70,12 @@
             | ("options",options) ->
                 let options = Str.split comma_rxp options in
                 if List.mem "mr" options
-                then { request with machine_readable = true }
+                then 
+                 (if List.mem "eclean" options 
+                   then { request with machine_readable = true; extended_clean = true }
+                   else { request with machine_readable = true; extended_clean = false })
+                else if List.mem "eclean" options
+                then { request with extended_clean = true }
                 else request
             | ("op","stats") -> {request with kind = Stats };
             | ("op","x-stats") -> {request with kind = Stats };
diff -r 5a15aab0027a request.mli
--- a/request.mli	Sun Oct 28 21:50:46 2012 +0100
+++ b/request.mli	Sun Oct 28 23:55:11 2012 +0100
@@ -11,6 +11,7 @@
   machine_readable : bool;
   clean : bool;
   limit : int;
+  extended_clean: bool;
 }
 val default_request : request
 val comma_rxp : Str.regexp
diff -r 5a15aab0027a sigInfo.ml
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sigInfo.ml	Sun Oct 28 23:55:11 2012 +0100
@@ -0,0 +1,132 @@
+(***********************************************************************)
+(* sigInfo.ml                                                           *)
+(*                                                                     *)
+(* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, *)
+(*               2011, 2012  Yaron Minsky and Contributors             *)
+(*                                                                     *)
+(* This file is part of SKS.  SKS is free software; you can            *)
+(* redistribute it and/or modify it under the terms of the GNU General *)
+(* Public License as published by the Free Software Foundation; either *)
+(* version 2 of the License, or (at your option) any later version.    *)
+(*                                                                     *)
+(* This program is distributed in the hope that it will be useful, but *)
+(* WITHOUT ANY WARRANTY; without even the implied warranty of          *)
+(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   *)
+(* General Public License for more details.                            *)
+(*                                                                     *)
+(* You should have received a copy of the GNU General Public License   *)
+(* along with this program; if not, write to the Free Software         *)
+(* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *)
+(* USA or see <http://www.gnu.org/licenses/>.                          *)
+(***********************************************************************)
+
+open StdLabels
+open MoreLabels
+open Common
+open Packet
+
+type siginfo = { mutable userid: string option;
+                 mutable policy_url: string option;
+                 mutable notation_data: (string * string) option;
+                 mutable revocation_key: string option;
+                 mutable is_primary_uid: bool;
+                 mutable keyid: string option;
+                 mutable sigtype: int;
+                 mutable sig_creation_time: int64 option;
+                 mutable sig_expiration_time: int64 option;
+                 mutable key_expiration_time: int64 option;
+               }
+
+(********************************************************************)
+
+let empty_siginfo () =
+  { userid = None;
+    policy_url = None;
+    notation_data = None;
+    revocation_key = None;
+    is_primary_uid = false;
+    keyid = None;
+    sigtype = 0;
+    sig_creation_time = None;
+    sig_expiration_time = None;
+    key_expiration_time = None;
+  }
+
+(********************************************************************)
+
+let sig_to_siginfo sign =
+  let siginfo = empty_siginfo () in
+  begin
+    match ParsePGP.parse_signature sign with
+      | V3sig s ->
+          siginfo.sigtype <- s.v3s_sigtype;
+          siginfo.keyid <- Some s.v3s_keyid;
+          siginfo.sig_creation_time <- Some s.v3s_ctime
+      | V4sig s ->
+          let update_siginfo ssp =
+            match ssp.ssp_type with
+
+              | 2 -> (* sign. creation time *)
+                  if ssp.ssp_length = 4 then
+                    siginfo.sig_creation_time <-
+                    Some (ParsePGP.int64_of_string ssp.ssp_body)
+
+              | 3 -> (* sign. expiration time *)
+                  if ssp.ssp_length = 4 then
+                    siginfo.sig_expiration_time <-
+                    let exp = ParsePGP.int64_of_string ssp.ssp_body in
+                    if Int64.compare exp Int64.zero = 0
+                    then None else Some exp
+
+              | 9 -> (* key expiration time *)
+                  if ssp.ssp_length = 4 then
+                    siginfo.key_expiration_time <-
+                    let exp = ParsePGP.int64_of_string ssp.ssp_body in
+                    if Int64.compare exp Int64.zero = 0
+                    then None else Some exp
+
+              | 12 -> (* revocation key *)
+                  let cin = new Channel.string_in_channel ssp.ssp_body 0 in
+                  let _revclass = cin#read_int_size 1 in
+                  let _algid = cin#read_int_size 1 in
+                  let fingerprint = cin#read_string 20 in
+                  siginfo.revocation_key <- Some fingerprint
+
+              | 16 -> (* issuer keyid *)
+                  if ssp.ssp_length = 8 then
+                    siginfo.keyid <- Some ssp.ssp_body
+                  else
+                    Printf.printf "Argh!  that makes no sense: %d\n" ssp.ssp_length
+
+              | 20 -> (* notation data *)
+                  let cin = new Channel.string_in_channel ssp.ssp_body 0 in
+                  let flags = cin#read_string 4 in
+                  let name_len = cin#read_int_size 2 in
+                  let value_len = cin#read_int_size 2 in
+                  let name_data = cin#read_string name_len in
+                  let value_data = cin#read_string value_len in
+
+                  if Char.code flags.[0] = 0x80 then
+                    (* human-readable notation data *)
+                    siginfo.notation_data <- Some (name_data,value_data)
+
+              | 25 -> (* primary userid (bool) *)
+                  if ssp.ssp_length = 1 then
+                    let v = int_of_char ssp.ssp_body.[0] in
+                    siginfo.is_primary_uid <- v <> 0
+
+              | 26 -> (* policy URL *)
+                  siginfo.policy_url <- Some ssp.ssp_body
+
+              | 28 -> (* signer's userid *)
+                  siginfo.userid <- Some ssp.ssp_body
+
+              | _ -> (* miscellaneous other packet *)
+                  ()
+          in
+          siginfo.sigtype <- s.v4s_sigtype;
+          List.iter (s.v4s_hashed_subpackets @ s.v4s_unhashed_subpackets)
+            ~f:(fun ssp -> try update_siginfo ssp with End_of_file -> ())
+  end;
+  siginfo
+  
diff -r 5a15aab0027a sigInfo.mli
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sigInfo.mli	Sun Oct 28 23:55:11 2012 +0100
@@ -0,0 +1,14 @@
+type siginfo = {
+  mutable userid : string option;
+  mutable policy_url : string option;
+  mutable notation_data : (string * string) option;
+  mutable revocation_key : string option;
+  mutable is_primary_uid : bool;
+  mutable keyid : string option;
+  mutable sigtype : int;
+  mutable sig_creation_time : int64 option;
+  mutable sig_expiration_time : int64 option;
+  mutable key_expiration_time : int64 option;
+}
+val empty_siginfo : unit -> siginfo
+val sig_to_siginfo : Packet.packet -> siginfo