Browse Source

Now with rustfmt.

Thomas Kerber 2 years ago
parent
commit
e5346fc8d9
12 changed files with 553 additions and 255 deletions
  1. 1
    0
      .gitignore
  2. 48
    11
      src/apdu.rs
  3. 93
    40
      src/extract.rs
  4. 18
    9
      src/fs/data.rs
  5. 15
    6
      src/fs/dummy.rs
  6. 30
    15
      src/fs/efdf.rs
  7. 118
    71
      src/fs/mod.rs
  8. 33
    26
      src/fs/path.rs
  9. 32
    16
      src/fs/short.rs
  10. 8
    4
      src/main.rs
  11. 112
    28
      src/scan.rs
  12. 45
    29
      src/util.rs

+ 1
- 0
.gitignore View File

@@ -1 +1,2 @@
1 1
 target
2
+**/*.rs.bk

+ 48
- 11
src/apdu.rs View File

@@ -17,21 +17,39 @@ impl<'a> InsRewriteHandle<'a> {
17 17
     pub fn new(handle: pcsc::Handle<'a>, rules: &[[u8; 4]]) -> Self {
18 18
         let mut map = HashMap::with_capacity(rules.len());
19 19
         for rule in rules.iter() {
20
-            map.insert(
21
-                Ins { cla: rule[0], ins: rule[1] },
22
-                Ins { cla: rule[2], ins: rule[3] });
20
+            map.insert(Ins {
21
+                           cla: rule[0],
22
+                           ins: rule[1],
23
+                       },
24
+                       Ins {
25
+                           cla: rule[2],
26
+                           ins: rule[3],
27
+                       });
28
+        }
29
+        InsRewriteHandle {
30
+            internal: handle,
31
+            rules: map,
23 32
         }
24
-        InsRewriteHandle { internal: handle, rules: map }
25 33
     }
26 34
 }
27 35
 
28 36
 impl<'a> Transmit for InsRewriteHandle<'a> {
29
-    fn transmit(&mut self, send: &[u8], buf: &mut[u8]) -> Result<usize, pcsc::Error> {
37
+    fn transmit(&mut self, send: &[u8], buf: &mut [u8]) -> Result<usize, pcsc::Error> {
30 38
         self.internal.transmit(send, buf)
31 39
     }
32 40
 
33
-    fn transmit_apdu(&mut self, cla: u8, ins: u8, p1: u8, p2: u8, data: &[u8], le: usize) -> Result<Vec<u8>, pcsc::Error> {
34
-        let mut ins = Ins { cla: cla, ins: ins};
41
+    fn transmit_apdu(&mut self,
42
+                     cla: u8,
43
+                     ins: u8,
44
+                     p1: u8,
45
+                     p2: u8,
46
+                     data: &[u8],
47
+                     le: usize)
48
+                     -> Result<Vec<u8>, pcsc::Error> {
49
+        let mut ins = Ins {
50
+            cla: cla,
51
+            ins: ins,
52
+        };
35 53
         if let Some(ins2) = self.rules.get(&ins) {
36 54
             ins = *ins2;
37 55
         }
@@ -49,16 +67,35 @@ pub struct ClaRewriteHandle<'a> {
49 67
 
50 68
 impl<'a> ClaRewriteHandle<'a> {
51 69
     pub fn new(handle: pcsc::Handle<'a>, cla: u8) -> Self {
52
-        ClaRewriteHandle { internal: handle, cla: cla }
70
+        ClaRewriteHandle {
71
+            internal: handle,
72
+            cla: cla,
73
+        }
53 74
     }
54 75
 }
55 76
 
56 77
 impl<'a> Transmit for ClaRewriteHandle<'a> {
57
-    fn transmit(&mut self, send: &[u8], buf: &mut[u8]) -> Result<usize, pcsc::Error> {
78
+    fn transmit(&mut self, send: &[u8], buf: &mut [u8]) -> Result<usize, pcsc::Error> {
58 79
         self.internal.transmit(send, buf)
59 80
     }
60 81
 
61
-    fn transmit_apdu(&mut self, cla: u8, ins: u8, p1: u8, p2: u8, data: &[u8], le: usize) -> Result<Vec<u8>, pcsc::Error> {
62
-        self.internal.transmit_apdu(if cla == 0x00 { self.cla } else { cla }, ins, p1, p2, data, le)
82
+    fn transmit_apdu(&mut self,
83
+                     cla: u8,
84
+                     ins: u8,
85
+                     p1: u8,
86
+                     p2: u8,
87
+                     data: &[u8],
88
+                     le: usize)
89
+                     -> Result<Vec<u8>, pcsc::Error> {
90
+        self.internal.transmit_apdu(if cla == 0x00 {
91
+                                        self.cla
92
+                                    } else {
93
+                                        cla
94
+                                    },
95
+                                    ins,
96
+                                    p1,
97
+                                    p2,
98
+                                    data,
99
+                                    le)
63 100
     }
64 101
 }

+ 93
- 40
src/extract.rs View File

@@ -16,7 +16,7 @@ enum FileType {
16 16
     EF,
17 17
     DF,
18 18
     Data,
19
-    Short
19
+    Short,
20 20
 }
21 21
 
22 22
 #[derive(Debug)]
@@ -26,7 +26,10 @@ struct FilePath {
26 26
     ftype: FileType,
27 27
 }
28 28
 
29
-fn extract_data_files<T: AsRef<[u8]>, P: AsRef<Path>>(handle: &mut pcsc::Transmit, files: &[T], outdir: P, caps: fs::Capabilities) {
29
+fn extract_data_files<T: AsRef<[u8]>, P: AsRef<Path>>(handle: &mut pcsc::Transmit,
30
+                                                      files: &[T],
31
+                                                      outdir: P,
32
+                                                      caps: fs::Capabilities) {
30 33
     let mut factory = None;
31 34
     for fact in fs::DATA_FACTORIES {
32 35
         if fact.has_required_capabilities(caps) {
@@ -37,7 +40,8 @@ fn extract_data_files<T: AsRef<[u8]>, P: AsRef<Path>>(handle: &mut pcsc::Transmi
37 40
     let factory = match factory {
38 41
         Some(v) => v,
39 42
         None => {
40
-            warn!("No recipe for data extract with AF capabilities! ({:?})", caps.list());
43
+            warn!("No recipe for data extract with AF capabilities! ({:?})",
44
+                  caps.list());
41 45
             return;
42 46
         }
43 47
     };
@@ -52,12 +56,17 @@ fn extract_data_files<T: AsRef<[u8]>, P: AsRef<Path>>(handle: &mut pcsc::Transmi
52 56
     println!(":::: Starting data extraction");
53 57
     for file in files {
54 58
         if let Err(e) = handle.extract_data(file.as_ref(), outdir.as_ref()) {
55
-            error!("Error during extraction of {}: {}", file.as_ref().to_hex(), e);
59
+            error!("Error during extraction of {}: {}",
60
+                   file.as_ref().to_hex(),
61
+                   e);
56 62
         }
57 63
     }
58 64
 }
59 65
 
60
-fn extract_full_files<T: AsRef<[u8]>, P: AsRef<Path>>(handle: &mut pcsc::Transmit, files: &[T], outdir: P, caps: fs::Capabilities) {
66
+fn extract_full_files<T: AsRef<[u8]>, P: AsRef<Path>>(handle: &mut pcsc::Transmit,
67
+                                                      files: &[T],
68
+                                                      outdir: P,
69
+                                                      caps: fs::Capabilities) {
61 70
     let mut factory = None;
62 71
     for fact in fs::FULL_FACTORIES {
63 72
         if fact.has_required_capabilities(caps) {
@@ -68,7 +77,8 @@ fn extract_full_files<T: AsRef<[u8]>, P: AsRef<Path>>(handle: &mut pcsc::Transmi
68 77
     let factory = match factory {
69 78
         Some(v) => v,
70 79
         None => {
71
-            warn!("No recipe for full id extract with AF capabilities! ({:?})", caps.list());
80
+            warn!("No recipe for full id extract with AF capabilities! ({:?})",
81
+                  caps.list());
72 82
             return;
73 83
         }
74 84
     };
@@ -83,12 +93,17 @@ fn extract_full_files<T: AsRef<[u8]>, P: AsRef<Path>>(handle: &mut pcsc::Transmi
83 93
     println!(":::: Starting full file identifier extraction");
84 94
     for file in files {
85 95
         if let Err(e) = handle.extract(file.as_ref(), outdir.as_ref(), caps) {
86
-            error!("Error during extraction of {}: {}", file.as_ref().to_hex(), e);
96
+            error!("Error during extraction of {}: {}",
97
+                   file.as_ref().to_hex(),
98
+                   e);
87 99
         }
88 100
     }
89 101
 }
90 102
 
91
-fn extract_short_files<T: AsRef<[u8]>, P: AsRef<Path>>(handle: &mut pcsc::Transmit, files: &[T], outdir: P, caps: fs::Capabilities) {
103
+fn extract_short_files<T: AsRef<[u8]>, P: AsRef<Path>>(handle: &mut pcsc::Transmit,
104
+                                                       files: &[T],
105
+                                                       outdir: P,
106
+                                                       caps: fs::Capabilities) {
92 107
     let mut factory = None;
93 108
     for fact in fs::SHORT_FACTORIES {
94 109
         if fact.has_required_capabilities(caps) {
@@ -99,7 +114,8 @@ fn extract_short_files<T: AsRef<[u8]>, P: AsRef<Path>>(handle: &mut pcsc::Transm
99 114
     let factory = match factory {
100 115
         Some(v) => v,
101 116
         None => {
102
-            warn!("No recipe for short id extraction with AF capabilities! ({:?})", caps.list());
117
+            warn!("No recipe for short id extraction with AF capabilities! ({:?})",
118
+                  caps.list());
103 119
             return;
104 120
         }
105 121
     };
@@ -114,13 +130,19 @@ fn extract_short_files<T: AsRef<[u8]>, P: AsRef<Path>>(handle: &mut pcsc::Transm
114 130
     println!(":::: Starting short file identifier extraction");
115 131
     for file in files {
116 132
         if let Err(e) = handle.extract(file.as_ref(), outdir.as_ref(), caps) {
117
-            error!("Error during extraction of {}: {}", file.as_ref().to_hex(), e);
133
+            error!("Error during extraction of {}: {}",
134
+                   file.as_ref().to_hex(),
135
+                   e);
118 136
         }
119 137
     }
120 138
 }
121 139
 
122 140
 fn print_usage(program: &str, command: &str, opts: &Options) -> ! {
123
-    let brief = format!("Usage: {0} {1} [options] INFILE OUTDIR\n\nExtracts the files listed in INFILE to OUTDIR from a smartcard. INFILE should have previously been generated using '{0} scan'.", program, command);
141
+    let brief = format!("Usage: {0} {1} [options] INFILE OUTDIR\n\nExtracts the files listed in \
142
+                         INFILE to OUTDIR from a smartcard. INFILE should have previously been \
143
+                         generated using '{0} scan'.",
144
+                        program,
145
+                        command);
124 146
     print!("{}", opts.usage(&brief));
125 147
     exit(1);
126 148
 }
@@ -184,17 +206,23 @@ fn parse_infile<P: AsRef<Path>>(infile: P) -> Result<Vec<FilePath>, ParseError>
184 206
             "short" => FileType::Short,
185 207
             "data" => FileType::Data,
186 208
             // Backwards compatibility with previous notation.
187
-            "full" => if parts.len() == 4 && parts[3] == "true" {
188
-                FileType::DF
189
-            } else {
190
-                FileType::EF
191
-            },
209
+            "full" => {
210
+                if parts.len() == 4 && parts[3] == "true" {
211
+                    FileType::DF
212
+                } else {
213
+                    FileType::EF
214
+                }
215
+            }
192 216
             _ => {
193 217
                 warn!("unknown path type: {}", parts[0]);
194 218
                 continue;
195
-            },
219
+            }
196 220
         };
197
-        ret.push(FilePath{af: af, path: path, ftype: ftype})
221
+        ret.push(FilePath {
222
+            af: af,
223
+            path: path,
224
+            ftype: ftype,
225
+        })
198 226
     }
199 227
     Ok(ret)
200 228
 }
@@ -204,15 +232,33 @@ pub fn main(args: Vec<String>) {
204 232
     let command = args[1].clone();
205 233
 
206 234
     let mut opts = Options::new();
207
-    opts.optopt("p", "pin", "sets the verify apdu pin in hex, with the first byte being the PIN id. (e.g. 813132333435 corresponds to the APDU 00200081053132333435)", "PIN");
208
-    opts.optopt("c", "cla", "sets the cla byte to use when extracting files. Specified as a single hex byte.", "CLA");
209
-    opts.optopt("", "apdumap", "specifies rules to rewrite apdus. Rules are comma sperated, and have the for '<ORIG CLA><ORIG INS>-><NEW CLA><NEW INS>'. Example: --apdumap 00a4->3030,00b0->3031", "RULES");
210
-    opts.optopt("r", "reader", "specifies the reader to use. Uses the first reader with the given string as part of its name.", "READER");
235
+    opts.optopt("p",
236
+                "pin",
237
+                "sets the verify apdu pin in hex, with the first byte being the PIN id. (e.g. \
238
+                 813132333435 corresponds to the APDU 00200081053132333435)",
239
+                "PIN");
240
+    opts.optopt("c",
241
+                "cla",
242
+                "sets the cla byte to use when extracting files. Specified as a single hex byte.",
243
+                "CLA");
244
+    opts.optopt("",
245
+                "apdumap",
246
+                "specifies rules to rewrite apdus. Rules are comma sperated, and have the for \
247
+                 '<ORIG CLA><ORIG INS>-><NEW CLA><NEW INS>'. Example: --apdumap \
248
+                 00a4->3030,00b0->3031",
249
+                "RULES");
250
+    opts.optopt("r",
251
+                "reader",
252
+                "specifies the reader to use. Uses the first reader with the given string as \
253
+                 part of its name.",
254
+                "READER");
211 255
     opts.optflag("h", "help", "prints this help text");
212
-    opts.optflag("", "data-each-file", "Try to access every data element for each file.");
256
+    opts.optflag("",
257
+                 "data-each-file",
258
+                 "Try to access every data element for each file.");
213 259
     let matches = match opts.parse(&args[2..]) {
214
-        Ok(m) => { m }
215
-        Err(e) => { panic!(e.to_string()) }
260
+        Ok(m) => m,
261
+        Err(e) => panic!(e.to_string()),
216 262
     };
217 263
     if matches.opt_present("h") {
218 264
         print_usage(&program, &command, &opts);
@@ -229,18 +275,20 @@ pub fn main(args: Vec<String>) {
229 275
         Err(e) => {
230 276
             error!("Error parsing infile: {}", e);
231 277
             exit(2)
232
-        },
278
+        }
233 279
     };
234 280
     let outdir = &matches.free[1];
235 281
     // Part 1: Sort by AF.
236 282
     let mut affiles = HashMap::new();
237 283
     for file in files {
238 284
         {
239
-            if !affiles.contains_key(&file.af[..]) {
240
-                affiles.insert(file.af.clone(), Vec::new());
285
+                if !affiles.contains_key(&file.af[..]) {
286
+                    affiles.insert(file.af.clone(), Vec::new());
287
+                }
288
+                affiles.get_mut(&file.af[..])
241 289
             }
242
-            affiles.get_mut(&file.af[..])
243
-        }.unwrap().push(file);
290
+            .unwrap()
291
+            .push(file);
244 292
     }
245 293
     let caps = match fs::Capabilities::test_for(&mut *handle, true) {
246 294
         Ok(v) => v,
@@ -250,7 +298,8 @@ pub fn main(args: Vec<String>) {
250 298
         }
251 299
     };
252 300
     if !caps.has(fs::Capability::SelectAF) {
253
-        warn!("Card does not appear to have the capability to select AFs. Trying to select AFs anyway.");
301
+        warn!("Card does not appear to have the capability to select AFs. Trying to select AFs \
302
+               anyway.");
254 303
     }
255 304
     // Part 2: For each AF, select it and rescan capabilities, and get a factory for it (if
256 305
     // possible).
@@ -308,15 +357,19 @@ pub fn main(args: Vec<String>) {
308 357
         }
309 358
         if data_files.len() > 0 {
310 359
             if matches.opt_present("data-each-file") {
311
-                data_files = data_files.into_iter().filter(|tag| tag.len() == 2)
312
-                    .flat_map(|tag|
313
-                    efs.iter()
314
-                        .chain(dfs.iter())
315
-                        .map(|file| {
316
-                            let mut path = file.to_owned();
317
-                            path.extend(tag.iter());
318
-                            path
319
-                        }).collect::<Vec<_>>()).collect();
360
+                data_files = data_files.into_iter()
361
+                    .filter(|tag| tag.len() == 2)
362
+                    .flat_map(|tag| {
363
+                        efs.iter()
364
+                            .chain(dfs.iter())
365
+                            .map(|file| {
366
+                                let mut path = file.to_owned();
367
+                                path.extend(tag.iter());
368
+                                path
369
+                            })
370
+                            .collect::<Vec<_>>()
371
+                    })
372
+                    .collect();
320 373
             }
321 374
             data_files.sort();
322 375
             data_files.dedup();

+ 18
- 9
src/fs/data.rs View File

@@ -1,4 +1,5 @@
1
-use fs::{FileSystemHandleFactory, FileSystemHandle, Capabilities, Error, Capability, FULL_FACTORIES, DUMMY_FACTORY, try_sw, scan_start, scan_update, scan_end, found_data};
1
+use fs::{FileSystemHandleFactory, FileSystemHandle, Capabilities, Error, Capability,
2
+         FULL_FACTORIES, DUMMY_FACTORY, try_sw, scan_start, scan_update, scan_end, found_data};
2 3
 use pcsclite as pcsc;
3 4
 use pcsclite::Transmit;
4 5
 
@@ -9,7 +10,10 @@ impl FileSystemHandleFactory for DataHandleFactory {
9 10
         c.has(Capability::ReadData)
10 11
     }
11 12
 
12
-    fn create<'a>(&self, handle: &'a mut Transmit, caps: Capabilities) -> Result<Box<FileSystemHandle<'a> + 'a>, Error> {
13
+    fn create<'a>(&self,
14
+                  handle: &'a mut Transmit,
15
+                  caps: Capabilities)
16
+                  -> Result<Box<FileSystemHandle<'a> + 'a>, Error> {
13 17
         // Find a full path factory that works, and use that. If none are available, us a dummy.
14 18
         let mut fsh = None;
15 19
         for factory in FULL_FACTORIES.iter().chain(&[DUMMY_FACTORY]) {
@@ -18,7 +22,7 @@ impl FileSystemHandleFactory for DataHandleFactory {
18 22
                 break;
19 23
             }
20 24
         }
21
-        Ok(Box::new(DataHandle{internal: fsh.unwrap()}))
25
+        Ok(Box::new(DataHandle { internal: fsh.unwrap() }))
22 26
     }
23 27
 
24 28
     fn method(&self) -> &str {
@@ -31,7 +35,7 @@ pub struct DataHandle<'a> {
31 35
 }
32 36
 
33 37
 impl<'a> Transmit for DataHandle<'a> {
34
-    fn transmit(&mut self, send: &[u8], buf: &mut[u8]) -> Result<usize, pcsc::Error> {
38
+    fn transmit(&mut self, send: &[u8], buf: &mut [u8]) -> Result<usize, pcsc::Error> {
35 39
         self.internal.transmit(send, buf)
36 40
     }
37 41
 }
@@ -48,11 +52,12 @@ impl<'a> FileSystemHandle<'a> for DataHandle<'a> {
48 52
                     scan_update((i << 8) | j);
49 53
                 }
50 54
                 let res = try!(self.transmit_apdu(0x00, 0xca, i as u8, j as u8, &[], 0x100));
51
-                const IGNORE_SW: &'static[&'static[u8]] = &[&[0x6a, 0x88], &[0x6a, 0x86], &[0x6a, 0x82]];
52
-                if IGNORE_SW.contains(&&res[res.len()-2..]) {
55
+                const IGNORE_SW: &'static [&'static [u8]] =
56
+                    &[&[0x6a, 0x88], &[0x6a, 0x86], &[0x6a, 0x82]];
57
+                if IGNORE_SW.contains(&&res[res.len() - 2..]) {
53 58
                     continue;
54 59
                 }
55
-                if res[res.len()-2] != 0x6c {
60
+                if res[res.len() - 2] != 0x6c {
56 61
                     if let Err(e) = try_sw(&res[..]) {
57 62
                         warn!("Error during recursive scan: {}. Continuing...", e);
58 63
                         continue;
@@ -79,6 +84,10 @@ impl<'a> FileSystemHandle<'a> for DataHandle<'a> {
79 84
         self.internal.is_df(file)
80 85
     }
81 86
 
82
-    fn current_df(&self) -> &[u8] { self.internal.current_df() }
83
-    fn class(&self, _: Option<bool>) -> &str { "data" }
87
+    fn current_df(&self) -> &[u8] {
88
+        self.internal.current_df()
89
+    }
90
+    fn class(&self, _: Option<bool>) -> &str {
91
+        "data"
92
+    }
84 93
 }

+ 15
- 6
src/fs/dummy.rs View File

@@ -5,10 +5,15 @@ use pcsclite::Transmit;
5 5
 pub struct DummyHandleFactory;
6 6
 
7 7
 impl FileSystemHandleFactory for DummyHandleFactory {
8
-    fn has_required_capabilities(&self, _: Capabilities) -> bool { true }
8
+    fn has_required_capabilities(&self, _: Capabilities) -> bool {
9
+        true
10
+    }
9 11
 
10
-    fn create<'a>(&self, handle: &'a mut Transmit, _: Capabilities) -> Result<Box<FileSystemHandle<'a> + 'a>, Error> {
11
-        Ok(Box::new(DummyHandle{handle: handle}))
12
+    fn create<'a>(&self,
13
+                  handle: &'a mut Transmit,
14
+                  _: Capabilities)
15
+                  -> Result<Box<FileSystemHandle<'a> + 'a>, Error> {
16
+        Ok(Box::new(DummyHandle { handle: handle }))
12 17
     }
13 18
 
14 19
     fn method(&self) -> &str {
@@ -21,7 +26,7 @@ pub struct DummyHandle<'a> {
21 26
 }
22 27
 
23 28
 impl<'a> Transmit for DummyHandle<'a> {
24
-    fn transmit(&mut self, send: &[u8], buf: &mut[u8]) -> Result<usize, pcsc::Error> {
29
+    fn transmit(&mut self, send: &[u8], buf: &mut [u8]) -> Result<usize, pcsc::Error> {
25 30
         self.handle.transmit(send, buf)
26 31
     }
27 32
 }
@@ -47,6 +52,10 @@ impl<'a> FileSystemHandle<'a> for DummyHandle<'a> {
47 52
         }
48 53
     }
49 54
 
50
-    fn current_df(&self) -> &[u8] { &[] }
51
-    fn class(&self, _: Option<bool>) -> &str { "dummy" }
55
+    fn current_df(&self) -> &[u8] {
56
+        &[]
57
+    }
58
+    fn class(&self, _: Option<bool>) -> &str {
59
+        "dummy"
60
+    }
52 61
 }

+ 30
- 15
src/fs/efdf.rs View File

@@ -1,4 +1,5 @@
1
-use fs::{FileSystemHandleFactory, FileSystemHandle, Capability, Capabilities, Error, try_sw, scan_start, scan_update, scan_end, found_file};
1
+use fs::{FileSystemHandleFactory, FileSystemHandle, Capability, Capabilities, Error, try_sw,
2
+         scan_start, scan_update, scan_end, found_file};
2 3
 use pcsclite as pcsc;
3 4
 use pcsclite::Transmit;
4 5
 
@@ -9,7 +10,10 @@ impl FileSystemHandleFactory for EFDFHandleFactory {
9 10
         c.has(Capability::SelectEFDF) && c.has(Capability::SelectDF) && c.has(Capability::SelectMF)
10 11
     }
11 12
 
12
-    fn create<'a>(&self, handle: &'a mut Transmit, caps: Capabilities) -> Result<Box<FileSystemHandle<'a> + 'a>, Error> {
13
+    fn create<'a>(&self,
14
+                  handle: &'a mut Transmit,
15
+                  caps: Capabilities)
16
+                  -> Result<Box<FileSystemHandle<'a> + 'a>, Error> {
13 17
         let p2 = if caps.has(Capability::ReturnNothing) {
14 18
             0x0c
15 19
         } else if caps.has(Capability::ReturnFCI) {
@@ -21,7 +25,11 @@ impl FileSystemHandleFactory for EFDFHandleFactory {
21 25
         } else {
22 26
             unreachable!()
23 27
         };
24
-        Ok(Box::new(EFDFHandle{handle: handle, current_df: Vec::new(), p2: p2}))
28
+        Ok(Box::new(EFDFHandle {
29
+            handle: handle,
30
+            current_df: Vec::new(),
31
+            p2: p2,
32
+        }))
25 33
     }
26 34
 
27 35
     fn method(&self) -> &str {
@@ -36,7 +44,7 @@ pub struct EFDFHandle<'a> {
36 44
 }
37 45
 
38 46
 impl<'a> Transmit for EFDFHandle<'a> {
39
-    fn transmit(&mut self, send: &[u8], buf: &mut[u8]) -> Result<usize, pcsc::Error> {
47
+    fn transmit(&mut self, send: &[u8], buf: &mut [u8]) -> Result<usize, pcsc::Error> {
40 48
         self.handle.transmit(send, buf)
41 49
     }
42 50
 }
@@ -52,16 +60,14 @@ impl<'a> FileSystemHandle<'a> for EFDFHandle<'a> {
52 60
                     first = true;
53 61
                     scan_update((i << 8) | j);
54 62
                 }
55
-                if (i, j) == (0x00, 0x00)
56
-                        || (i, j) == (0x3F, 0x00)
57
-                        || (i, j) == (0x3F, 0xFF)
58
-                        || (i, j) == (0xFF, 0xFF)
59
-                        || (i, j) == (0x7F, 0xFF) {
63
+                if (i, j) == (0x00, 0x00) || (i, j) == (0x3F, 0x00) || (i, j) == (0x3F, 0xFF) ||
64
+                   (i, j) == (0xFF, 0xFF) ||
65
+                   (i, j) == (0x7F, 0xFF) {
60 66
                     continue;
61 67
                 }
62 68
                 let p2 = self.p2;
63 69
                 let res = try!(self.transmit_apdu(0x00, 0xa4, 0x00, p2, &[i as u8, j as u8], 0x00));
64
-                if &res[res.len()-2..] == &[0x6a, 0x82] {
70
+                if &res[res.len() - 2..] == &[0x6a, 0x82] {
65 71
                     continue;
66 72
                 }
67 73
                 let mut fpath = self.current_df.clone();
@@ -71,7 +77,7 @@ impl<'a> FileSystemHandle<'a> for EFDFHandle<'a> {
71 77
                 }
72 78
                 try!(self.select_path(&fpath[..], true));
73 79
                 let res = try!(self.transmit_apdu(0x00, 0xa4, 0x01, p2, &[i as u8, j as u8], 0x00));
74
-                let is_df = &res[res.len()-2..] != &[0x6a, 0x82];
80
+                let is_df = &res[res.len() - 2..] != &[0x6a, 0x82];
75 81
                 try!(self.select_path(&fpath[..], true));
76 82
                 fpath.push(i as u8);
77 83
                 fpath.push(j as u8);
@@ -93,7 +99,7 @@ impl<'a> FileSystemHandle<'a> for EFDFHandle<'a> {
93 99
         self.current_df = if is_dir {
94 100
             path.to_owned()
95 101
         } else {
96
-            path[..path.len()-2].to_owned()
102
+            path[..path.len() - 2].to_owned()
97 103
         };
98 104
         Ok(())
99 105
     }
@@ -103,11 +109,20 @@ impl<'a> FileSystemHandle<'a> for EFDFHandle<'a> {
103 109
         if path.len() == 0 {
104 110
             return Ok(true);
105 111
         }
106
-        try!(self.select_path(&path[..path.len()-2], true));
107
-        Ok(try_sw(&try!(self.transmit_apdu(0x00, 0xa4, 0x01, p2, &path[path.len()-2..], 0x00))[..]).is_ok())
112
+        try!(self.select_path(&path[..path.len() - 2], true));
113
+        Ok(try_sw(&try!(self.transmit_apdu(0x00,
114
+                                           0xa4,
115
+                                           0x01,
116
+                                           p2,
117
+                                           &path[path.len() -
118
+                                                 2..],
119
+                                           0x00))[..])
120
+            .is_ok())
108 121
     }
109 122
 
110
-    fn current_df(&self) -> &[u8] { &self.current_df[..] }
123
+    fn current_df(&self) -> &[u8] {
124
+        &self.current_df[..]
125
+    }
111 126
     fn class(&self, df: Option<bool>) -> &str {
112 127
         match df {
113 128
             Some(true) => "df",

+ 118
- 71
src/fs/mod.rs View File

@@ -14,22 +14,17 @@ pub mod dummy;
14 14
 
15 15
 /// A list of factories for creating file system handles to run a recursive scan of full file
16 16
 /// identifiers.
17
-pub const FULL_FACTORIES: &'static[&'static FileSystemHandleFactory] = &[
18
-    &path::PathHandleFactory,
19
-    &efdf::EFDFHandleFactory,
20
-];
17
+pub const FULL_FACTORIES: &'static [&'static FileSystemHandleFactory] = &[&path::PathHandleFactory,
18
+                                                                          &efdf::EFDFHandleFactory];
21 19
 
22 20
 /// A list of factories for creating file system handles to find short EF identifiers.
23 21
 ///
24 22
 /// These cannot do a full recursive scan, and each path returned has an odd number of bytes, to
25 23
 /// indicate that a short EF id is used.
26
-pub const SHORT_FACTORIES: &'static[&'static FileSystemHandleFactory] = &[
27
-    &short::ShortHandleFactory,
28
-];
24
+pub const SHORT_FACTORIES: &'static [&'static FileSystemHandleFactory] =
25
+    &[&short::ShortHandleFactory];
29 26
 
30
-pub const DATA_FACTORIES: &'static[&'static FileSystemHandleFactory] = &[
31
-    &data::DataHandleFactory,
32
-];
27
+pub const DATA_FACTORIES: &'static [&'static FileSystemHandleFactory] = &[&data::DataHandleFactory];
33 28
 
34 29
 pub const DUMMY_FACTORY: &'static FileSystemHandleFactory = &dummy::DummyHandleFactory;
35 30
 
@@ -95,10 +90,9 @@ impl From<io::Error> for Error {
95 90
 }
96 91
 
97 92
 fn try_sw(rapdu: &[u8]) -> Result<(&[u8], &[u8]), Error> {
98
-    const ERR_SW1: &'static [u16] = &[
99
-        0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
100
-        0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f];
101
-    let sw = &rapdu[rapdu.len()-2..];
93
+    const ERR_SW1: &'static [u16] = &[0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d,
94
+                                      0x6e, 0x6f];
95
+    let sw = &rapdu[rapdu.len() - 2..];
102 96
     let sw = (sw[0] as u16) << 8 | sw[1] as u16;
103 97
     if sw == 0x6982 {
104 98
         Err(Error::AccessDenied)
@@ -115,13 +109,16 @@ fn try_sw(rapdu: &[u8]) -> Result<(&[u8], &[u8]), Error> {
115 109
     } else if ERR_SW1.contains(&(sw >> 8)) {
116 110
         Err(Error::unknown_error(sw))
117 111
     } else {
118
-        Ok((&rapdu[..rapdu.len()-2], &rapdu[rapdu.len()-2..]))
112
+        Ok((&rapdu[..rapdu.len() - 2], &rapdu[rapdu.len() - 2..]))
119 113
     }
120 114
 }
121 115
 
122 116
 pub trait FileSystemHandleFactory {
123 117
     fn has_required_capabilities(&self, c: Capabilities) -> bool;
124
-    fn create<'a>(&self, handle: &'a mut pcsc::Transmit, cap: Capabilities) -> Result<Box<FileSystemHandle<'a> + 'a>, Error>;
118
+    fn create<'a>(&self,
119
+                  handle: &'a mut pcsc::Transmit,
120
+                  cap: Capabilities)
121
+                  -> Result<Box<FileSystemHandle<'a> + 'a>, Error>;
125 122
     fn method(&self) -> &str;
126 123
 }
127 124
 
@@ -134,21 +131,26 @@ pub trait FileSystemHandle<'a>: pcsc::Transmit {
134 131
 
135 132
     fn extract_data(&mut self, file: &[u8], outdir: &Path) -> Result<(), Error> {
136 133
         let mut path = PathBuf::from(outdir);
137
-        let (file, obj) = (&file[..file.len()-2], &file[file.len()-2..]);
134
+        let (file, obj) = (&file[..file.len() - 2], &file[file.len() - 2..]);
138 135
         let df = try!(self.is_df(file));
139 136
         if file.len() > 0 {
140
-            for name in file.chunks(2).take(file.len()/2 - 1) {
137
+            for name in file.chunks(2).take(file.len() / 2 - 1) {
141 138
                 path.push(format!("{}", name.to_hex()));
142 139
             }
143
-            path.push(format!("{}", &file[file.len()-2..].to_hex()));
140
+            path.push(format!("{}", &file[file.len() - 2..].to_hex()));
144 141
         }
145 142
         path.push(format!("[{}]", obj.to_hex()));
146 143
         try!(create_dir_all(path.parent().unwrap()));
147 144
         let mut f = try!(File::create(path));
148 145
         try!(self.select_path(file, df));
149 146
         let mut rapdu = try!(self.transmit_apdu(0x00, 0xca, obj[0], obj[1], &[], 0x100));
150
-        if rapdu[rapdu.len()-2] == 0x6c {
151
-            rapdu = try!(self.transmit_apdu(0x00, 0xca, obj[0], obj[1], &[], rapdu[rapdu.len()-1] as usize));
147
+        if rapdu[rapdu.len() - 2] == 0x6c {
148
+            rapdu = try!(self.transmit_apdu(0x00,
149
+                                            0xca,
150
+                                            obj[0],
151
+                                            obj[1],
152
+                                            &[],
153
+                                            rapdu[rapdu.len() - 1] as usize));
152 154
         }
153 155
         let res = try!(try_sw(&rapdu[..]));
154 156
         try!(writeln!(f, "type: data object\n"));
@@ -161,8 +163,8 @@ pub trait FileSystemHandle<'a>: pcsc::Transmit {
161 163
             try!(self.select_path(file, false));
162 164
             0x00
163 165
         } else {
164
-            try!(self.select_path(&file[..file.len()-1], true));
165
-            file[file.len()-1]
166
+            try!(self.select_path(&file[..file.len() - 1], true));
167
+            file[file.len() - 1]
166 168
         };
167 169
         let mut path = PathBuf::from(outdir);
168 170
         for name in file.chunks(2) {
@@ -179,7 +181,7 @@ pub trait FileSystemHandle<'a>: pcsc::Transmit {
179 181
                 0x80 | shortef
180 182
             };
181 183
             let mut rapdu = try!(self.transmit_apdu(0x00, 0xb0, p1, 0x00, &[], 0xffff));
182
-            if rapdu[rapdu.len()-2] == 0x6c {
184
+            if rapdu[rapdu.len() - 2] == 0x6c {
183 185
                 rapdu = try!(self.transmit_apdu(0x00, 0xb0, p1, 0x00, &[], rapdu[rapdu.len()-1] as usize));
184 186
             }
185 187
             let res = try_sw(&rapdu[..]);
@@ -213,8 +215,13 @@ pub trait FileSystemHandle<'a>: pcsc::Transmit {
213 215
             // try read record
214 216
             for i in 1.. {
215 217
                 let mut rapdu = try!(self.transmit_apdu(0x00, 0xb2, i as u8, (shortef << 3) | 0x04, &[], 0xffff));
216
-                if rapdu[rapdu.len()-2] == 0x6c {
217
-                    rapdu = try!(self.transmit_apdu(0x00, 0xb2, i as u8, (shortef << 3) | 0x04, &[], rapdu[rapdu.len()-1] as usize));
218
+                if rapdu[rapdu.len() - 2] == 0x6c {
219
+                    rapdu = try!(self.transmit_apdu(0x00,
220
+                                                    0xb2,
221
+                                                    i as u8,
222
+                                                    (shortef << 3) | 0x04,
223
+                                                    &[],
224
+                                                    rapdu[rapdu.len() - 1] as usize));
218 225
                 }
219 226
                 let res = try_sw(&rapdu[..]);
220 227
                 match res {
@@ -261,36 +268,66 @@ pub trait FileSystemHandle<'a>: pcsc::Transmit {
261 268
         Ok(())
262 269
     }
263 270
 
264
-    fn scan_paths(&mut self, paths: &[(&[u8], bool)], af: &[u8], f: &mut Write, flog: &mut Write) -> Result<Vec<(Vec<u8>, bool)>, Error> {
271
+    fn scan_paths(&mut self,
272
+                  paths: &[(&[u8], bool)],
273
+                  af: &[u8],
274
+                  f: &mut Write,
275
+                  flog: &mut Write)
276
+                  -> Result<Vec<(Vec<u8>, bool)>, Error> {
265 277
         let mut res = Vec::new();
266 278
         for (i, &(path, is_df)) in paths.iter().enumerate() {
267 279
             let _ = writeln!(stderr(), ":: Scanning path {}/{}...", i + 1, paths.len());
268 280
             try!(self.select_path(path, is_df));
269 281
             let new = try!(self.scan_current_df());
270 282
             for &(ref file, df) in new.iter() {
271
-                try!(writeln!(f, "{}::{}::{}", self.class(Some(df)), af.to_hex(), file.to_hex()));
283
+                try!(writeln!(f,
284
+                              "{}::{}::{}",
285
+                              self.class(Some(df)),
286
+                              af.to_hex(),
287
+                              file.to_hex()));
272 288
             }
273 289
             res.extend(new);
274
-            try!(writeln!(flog, "scanned-{} {}::{}", self.class(None), af.to_hex(), path.to_hex()));
290
+            try!(writeln!(flog,
291
+                          "scanned-{} {}::{}",
292
+                          self.class(None),
293
+                          af.to_hex(),
294
+                          path.to_hex()));
275 295
         }
276 296
         Ok(res)
277 297
     }
278 298
 
279
-    fn rec_scan(&mut self, filter_root: bool, filter_dup: bool, af: &[u8], paths: Vec<Vec<u8>>, f: &mut Write, flog: &mut Write) -> Result<Vec<(Vec<u8>, bool)>, Error> {
280
-        let mut files = try!(paths.into_iter().map(|p| {
281
-            let df = try!(self.is_df(&p[..]));
282
-            Ok((p, df))
283
-        }).collect::<Result<Vec<_>, Error>>());
284
-        let mut dirs = files.iter().filter(|&&(_, df)| df)
299
+    fn rec_scan(&mut self,
300
+                filter_root: bool,
301
+                filter_dup: bool,
302
+                af: &[u8],
303
+                paths: Vec<Vec<u8>>,
304
+                f: &mut Write,
305
+                flog: &mut Write)
306
+                -> Result<Vec<(Vec<u8>, bool)>, Error> {
307
+        let mut files = try!(paths.into_iter()
308
+            .map(|p| {
309
+                let df = try!(self.is_df(&p[..]));
310
+                Ok((p, df))
311
+            })
312
+            .collect::<Result<Vec<_>, Error>>());
313
+        let mut dirs = files.iter()
314
+            .filter(|&&(_, df)| df)
285 315
             .map(|&(ref p, _)| p.to_owned())
286 316
             .collect::<Vec<_>>();
287 317
         for &(ref file, df) in files.iter() {
288
-            try!(writeln!(f, "{}::{}::{}", self.class(Some(df)), af.to_hex(), file.to_hex()));
318
+            try!(writeln!(f,
319
+                          "{}::{}::{}",
320
+                          self.class(Some(df)),
321
+                          af.to_hex(),
322
+                          file.to_hex()));
289 323
         }
290 324
         let mut index = 0;
291 325
         let mut rootdirs = vec![];
292 326
         while let Some(dir) = dirs.pop() {
293
-            let _ = writeln!(stderr(), ":: Scanning DF {}/{}...", index + 1, index + 1 + dirs.len());
327
+            let _ = writeln!(stderr(),
328
+                             ":: Scanning DF {}/{}...",
329
+                             index + 1,
330
+                             index + 1 + dirs.len());
294 331
             if dir.len() > 0 {
295 332
                 try!(self.select_path(&dir[..], true));
296 333
             }
@@ -299,19 +336,28 @@ pub trait FileSystemHandle<'a>: pcsc::Transmit {
299 336
                 if df {
300 337
                     if dir.len() == 0 {
301 338
                         rootdirs.push(file.clone());
302
-                    } else if filter_root && rootdirs.iter().any(|f| &f[..] == &file[file.len()-2..]) {
339
+                    } else if filter_root && rootdirs.iter().any(|f| &f[..] == &file[file.len() - 2..]) {
303 340
                         continue;
304
-                    } else if filter_dup && &file[file.len()-2..] == &file[file.len()-4..file.len()-2] {
341
+                    } else if filter_dup &&
342
+                       &file[file.len() - 2..] == &file[file.len() - 4..file.len() - 2] {
305 343
                         continue;
306 344
                     }
307 345
                     try!(writeln!(flog, "dir-found {}::{}", af.to_hex(), file.to_hex()));
308 346
                     dirs.push(file.clone());
309 347
                 }
310
-                try!(writeln!(f, "{}::{}::{}", self.class(Some(df)), af.to_hex(), file.to_hex()));
348
+                try!(writeln!(f,
349
+                              "{}::{}::{}",
350
+                              self.class(Some(df)),
351
+                              af.to_hex(),
352
+                              file.to_hex()));
311 353
                 files.push((file, df));
312 354
             }
313 355
             index += 1;
314
-            try!(writeln!(flog, "scanned-{} {}::{}", self.class(None), af.to_hex(), dir.to_hex()));
356
+            try!(writeln!(flog,
357
+                          "scanned-{} {}::{}",
358
+                          self.class(None),
359
+                          af.to_hex(),
360
+                          dir.to_hex()));
315 361
         }
316 362
         Ok(files)
317 363
     }
@@ -341,23 +387,23 @@ pub enum Capability {
341 387
 impl Capability {
342 388
     fn raw(self) -> usize {
343 389
         match self {
344
-            Capability::SelectMF            => 0x00000001,
345
-            Capability::SelectAF            => 0x00000002,
346
-            Capability::SelectEFDF          => 0x00000004,
347
-            Capability::SelectEF            => 0x00000008,
348
-            Capability::SelectDF            => 0x00000010,
349
-            Capability::SelectParent        => 0x00000020,
350
-            Capability::SelectPath          => 0x00000040,
351
-            Capability::ReturnFCI           => 0x00000080,
352
-            Capability::ReturnFCP           => 0x00000100,
353
-            Capability::ReturnFMD           => 0x00000200,
354
-            Capability::ReturnNothing       => 0x00000400,
390
+            Capability::SelectMF => 0x00000001,
391
+            Capability::SelectAF => 0x00000002,
392
+            Capability::SelectEFDF => 0x00000004,
393
+            Capability::SelectEF => 0x00000008,
394
+            Capability::SelectDF => 0x00000010,
395
+            Capability::SelectParent => 0x00000020,
396
+            Capability::SelectPath => 0x00000040,
397
+            Capability::ReturnFCI => 0x00000080,
398
+            Capability::ReturnFCP => 0x00000100,
399
+            Capability::ReturnFMD => 0x00000200,
400
+            Capability::ReturnNothing => 0x00000400,
355 401
             Capability::ReadBinaryCurrentEF => 0x00000800,
356
-            Capability::ReadBinaryLongEF    => 0x00001000,
357
-            Capability::ReadBinaryShortEF   => 0x00002000,
402
+            Capability::ReadBinaryLongEF => 0x00001000,
403
+            Capability::ReadBinaryShortEF => 0x00002000,
358 404
             Capability::ReadRecordCurrentEF => 0x00004000,
359
-            Capability::ReadRecordShortEF   => 0x00008000,
360
-            Capability::ReadData            => 0x00010000,
405
+            Capability::ReadRecordShortEF => 0x00008000,
406
+            Capability::ReadData => 0x00010000,
361 407
         }
362 408
     }
363 409
 
@@ -391,16 +437,14 @@ pub struct Capabilities(usize);
391 437
 /// Tests if a result apdu indicates that the issued command is supported
392 438
 /// for some input.
393 439
 fn test_result(res: &[u8]) -> bool {
394
-    const COMMAND_NOT_SUPPORTED: &'static [&'static [u8]] = &[
395
-        &[0x6f, 0x00],
396
-        &[0x6f, 0x00],
397
-        &[0x6e, 0x00],
398
-        &[0x6d, 0x00],
399
-        &[0x6b, 0x00],
400
-        &[0x6a, 0x86],
401
-        &[0x6a, 0x81],
402
-        &[0x67, 0x00],
403
-    ];
440
+    const COMMAND_NOT_SUPPORTED: &'static [&'static [u8]] = &[&[0x6f, 0x00],
441
+                                                              &[0x6f, 0x00],
442
+                                                              &[0x6e, 0x00],
443
+                                                              &[0x6d, 0x00],
444
+                                                              &[0x6b, 0x00],
445
+                                                              &[0x6a, 0x86],
446
+                                                              &[0x6a, 0x81],
447
+                                                              &[0x67, 0x00]];
404 448
 
405 449
     !COMMAND_NOT_SUPPORTED.contains(&res)
406 450
 }
@@ -414,9 +458,13 @@ impl Capabilities {
414 458
         let mut ret = Self::new();
415 459
         // Try all p1 and p2 values for select.
416 460
         // 0xff as p1 is a dummy value for select mf.
417
-        const P1AF: &'static[u8] = &[0x00, 0x01, 0x02, 0x03, 0x04, 0x08, 0xff];
418
-        const P1NOAF: &'static[u8] = &[0x00, 0x01, 0x02, 0x03, 0x08, 0xff];
419
-        let p1s = if test_af { P1AF } else { P1NOAF };
461
+        const P1AF: &'static [u8] = &[0x00, 0x01, 0x02, 0x03, 0x04, 0x08, 0xff];
462
+        const P1NOAF: &'static [u8] = &[0x00, 0x01, 0x02, 0x03, 0x08, 0xff];
463
+        let p1s = if test_af {
464
+            P1AF
465
+        } else {
466
+            P1NOAF
467
+        };
420 468
         let p2s = &[0x00, 0x04, 0x08, 0x0c];
421 469
         for p1 in p1s {
422 470
             for p2 in p2s {
@@ -425,8 +473,7 @@ impl Capabilities {
425 473
                 } else {
426 474
                     try!(handle.transmit_apdu(0x00, 0xa4, *p1, *p2, &[0x74, 0x37], 0x00))
427 475
                 };
428
-                if !test_result(&res[..]) ||
429
-                        (p1 == &0xff && &res[..] == &[0x6a, 0x82][..]) {
476
+                if !test_result(&res[..]) || (p1 == &0xff && &res[..] == &[0x6a, 0x82][..]) {
430 477
                     continue;
431 478
                 }
432 479
                 match *p1 {

+ 33
- 26
src/fs/path.rs View File

@@ -1,4 +1,5 @@
1
-use fs::{FileSystemHandleFactory, FileSystemHandle, Capability, Capabilities, Error, try_sw, scan_start, scan_update, scan_end, is_df_fcp, found_file};
1
+use fs::{FileSystemHandleFactory, FileSystemHandle, Capability, Capabilities, Error, try_sw,
2
+         scan_start, scan_update, scan_end, is_df_fcp, found_file};
2 3
 use pcsclite as pcsc;
3 4
 use pcsclite::Transmit;
4 5
 use rustc_serialize::hex::ToHex;
@@ -10,8 +11,14 @@ impl FileSystemHandleFactory for PathHandleFactory {
10 11
         c.has(Capability::SelectPath) && c.has(Capability::ReturnFCP) && c.has(Capability::SelectMF)
11 12
     }
12 13
 
13
-    fn create<'a>(&self, handle: &'a mut Transmit, _: Capabilities) -> Result<Box<FileSystemHandle<'a> + 'a>, Error> {
14
-        Ok(Box::new(PathHandle{handle: handle, current_df: Vec::new()}))
14
+    fn create<'a>(&self,
15
+                  handle: &'a mut Transmit,
16
+                  _: Capabilities)
17
+                  -> Result<Box<FileSystemHandle<'a> + 'a>, Error> {
18
+        Ok(Box::new(PathHandle {
19
+            handle: handle,
20
+            current_df: Vec::new(),
21
+        }))
15 22
     }
16 23
 
17 24
     fn method(&self) -> &str {
@@ -25,7 +32,7 @@ pub struct PathHandle<'a> {
25 32
 }
26 33
 
27 34
 impl<'a> Transmit for PathHandle<'a> {
28
-    fn transmit(&mut self, send: &[u8], buf: &mut[u8]) -> Result<usize, pcsc::Error> {
35
+    fn transmit(&mut self, send: &[u8], buf: &mut [u8]) -> Result<usize, pcsc::Error> {
29 36
         self.handle.transmit(send, buf)
30 37
     }
31 38
 }
@@ -46,32 +53,31 @@ impl<'a> FileSystemHandle<'a> for PathHandle<'a> {
46 53
                     first = true;
47 54
                     scan_update((i << 8) | j);
48 55
                 }
49
-                if (i, j) == (0x00, 0x00)
50
-                        || (i, j) == (0x3F, 0x00)
51
-                        || (i, j) == (0x3F, 0xFF)
52
-                        || (i, j) == (0xFF, 0xFF)
53
-                        || (i, j) == (0x7F, 0xFF) {
56
+                if (i, j) == (0x00, 0x00) || (i, j) == (0x3F, 0x00) || (i, j) == (0x3F, 0xFF) ||
57
+                   (i, j) == (0xFF, 0xFF) ||
58
+                   (i, j) == (0x7F, 0xFF) {
54 59
                     continue;
55 60
                 }
56
-                data[l-2] = i as u8;
57
-                data[l-1] = j as u8;
61
+                data[l - 2] = i as u8;
62
+                data[l - 1] = j as u8;
58 63
                 let res = try!(self.transmit_apdu(0x00, 0xa4, 0x08, 0x04, &data[..], 0x100));
59
-                if &res[res.len()-2..] == &[0x6a, 0x82] {
64
+                if &res[res.len() - 2..] == &[0x6a, 0x82] {
60 65
                     continue;
61
-                } else if [&[0x62, 0x83][..], &[0x69, 0x82]].contains(&&res[res.len()-2..]) {
66
+                } else if [&[0x62, 0x83][..], &[0x69, 0x82]].contains(&&res[res.len() - 2..]) {
62 67
                 } else if let Err(e) = try_sw(&res[..]) {
63 68
                     warn!("Error during recursive scan: {}. Continuing...", e);
64 69
                     continue;
65 70
                 }
66
-                let df = if &res[res.len()-2..] == &[0x90, 0x00] {
67
-                    is_df_fcp(&res[..res.len()-2])
68
-                } else if res[res.len()-2] != 0x61 {
71
+                let df = if &res[res.len() - 2..] == &[0x90, 0x00] {
72
+                    is_df_fcp(&res[..res.len() - 2])
73
+                } else if res[res.len() - 2] != 0x61 {
69 74
                     warn!("Error determining if {} is DF: {}",
70 75
                           data.to_hex(),
71 76
                           Error::unexpected_result("expected response FCP template", res));
72 77
                     true
73 78
                 } else {
74
-                    let res = try!(self.transmit_apdu(0x00, 0xc0, 0x00, 0x00, &[], res[1] as usize));
79
+                    let res =
80
+                        try!(self.transmit_apdu(0x00, 0xc0, 0x00, 0x00, &[], res[1] as usize));
75 81
                     let (fcp, _) = match try_sw(&res[..]) {
76 82
                         Ok(v) => v,
77 83
                         Err(e) => {
@@ -97,10 +103,9 @@ impl<'a> FileSystemHandle<'a> for PathHandle<'a> {
97 103
             try!(self.transmit_apdu(0x00, 0xa4, 0x08, 0x04, path, 0x00))
98 104
         };
99 105
         try!(try_sw(&res[..]));
100
-        if &res[res.len()-2..] == &[0x90, 0x00] {
101
-        } else if res[res.len()-2] != 0x61 {
102
-            return Err(Error::unexpected_result(
103
-                "expected response FCP template", res));
106
+        if &res[res.len() - 2..] == &[0x90, 0x00] {
107
+        } else if res[res.len() - 2] != 0x61 {
108
+            return Err(Error::unexpected_result("expected response FCP template", res));
104 109
         } else {
105 110
             let res = try!(self.transmit_apdu(0x00, 0xc0, 0x00, 0x00, &[], res[1] as usize));
106 111
             try!(try_sw(&res[..]));
@@ -108,7 +113,7 @@ impl<'a> FileSystemHandle<'a> for PathHandle<'a> {
108 113
         if is_dir {
109 114
             self.current_df = path.to_owned();
110 115
         } else {
111
-            self.current_df = path[..path.len()-2].to_owned();
116
+            self.current_df = path[..path.len() - 2].to_owned();
112 117
         }
113 118
         Ok(())
114 119
     }
@@ -119,9 +124,9 @@ impl<'a> FileSystemHandle<'a> for PathHandle<'a> {
119 124
         }
120 125
         let res = try!(self.transmit_apdu(0x00, 0xa4, 0x08, 0x04, &path[..], 0x100));
121 126
         try!(try_sw(&res[..]));
122
-        if &res[res.len()-2..] == &[0x90, 0x00] {
123
-            Ok(is_df_fcp(&res[..res.len()-2]))
124
-        } else if res[res.len()-2] != 0x61 {
127
+        if &res[res.len() - 2..] == &[0x90, 0x00] {
128
+            Ok(is_df_fcp(&res[..res.len() - 2]))
129
+        } else if res[res.len() - 2] != 0x61 {
125 130
             warn!("Error determining if {} is DF: {}",
126 131
                   path.to_hex(),
127 132
                   Error::unexpected_result("expected response FCP template", res));
@@ -133,7 +138,9 @@ impl<'a> FileSystemHandle<'a> for PathHandle<'a> {
133 138
         }
134 139
     }
135 140
 
136
-    fn current_df(&self) -> &[u8] { &self.current_df[..] }
141
+    fn current_df(&self) -> &[u8] {
142
+        &self.current_df[..]
143
+    }
137 144
     fn class(&self, df: Option<bool>) -> &str {
138 145
         match df {
139 146
             Some(true) => "df",

+ 32
- 16
src/fs/short.rs View File

@@ -1,4 +1,5 @@
1
-use fs::{FileSystemHandleFactory, FileSystemHandle, Capabilities, Error, Capability, FULL_FACTORIES, DUMMY_FACTORY, try_sw, found_file};
1
+use fs::{FileSystemHandleFactory, FileSystemHandle, Capabilities, Error, Capability,
2
+         FULL_FACTORIES, DUMMY_FACTORY, try_sw, found_file};
2 3
 use pcsclite as pcsc;
3 4
 use pcsclite::Transmit;
4 5
 
@@ -9,7 +10,10 @@ impl FileSystemHandleFactory for ShortHandleFactory {
9 10
         c.has(Capability::ReadBinaryShortEF) || c.has(Capability::ReadRecordShortEF)
10 11
     }
11 12
 
12
-    fn create<'a>(&self, handle: &'a mut Transmit, caps: Capabilities) -> Result<Box<FileSystemHandle<'a> + 'a>, Error> {
13
+    fn create<'a>(&self,
14
+                  handle: &'a mut Transmit,
15
+                  caps: Capabilities)
16
+                  -> Result<Box<FileSystemHandle<'a> + 'a>, Error> {
13 17
         // Find a full path factory that works, and use that. If none are available, us a dummy.
14 18
         let mut fsh = None;
15 19
         for factory in FULL_FACTORIES.iter().chain(&[DUMMY_FACTORY]) {
@@ -18,7 +22,10 @@ impl FileSystemHandleFactory for ShortHandleFactory {
18 22
                 break;
19 23
             }
20 24
         }
21
-        Ok(Box::new(ShortHandle{internal: fsh.unwrap(), caps: caps}))
25
+        Ok(Box::new(ShortHandle {
26
+            internal: fsh.unwrap(),
27
+            caps: caps,
28
+        }))
22 29
     }
23 30
 
24 31
     fn method(&self) -> &str {
@@ -32,7 +39,7 @@ pub struct ShortHandle<'a> {
32 39
 }
33 40
 
34 41
 impl<'a> Transmit for ShortHandle<'a> {
35
-    fn transmit(&mut self, send: &[u8], buf: &mut[u8]) -> Result<usize, pcsc::Error> {
42
+    fn transmit(&mut self, send: &[u8], buf: &mut [u8]) -> Result<usize, pcsc::Error> {
36 43
         self.internal.transmit(send, buf)
37 44
     }
38 45
 }
@@ -44,28 +51,33 @@ impl<'a> FileSystemHandle<'a> for ShortHandle<'a> {
44 51
             if self.caps.has(Capability::ReadBinaryShortEF) {
45 52
                 let res = try!(self.transmit_apdu(0x00, 0xb0, 0x80 | i, 0x00, &[], 0x00));
46 53
                 match try_sw(&res[..]) {
47
-                    Ok(_) | Err(Error::WrongLe(_, _)) => {
54
+                    Ok(_) |
55
+                    Err(Error::WrongLe(_, _)) => {
48 56
                         ret.push(i);
49 57
                     }
50
-                    _ => {},
58
+                    _ => {}
51 59
                 }
52 60
             }
53 61
             if self.caps.has(Capability::ReadRecordShortEF) {
54 62
                 let res = try!(self.transmit_apdu(0x00, 0xb2, 0x01, (i << 3) | 0x04, &[], 0x00));
55 63
                 match try_sw(&res[..]) {
56
-                    Ok(_) | Err(Error::RecordNotFound) | Err(Error::WrongLe(_, _)) => {
64
+                    Ok(_) |
65
+                    Err(Error::RecordNotFound) |
66
+                    Err(Error::WrongLe(_, _)) => {
57 67
                         ret.push(i);
58 68
                     }
59
-                    _ => {},
69
+                    _ => {}
60 70
                 }
61 71
             }
62 72
         }
63
-        Ok(ret.into_iter().map(|i| {
64
-            let mut v = self.current_df().to_owned();
65
-            v.push(i);
66
-            found_file(&v[..], false, false);
67
-            (v, false)
68
-        }).collect())
73
+        Ok(ret.into_iter()
74
+            .map(|i| {
75
+                let mut v = self.current_df().to_owned();
76
+                v.push(i);
77
+                found_file(&v[..], false, false);
78
+                (v, false)
79
+            })
80
+            .collect())
69 81
     }
70 82
 
71 83
     fn select_path(&mut self, path: &[u8], is_dir: bool) -> Result<(), Error> {
@@ -76,6 +88,10 @@ impl<'a> FileSystemHandle<'a> for ShortHandle<'a> {
76 88
         self.internal.is_df(file)
77 89
     }
78 90
 
79
-    fn current_df(&self) -> &[u8] { self.internal.current_df() }
80
-    fn class(&self, _: Option<bool>) -> &str { "short" }
91
+    fn current_df(&self) -> &[u8] {
92
+        self.internal.current_df()
93
+    }
94
+    fn class(&self, _: Option<bool>) -> &str {
95
+        "short"
96
+    }
81 97
 }

+ 8
- 4
src/main.rs View File

@@ -18,15 +18,16 @@ fn print_usage(program: &str) -> ! {
18 18
     println!("Usage: {} COMMAND [...]\n", program);
19 19
     println!("Supported commands:\n");
20 20
     println!("extract\nscan\n");
21
-    println!("Use '{} help COMMAND' for help on the specified subcommand.", program);
21
+    println!("Use '{} help COMMAND' for help on the specified subcommand.",
22
+             program);
22 23
     exit(1);
23 24
 }
24 25
 
25 26
 fn log_format(r: &log::LogRecord) -> String {
26 27
     let prefix = match r.level() {
27 28
         log::LogLevel::Error => "!!!! ",
28
-        log::LogLevel::Warn =>  "!! ",
29
-        log::LogLevel::Info =>  "",
29
+        log::LogLevel::Warn => "!! ",
30
+        log::LogLevel::Info => "",
30 31
         log::LogLevel::Debug => "? ",
31 32
         log::LogLevel::Trace => ">> ",
32 33
     };
@@ -34,7 +35,10 @@ fn log_format(r: &log::LogRecord) -> String {
34 35
 }
35 36
 
36 37
 fn main() {
37
-    if let Err(e) = env_logger::LogBuilder::new().format(log_format).filter(None, log::LogLevelFilter::Info).init() {
38
+    if let Err(e) = env_logger::LogBuilder::new()
39
+        .format(log_format)
40
+        .filter(None, log::LogLevelFilter::Info)
41
+        .init() {
38 42
         panic!("Failed to initialize global logger: {}", e);
39 43
     }
40 44
     let args = args().collect::<Vec<_>>();

+ 112
- 28
src/scan.rs View File

@@ -9,12 +9,20 @@ use std::io::Write;
9 9
 use rustc_serialize::hex::{FromHex, ToHex};
10 10
 
11 11
 fn print_usage(program: &str, command: &str, opts: &Options) -> ! {
12
-    let brief = format!("Usage: {} {} [options] FILE\n\nScans a smartcard for files and stores a list of found files in FILE.", program, command);
12
+    let brief = format!("Usage: {} {} [options] FILE\n\nScans a smartcard for files and stores a \
13
+                         list of found files in FILE.",
14
+                        program,
15
+                        command);
13 16
     print!("{}", opts.usage(&brief));
14 17
     exit(1);
15 18
 }
16 19
 
17
-fn do_data_scan<T: AsRef<[u8]>>(handle: &mut pcsc::Transmit, caps: fs::Capabilities, paths: &[(T, bool)], af: &[u8], f: &mut Write, flog: &mut Write) {
20
+fn do_data_scan<T: AsRef<[u8]>>(handle: &mut pcsc::Transmit,
21
+                                caps: fs::Capabilities,
22
+                                paths: &[(T, bool)],
23
+                                af: &[u8],
24
+                                f: &mut Write,
25
+                                flog: &mut Write) {
18 26
     let mut factory = None;
19 27
     for fact in fs::DATA_FACTORIES {
20 28
         if fact.has_required_capabilities(caps) {
@@ -25,7 +33,8 @@ fn do_data_scan<T: AsRef<[u8]>>(handle: &mut pcsc::Transmit, caps: fs::Capabilit
25 33
     let factory = match factory {
26 34
         Some(v) => v,
27 35
         None => {
28
-            warn!("No recipe for data scan with AF capabilities! ({:?})", caps.list());
36
+            warn!("No recipe for data scan with AF capabilities! ({:?})",
37
+                  caps.list());
29 38
             return;
30 39
         }
31 40
     };
@@ -44,7 +53,15 @@ fn do_data_scan<T: AsRef<[u8]>>(handle: &mut pcsc::Transmit, caps: fs::Capabilit
44 53
     }
45 54
 }
46 55
 
47
-fn do_full_id_scan(handle: &mut pcsc::Transmit, caps: fs::Capabilities, filter_root: bool, filter_dup: bool, af: &[u8], root: Vec<u8>, f: &mut Write, flog: &mut Write) -> Vec<(Vec<u8>, bool)> {
56
+fn do_full_id_scan(handle: &mut pcsc::Transmit,
57
+                   caps: fs::Capabilities,
58
+                   filter_root: bool,
59
+                   filter_dup: bool,
60
+                   af: &[u8],
61
+                   root: Vec<u8>,
62
+                   f: &mut Write,
63
+                   flog: &mut Write)
64
+                   -> Vec<(Vec<u8>, bool)> {
48 65
     let mut factory = None;
49 66
     for fact in fs::FULL_FACTORIES {
50 67
         if fact.has_required_capabilities(caps) {
@@ -55,7 +72,8 @@ fn do_full_id_scan(handle: &mut pcsc::Transmit, caps: fs::Capabilities, filter_r
55 72
     let factory = match factory {
56 73
         Some(v) => v,
57 74
         None => {
58
-            warn!("No recipe for full id scan with AF capabilities! ({:?})", caps.list());
75
+            warn!("No recipe for full id scan with AF capabilities! ({:?})",
76
+                  caps.list());
59 77
             return vec![(Vec::new(), true)];
60 78
         }
61 79
     };
@@ -77,7 +95,12 @@ fn do_full_id_scan(handle: &mut pcsc::Transmit, caps: fs::Capabilities, filter_r
77 95
     }
78 96
 }
79 97
 
80
-fn do_short_id_scan<T: AsRef<[u8]>>(handle: &mut pcsc::Transmit, caps: fs::Capabilities, dfs: &[T], af: &[u8], f: &mut Write, flog: &mut Write) {
98
+fn do_short_id_scan<T: AsRef<[u8]>>(handle: &mut pcsc::Transmit,
99
+                                    caps: fs::Capabilities,
100
+                                    dfs: &[T],
101
+                                    af: &[u8],
102
+                                    f: &mut Write,
103
+                                    flog: &mut Write) {
81 104
     let mut factory = None;
82 105
     for fact in fs::SHORT_FACTORIES {
83 106
         if fact.has_required_capabilities(caps) {
@@ -88,7 +111,8 @@ fn do_short_id_scan<T: AsRef<[u8]>>(handle: &mut pcsc::Transmit, caps: fs::Capab
88 111
     let factory = match factory {
89 112
         Some(v) => v,
90 113
         None => {
91
-            warn!("No recipe for short id scan with AF capabilities! ({:?})", caps.list());
114
+            warn!("No recipe for short id scan with AF capabilities! ({:?})",
115
+                  caps.list());
92 116
             return;
93 117
         }
94 118
     };
@@ -112,23 +136,52 @@ pub fn main(args: Vec<String>) {
112 136
     let command = args[1].clone();
113 137
 
114 138
     let mut opts = Options::new();
115
-    opts.optopt("p", "pin", "sets the verify apdu pin in hex, with the first byte being the PIN id. (e.g. 813132333435 corresponds to the APDU 00200081053132333435)", "PIN");
116
-    opts.optopt("c", "cla", "sets the cla byte to use when scanning for files. Specified as a single hex byte.", "CLA");
117
-    opts.optopt("", "apdumap", "specifies rules to rewrite apdus. Rules are comma sperated, and have the for '<ORIG CLA><ORIG INS>-><NEW CLA><NEW INS>'. Example: --apdumap 00a4->3030,00b0->3031", "RULES");
118
-    opts.optopt("r", "reader", "specifies the reader to use. Uses the first reader with the given string as part of its name.", "READER");
119
-    opts.optmulti("a", "af", "specifies one available af name in hex, and optionally a root path to start scanning from (specified in the format 'AFNAME/PATH'). This option may appear multiple times, and each indicates an af to scan. The default af is scanned if no other is specified.", "AF");
139
+    opts.optopt("p",
140
+                "pin",
141
+                "sets the verify apdu pin in hex, with the first byte being the PIN id. (e.g. \
142
+                 813132333435 corresponds to the APDU 00200081053132333435)",
143
+                "PIN");
144
+    opts.optopt("c",
145
+                "cla",
146
+                "sets the cla byte to use when scanning for files. Specified as a single hex \
147
+                 byte.",
148
+                "CLA");
149
+    opts.optopt("",
150
+                "apdumap",
151
+                "specifies rules to rewrite apdus. Rules are comma sperated, and have the for \
152
+                 '<ORIG CLA><ORIG INS>-><NEW CLA><NEW INS>'. Example: --apdumap \
153
+                 00a4->3030,00b0->3031",
154
+                "RULES");
155
+    opts.optopt("r",
156
+                "reader",
157
+                "specifies the reader to use. Uses the first reader with the given string as \
158
+                 part of its name.",
159
+                "READER");
160
+    opts.optmulti("a",
161
+                  "af",
162
+                  "specifies one available af name in hex, and optionally a root path to start \
163
+                   scanning from (specified in the format 'AFNAME/PATH'). This option may appear \
164
+                   multiple times, and each indicates an af to scan. The default af is scanned \
165
+                   if no other is specified.",
166
+                  "AF");
120 167
     // TODO: add support
121
-    //opts.optflag("", "ef-dir", "attempt to extract available AFs from EF.DIR");
168
+    // opts.optflag("", "ef-dir", "attempt to extract available AFs from EF.DIR");
122 169
     opts.optflag("h", "help", "prints this help text");
123
-    opts.optflag("", "filter-root", "filters DF names from the root of an AF occurring further into the path. Prevents some recursive structures on some cards.");
124
-    opts.optflag("", "filter-dup", "filters DF names that are the same as the parent's name. Prevents some recursive structures on some cards.");
170
+    opts.optflag("",
171
+                 "filter-root",
172
+                 "filters DF names from the root of an AF occurring further into the path. \
173
+                  Prevents some recursive structures on some cards.");
174
+    opts.optflag("",
175
+                 "filter-dup",
176
+                 "filters DF names that are the same as the parent's name. Prevents some \
177
+                  recursive structures on some cards.");
125 178
     opts.optflag("f", "filter", "alias for --filter-root --filter-dup.");
126 179
     opts.optflag("", "data-af", "scan for data objects on afs.");
127 180
     opts.optflag("", "data-df", "scan for data objects on dfs.");
128 181
     opts.optflag("", "data-ef", "scan for data objects on efs.");
129 182
     let matches = match opts.parse(&args[2..]) {
130
-        Ok(m) => { m }
131
-        Err(e) => { panic!(e.to_string()) }
183
+        Ok(m) => m,
184
+        Err(e) => panic!(e.to_string()),
132 185
     };
133 186
     if matches.opt_present("h") {
134 187
         print_usage(&program, &command, &opts);
@@ -147,7 +200,8 @@ pub fn main(args: Vec<String>) {
147 200
             exit(2);
148 201
         }
149 202
     };
150
-    let mut logfile = match File::create((matches.free[0].as_ref() as &Path).with_extension("log")) {
203
+    let mut logfile = match File::create((matches.free[0].as_ref() as &Path)
204
+        .with_extension("log")) {
151 205
         Ok(v) => v,
152 206
         Err(e) => {
153 207
             error!("Failed to create log file: {}", e);
@@ -178,9 +232,9 @@ pub fn main(args: Vec<String>) {
178 232
         afs.push((af, root));
179 233
     }
180 234
     // TODO: implement.
181
-    //if matches.opt_present("ef-dir") {
235
+    // if matches.opt_present("ef-dir") {
182 236
     //    unimplemented!();
183
-    //}
237
+    // }
184 238
     if afs.len() == 0 {
185 239
         afs.push((Vec::new(), Vec::new()));
186 240
     } else {
@@ -194,7 +248,8 @@ pub fn main(args: Vec<String>) {
194 248
         }
195 249
     };
196 250
     if !caps.has(fs::Capability::SelectAF) {
197
-        warn!("Card does not appear to have the capability to select AFs. Trying to select AFs anyway.");
251
+        warn!("Card does not appear to have the capability to select AFs. Trying to select AFs \
252
+               anyway.");
198 253
     }
199 254
     for af in afs.into_iter() {
200 255
         if af.0.len() > 0 {
@@ -216,19 +271,48 @@ pub fn main(args: Vec<String>) {
216 271
         };
217 272
         let filter_root = matches.opt_present("filter-root") || matches.opt_present("f");
218 273
         let filter_dup = matches.opt_present("filter-dup") || matches.opt_present("f");
219
-        let res = do_full_id_scan(&mut *handle, caps, filter_root, filter_dup, &af.0[..], af.1, &mut f, &mut logfile);
274
+        let res = do_full_id_scan(&mut *handle,
275
+                                  caps,
276
+                                  filter_root,
277
+                                  filter_dup,
278
+                                  &af.0[..],
279
+                                  af.1,
280
+                                  &mut f,
281
+                                  &mut logfile);
220 282
         let dfs = res.iter().filter(|&&(_, df)| df).map(|&(ref v, _)| v).collect::<Vec<_>>();
221
-        do_short_id_scan(&mut *handle, caps, &dfs[..], &af.0[..], &mut f, &mut logfile);
283
+        do_short_id_scan(&mut *handle,
284
+                         caps,
285
+                         &dfs[..],
286
+                         &af.0[..],
287
+                         &mut f,
288
+                         &mut logfile);
222 289
         if matches.opt_present("data-df") {
223
-            let dfs = res.iter().filter(|&&(_, df)| df).map(|&(ref v, _)| (v, true)).collect::<Vec<_>>();
224
-            do_data_scan(&mut *handle, caps, &dfs[..], &af.0[..], &mut f, &mut logfile);
290
+            let dfs =
291
+                res.iter().filter(|&&(_, df)| df).map(|&(ref v, _)| (v, true)).collect::<Vec<_>>();
292
+            do_data_scan(&mut *handle,
293
+                         caps,
294
+                         &dfs[..],
295
+                         &af.0[..],
296
+                         &mut f,
297
+                         &mut logfile);
225 298
         }
226 299
         if matches.opt_present("data-ef") {
227
-            let efs = res.iter().filter(|&&(_, df)| !df).map(|&(ref v, _)| (v, true)).collect::<Vec<_>>();
228
-            do_data_scan(&mut *handle, caps, &efs[..], &af.0[..], &mut f, &mut logfile);
300
+            let efs =
301
+                res.iter().filter(|&&(_, df)| !df).map(|&(ref v, _)| (v, true)).collect::<Vec<_>>();
302
+            do_data_scan(&mut *handle,
303
+                         caps,
304
+                         &efs[..],
305
+                         &af.0[..],
306
+                         &mut f,
307
+                         &mut logfile);
229 308
         }
230 309
         if matches.opt_present("data-af") {
231
-            do_data_scan(&mut *handle, caps, &[(&[], true)], &af.0[..], &mut f, &mut logfile);
310
+            do_data_scan(&mut *handle,
311
+                         caps,
312
+                         &[(&[], true)],
313
+                         &af.0[..],
314
+                         &mut f,
315
+                         &mut logfile);
232 316
         }
233 317
     }
234 318
 

+ 45
- 29
src/util.rs View File

@@ -33,29 +33,34 @@ pub fn try_pin<T: AsRef<[u8]>>(handle: &mut pcsc::Transmit, pin: &Option<T>) {
33 33
 
34 34
 fn rewrites_opt(matches: &Matches) -> Option<Vec<[u8; 4]>> {
35 35
     if let Some(rulestr) = matches.opt_str("apdumap") {
36
-        Some(rulestr.split(",").map(|part| {
37
-            let rule = part.split("->").collect::<Vec<_>>();
38
-            if rule.len() != 2 {
39
-                error!("Error parsing apdu map rule '{}': Expected '->'", part);
40
-                exit(2);
41
-            }
42
-            let bin = rule.iter().map(|p| {
43
-                match p.from_hex() {
44
-                    Ok(v) => v,
45
-                    Err(e) => {
46
-                        error!("Error parsing rule segment '{}': {}", p, e);
36
+        Some(rulestr.split(",")
37
+            .map(|part| {
38
+                let rule = part.split("->").collect::<Vec<_>>();
39
+                if rule.len() != 2 {
40
+                    error!("Error parsing apdu map rule '{}': Expected '->'", part);
41
+                    exit(2);
42
+                }
43
+                let bin = rule.iter()
44
+                    .map(|p| {
45
+                        match p.from_hex() {
46
+                            Ok(v) => v,
47
+                            Err(e) => {
48
+                                error!("Error parsing rule segment '{}': {}", p, e);
49
+                                exit(2);
50
+                            }
51
+                        }
52
+                    })
53
+                    .collect::<Vec<_>>();
54
+                for item in bin.iter() {
55
+                    if item.len() != 2 {
56
+                        error!("Error parsing rule segment '{}': Expected length of 2 bytes!",
57
+                               item.to_hex());
47 58
                         exit(2);
48 59
                     }
49 60
                 }
50
-            }).collect::<Vec<_>>();
51
-            for item in bin.iter() {
52
-                if item.len() != 2 {
53
-                    error!("Error parsing rule segment '{}': Expected length of 2 bytes!", item.to_hex());
54
-                    exit(2);
55
-                }
56
-            }
57
-            [bin[0][0], bin[0][1], bin[1][0], bin[1][1]]
58
-        }).collect::<Vec<_>>())
61
+                [bin[0][0], bin[0][1], bin[1][0], bin[1][1]]
62
+            })
63
+            .collect::<Vec<_>>())
59 64
     } else {
60 65
         None
61 66
     }
@@ -71,7 +76,8 @@ fn cla_opt(matches: &Matches) -> Option<u8> {
71 76
             }
72 77
         };
73 78
         if raw.len() != 1 {
74
-            error!("Error parsing cla value: expected only 1 byte (received {})", raw.len());
79
+            error!("Error parsing cla value: expected only 1 byte (received {})",
80
+                   raw.len());
75 81
             exit(2);
76 82
         }
77 83
         Some(raw[0])
@@ -90,7 +96,9 @@ pub fn init_context() -> pcsc::Context {
90 96
     }
91 97
 }
92 98
 
93
-pub fn init_handle<'a, 'b>(context: &'a pcsc::Context, matches: &'b Matches) -> Box<pcsc::Transmit + 'a> {
99
+pub fn init_handle<'a, 'b>(context: &'a pcsc::Context,
100
+                           matches: &'b Matches)
101
+                           -> Box<pcsc::Transmit + 'a> {
94 102
     let mut readers = match context.list_readers() {
95 103
         Ok(v) => v,
96 104
         Err(e) => {
@@ -99,10 +107,13 @@ pub fn init_handle<'a, 'b>(context: &'a pcsc::Context, matches: &'b Matches) ->
99 107
         }
100 108
     };
101 109
     let reader = match matches.opt_str("reader") {
102
-        Some(pat) => readers.filter(|r| match r.to_str() {
103
-            Ok(s) => s.to_lowercase().contains(&pat),
104
-            Err(_) => false
105
-        }).next(),
110
+        Some(pat) => {
111
+            readers.filter(|r| match r.to_str() {
112
+                    Ok(s) => s.to_lowercase().contains(&pat),
113
+                    Err(_) => false,
114
+                })
115
+                .next()
116
+        }
106 117
         None => readers.next(),
107 118
     };
108 119
     let reader = match reader {
@@ -112,7 +123,9 @@ pub fn init_handle<'a, 'b>(context: &'a pcsc::Context, matches: &'b Matches) ->
112 123
             exit(2);
113 124
         }
114 125
     };
115
-    let hraw = match context.connect(reader, pcsc::ShareMode::Exclusive, &[pcsc::Protocol::T0, pcsc::Protocol::T1]) {
126
+    let hraw = match context.connect(reader,
127
+                                     pcsc::ShareMode::Exclusive,
128
+                                     &[pcsc::Protocol::T0, pcsc::Protocol::T1]) {
116 129
         Ok((v, _)) => v,
117 130
         Err(e) => {
118 131
             error!("Failed to initiatialize PCSC reader handle: {}", e);
@@ -126,7 +139,7 @@ pub fn init_handle<'a, 'b>(context: &'a pcsc::Context, matches: &'b Matches) ->
126 139
         (Some(_), Some(_)) => {
127 140
             error!("Confliction options --cla and --apdumap supplied.");
128 141
             exit(2);
129
-        },
142
+        }
130 143
     }
131 144
 }
132 145
 
@@ -147,7 +160,10 @@ pub fn parse_pin(matches: &Matches) -> Option<Vec<u8>> {
147 160
     })
148 161
 }
149 162
 
150
-pub fn select_af(handle: &mut pcsc::Transmit, caps: fs::Capabilities, af: &[u8]) -> Result<Vec<u8>, pcsc::Error> {
163
+pub fn select_af(handle: &mut pcsc::Transmit,
164
+                 caps: fs::Capabilities,
165
+                 af: &[u8])
166
+                 -> Result<Vec<u8>, pcsc::Error> {
151 167
     let p2 = if caps.has(fs::Capability::ReturnNothing) {
152 168
         0x0c
153 169
     } else if caps.has(fs::Capability::ReturnFCI) {

Loading…
Cancel
Save