keepass_db/
lib.rs

1//! Read, modify and write KeePass 2.x databases
2//!
3//! The main types used in this crate are:
4//!
5//! * [`Key`] which represents the composite key used to lock a database
6//! * [`KeePassDoc`] which represents the contents of an unlocked KeePass database
7//!
8//! # Opening a database:
9//!
10//! ```
11//! use std::io::Error;
12//! use keepass_db::{KeePassDoc, protected_stream::CipherValue, Key};
13//! fn main() -> Result<(), Error> {
14//!     let mut key = Key::new();
15//!     key.set_user_password("asdf");
16//!     let mut doc = KeePassDoc::load_file("testdata/dummy-kdbx41.kdbx", &key)?;
17//!     let database = doc.file;
18//!     let stream = &mut doc.cipher;
19//!     let basic_entry = database.root_group().all_entries().filter(|e| e.url().unprotect(stream).unwrap() == "https://keepass.info/").last().unwrap();
20//!     println!("Password: {}", basic_entry.password().unprotect(stream).unwrap());
21//!     Ok(())
22//! }
23//! ```
24
25use std::collections::VecDeque;
26use std::collections::{BTreeMap, HashMap};
27use std::convert::TryInto;
28use std::slice::Iter;
29use std::fs::File;
30use std::io::prelude::*;
31use std::io::Cursor;
32use std::io::{self, SeekFrom};
33use std::process;
34use std::cmp;
35
36use num_derive::{FromPrimitive, ToPrimitive};
37use num_traits::FromPrimitive;
38#[cfg(feature = "write")]
39use num_traits::ToPrimitive;
40
41use log::debug;
42
43use base64::engine::{Engine, general_purpose::STANDARD as base64};
44use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
45use uuid::{uuid, Uuid};
46//use borsh::de::BorshDeserialize;  // try_from_slice()
47use chrono::prelude::*;
48use flate2::read::GzDecoder;
49
50use openssl::error::ErrorStack;
51use openssl::symm::{decrypt, Cipher, Crypter, Mode};
52
53#[cfg(feature = "write")]
54use openssl::symm::encrypt;
55
56use ring::digest::{Context, SHA256, SHA512};
57use ring::hmac;
58use sxd_document::parser;
59use sxd_xpath::{evaluate_xpath, Context as XPathContext, Factory, Value};
60
61use xml::attribute::OwnedAttribute;
62use xml::name::OwnedName;
63use xml::reader::{EventReader, ParserConfig, XmlEvent};
64use xml::writer::EventWriter;
65use derive_getters::Getters;
66
67use keepass_db_derive::{KdbxParse, KdbxSerialize};
68
69mod kdb1;
70mod utils;
71pub mod protected_stream;
72
73
74//trait KdbxDefault: Default {
75//    fn provide_default() -> Self
76//        {
77//        <Self as Default>::default()
78//    }
79//}
80
81trait KdbxParse<C>: Sized + Default {
82    //    fn provide_default() -> Self
83    //        where Self: Default {
84    //        <Self as Default>::default()
85    //    }
86
87    fn parse<R: Read>(
88        reader: &mut EventReader<R>,
89        name: OwnedName,
90        attributes: Vec<OwnedAttribute>,
91        context: &mut C,
92    ) -> Result<Option<Self>, String>;
93}
94
95//impl<T: KdbxParse> KdbxParse
96//    where T: KdbxParse + Default {
97//    fn default() -> Self {
98
99trait KdbxSerialize<C>: Sized {
100    fn serialize2<W: Write>(
101        writer: &mut EventWriter<W>,
102        value: Self,
103        context: &mut C,
104    ) -> Result<(), String>;
105}
106
107#[cfg(test)]
108mod tests;
109
110#[derive(FromPrimitive, ToPrimitive)]
111enum Compression {
112    None = 0,
113    Gzip = 1,
114}
115
116#[derive(FromPrimitive, ToPrimitive)]
117enum TlvType {
118    End = 0,
119    Comment = 1,
120    CipherId = 2,
121    CompressionFlags = 3,
122    MasterSeed = 4,
123    TransformSeed = 5,
124    TransformRounds = 6,
125    EncryptionIv = 7,
126    ProtectedStreamKey = 8,
127    StreamStartBytes = 9,
128    InnerRandomStreamId = 10,
129    KdfParameters = 11,
130    PublicCustomData = 12,
131}
132
133// struct Header {
134//     major_version: u16,
135//     minor_version: u16,
136//     tlvs: BTreeMap<u8, Vec<Vec<u8>>>,
137// }
138
139// impl Header {
140fn load_tlvs<R: Read>(
141    input: &mut R,
142    major_version: u16,
143) -> io::Result<(BTreeMap<u8, Vec<Vec<u8>>>, Vec<u8>)> {
144    // let minor_version = 0;
145    let mut tlvs = BTreeMap::new();
146    let mut header_blob = Vec::new();
147    loop {
148        let mut tlv_header = if major_version == 3 {
149            vec![0; 3]
150        } else {
151            vec![0; 5]
152        };
153        input.read_exact(&mut tlv_header)?;
154        header_blob.extend(&tlv_header);
155        let mut header_cursor = Cursor::new(tlv_header);
156        let tlv_type = header_cursor.read_u8()?;
157        let tlv_len = if major_version <= 3 {
158            header_cursor.read_u16::<LittleEndian>()? as u32
159        } else {
160            header_cursor.read_u32::<LittleEndian>()?
161        };
162        let mut tlv_data = vec![0; tlv_len as usize];
163        input.read_exact(&mut tlv_data)?;
164        header_blob.extend(&tlv_data);
165        debug!("TLV({}, {}): {:?}", tlv_type, tlv_len, &tlv_data);
166        if tlv_type == 0 {
167            break;
168        }
169        let values = match tlvs.get_mut(&tlv_type) {
170            Some(v) => v,
171            None => {
172                let v = Vec::new();
173                tlvs.insert(tlv_type, v);
174                tlvs.get_mut(&tlv_type).unwrap()
175            }
176        };
177        values.push(tlv_data);
178    }
179    Ok((tlvs, header_blob))
180}
181
182#[cfg(feature = "write")]
183fn save_tlvs<W: Write>(
184    output: &mut W,
185    tlvs: &BTreeMap<u8, Vec<Vec<u8>>>,
186    major_version: u16,
187) -> io::Result<Vec<u8>> {
188    let mut buf = Cursor::new(Vec::new());
189    let term = HashMap::from([(0, vec![vec![]])]);
190    for (key, values) in tlvs.iter().chain(term.iter()) {
191        for value in values {
192            buf.write_u8(*key)?;
193            // TODO Check for overflow
194            if major_version <= 3 {
195                buf.write_u16::<LittleEndian>(value.len() as u16)?;
196            } else {
197                buf.write_u32::<LittleEndian>(value.len() as u32)?;
198            }
199            buf.write(value)?;
200        }
201    }
202    let bytes = buf.into_inner();
203    output.write(&bytes)?;
204    Ok(bytes)
205}
206// }
207
208#[derive(PartialEq, Eq, FromPrimitive, ToPrimitive)]
209enum MapType {
210    None = 0,
211    // Byte = 0x02,
212    // UInt16 = 0x03,
213    UInt32 = 0x04,
214    UInt64 = 0x05,
215    Bool = 0x08,
216    // SByte = 0x0A,
217    // Int16 = 0x0B,
218    Int32 = 0x0C,
219    Int64 = 0x0D,
220    // Float = 0x10,
221    // Double = 0x11,
222    // Decimal = 0x12,
223    // Char = 0x17, // 16-bit Unicode character
224    String = 0x18,
225    ByteArray = 0x42,
226}
227
228#[derive(PartialEq, Eq, Debug)]
229pub enum MapValue {
230    UInt32(u32),
231    UInt64(u64),
232    Bool(bool),
233    Int32(i32),
234    Int64(i64),
235    String(String),
236    ByteArray(Vec<u8>),
237}
238
239impl From<&MapValue> for MapType {
240    fn from(value: &MapValue) -> Self {
241        match value {
242            MapValue::Bool(_) => MapType::Bool,
243            MapValue::Int32(_) => MapType::Int32,
244            MapValue::Int64(_) => MapType::Int64,
245            MapValue::UInt32(_) => MapType::UInt32,
246            MapValue::UInt64(_) => MapType::UInt64,
247            MapValue::String(_) => MapType::String,
248            MapValue::ByteArray(_) => MapType::ByteArray,
249        }
250    }
251}
252
253fn load_map(tlv_data: &[u8]) -> io::Result<HashMap<String, MapValue>> {
254    let mut custom_data = HashMap::new();
255    let kdf_parameters = &tlv_data;
256    let mut c = Cursor::new(kdf_parameters);
257    let variant_minor = c.read_u8()?;
258    let variant_major = c.read_u8()?;
259    if variant_major != 1 {
260        let _ = eprintln!(
261            "Unsupported variant dictionary version ({}.{})\n",
262            variant_major, variant_minor
263        );
264        return Err(io::Error::new(io::ErrorKind::Other, "Unsupported variant"));
265    };
266
267    loop {
268        let item_type = MapType::from_u8(c.read_u8()?)
269            .ok_or(io::Error::new(io::ErrorKind::Other, "Unknown type"))?;
270        if item_type == MapType::None {
271            break;
272        }
273        let item_key_len = c.read_u32::<LittleEndian>()?;
274        let mut item_key = vec![0; item_key_len as usize];
275        c.read_exact(&mut item_key)?;
276        let item_key_str = String::from_utf8_lossy(&item_key).to_owned();
277        let item_value_len = c.read_u32::<LittleEndian>()?;
278        let mut item_value = vec![0; item_value_len as usize];
279        c.read_exact(&mut item_value)?;
280        debug!("K: {}, V: {:0x?}", item_key_str, item_value);
281        let item_value = match item_type {
282            MapType::Bool => {
283                if item_value.len() != 1 {
284                    return Err(io::Error::new(
285                        io::ErrorKind::Unsupported,
286                        "Invalid bool value",
287                    ));
288                }
289                MapValue::Bool(item_value[0] != 0)
290            }
291            MapType::Int32 => {
292                MapValue::Int32(i32::from_le_bytes(item_value.try_into().map_err(|_| {
293                    io::Error::new(io::ErrorKind::Unsupported, "Invalid i32 value")
294                })?))
295            }
296            MapType::Int64 => {
297                MapValue::Int64(i64::from_le_bytes(item_value.try_into().map_err(|_| {
298                    io::Error::new(io::ErrorKind::Unsupported, "Invalid i64 value")
299                })?))
300            }
301            MapType::UInt32 => {
302                MapValue::UInt32(u32::from_le_bytes(item_value.try_into().map_err(|_| {
303                    io::Error::new(io::ErrorKind::Unsupported, "Invalid u32 value")
304                })?))
305            }
306            MapType::UInt64 => {
307                MapValue::UInt64(u64::from_le_bytes(item_value.try_into().map_err(|_| {
308                    io::Error::new(io::ErrorKind::Unsupported, "Invalid u64 value")
309                })?))
310            }
311            MapType::String => {
312                MapValue::String(String::from_utf8(item_value).map_err(|_| {
313                    io::Error::new(io::ErrorKind::Unsupported, "Invalid string value")
314                })?)
315            }
316            MapType::ByteArray => MapValue::ByteArray(item_value),
317            MapType::None => {
318                unreachable!()
319            }
320        };
321        custom_data.insert(item_key_str.to_owned().to_string(), item_value);
322    }
323    Ok(custom_data)
324}
325
326#[cfg(feature = "write")]
327fn save_map(map: &HashMap<String, MapValue>) -> Vec<u8> {
328    let variant_major = 1;
329    let variant_minor = 0;
330    let mut output = Cursor::new(Vec::new());
331    output.write_u8(variant_minor).unwrap();
332    output.write_u8(variant_major).unwrap();
333    for (k, v) in map {
334        output.write_u8(MapType::from(v).to_u8().unwrap()).unwrap();
335        output.write_u32::<LittleEndian>(k.len() as u32).unwrap();
336        output.write(k.as_bytes()).unwrap();
337        let item_value = match v {
338            MapValue::Bool(v) => {
339                vec![if *v { 1 } else { 0 }]
340            }
341            MapValue::Int32(v) => v.to_le_bytes().to_vec(),
342            MapValue::Int64(v) => v.to_le_bytes().to_vec(),
343            MapValue::UInt32(v) => v.to_le_bytes().to_vec(),
344            MapValue::UInt64(v) => v.to_le_bytes().to_vec(),
345            MapValue::String(v) => v.as_bytes().to_vec(),
346            MapValue::ByteArray(v) => v.clone(),
347        };
348        output
349            .write_u32::<LittleEndian>(item_value.len() as u32)
350            .unwrap();
351        output.write(&item_value).unwrap();
352    }
353    output.write_u8(0).unwrap(); // End of dictionary
354    output.into_inner()
355}
356
357struct BlockReader<R: Read> {
358    index: u64,
359    // block_size: u32,
360    hmac_key_base: Vec<u8>,
361    output: R,
362    buf: VecDeque<u8>,
363    complete: bool,
364}
365
366impl<R: Read> BlockReader<R> {
367    // const DEFAULT_BLOCK_SIZE: u32 = 1024*1024;
368
369    fn new(key: &[u8], output: R) -> Self {
370        Self {
371            index: 0,
372            // block_size: Self::DEFAULT_BLOCK_SIZE,
373            hmac_key_base: key.to_owned(),
374            output,
375            // buf: vec![0u8; 12],  /* Room for 64-bit block index and 32-bit size */
376            buf: VecDeque::new(),
377            complete: false,
378        }
379    }
380
381    fn load_next_block(&mut self) -> io::Result<()> {
382        println!("Block {}", self.index);
383        let mut hmac_tag: [u8; 32] = [0; 32];
384        // if major_version == 4 {
385        self.output.read_exact(&mut hmac_tag)?;
386        // } else {
387        //     /* KDBX 3.x format encrypts the database after breaking
388        //     * the stream into blocks */
389        //     let mut ciphertext = vec![];
390        //     self.output.read_to_end(&mut ciphertext)?;
391        //     let data = decrypt(Cipher::aes_256_cbc(), &master_key, Some(encryption_iv), &ciphertext).unwrap();
392        //     let mut c = Cursor::new(data);
393
394        //     /* Start stream header is used to verify successful decrypt */
395        //     let mut start_stream = vec![0; 32];
396        //     c.read_exact(&mut start_stream)?;
397        //     assert_eq!(&start_stream, &tlvs[&9u8]);
398        //     println!("Master Key appears valid");
399
400        //     let mut buf = vec![];
401        //     for self.index in 0.. {
402        //         println!("Block {}", self.index);
403        //         let block_id = c.read_u32::<LittleEndian>()?;
404        //         assert_eq!(self.index as u32, block_id);
405        //         let mut block_hash_expected = vec![0; 32];
406        //         c.read_exact(&mut block_hash_expected)?;
407        //         let block_size = c.read_u32::<LittleEndian>()?;
408        //         let mut block_data = vec![0; block_size as usize];
409        //         c.read_exact(&mut block_data)?;
410        //         let mut context = Context::new(&SHA256);
411        //         context.update(&block_data);
412        //         let block_hash = context.finish().as_ref().to_owned();
413        //         if block_size == 0 {
414        //             break;
415        //         }
416        //         assert_eq!(block_hash_expected, block_hash, "Failed hash");
417        //         buf.extend(block_data);
418        //     }
419        //     let mut gz:Box<dyn Read> = match compress {
420        //         Compression::Gzip => Box::new(GzDecoder::new(Cursor::new(buf))),
421        //         Compression::None => Box::new(Cursor::new(buf)),
422        //     };
423        //     let mut xml_file = File::create("data2.xml")?;
424        //     let mut contents = String::new();
425        //     gz.read_to_string(&mut contents)?;
426        //     let _ = xml_file.write(&contents.as_bytes());
427        //     // println!("{:#?}", &contents);
428        //     if &contents[0..3] == "\u{feff}" {
429        //         contents = contents[3..].to_string();
430        //     }
431        //     let package = parser::parse(&contents).unwrap();
432        //     let document = package.as_document();
433        //     let header_hash = evaluate_xpath(&document, "/KeePassFile/Meta/HeaderHash/text()").expect("Missing header hash");
434        //     if header_hash.string() != "" {
435        //         println!("Header Hash: '{}'", header_hash.string());
436        //         let expected_hash = base64.decode(&header_hash.string()).expect("Valid base64");
437        //         if expected_hash != digest.as_ref() {
438        //             eprintln!("Possible header corruption\n");
439        //             process::exit(1);
440        //         }
441        //     }
442        //     return Ok(());
443        // }
444        let block_size = self.output.read_u32::<LittleEndian>()?;
445        if block_size == 0 {
446            self.complete = true;
447            return Ok(());
448        }
449        let mut block = vec![0; block_size as usize];
450        self.output.read_exact(&mut block)?;
451
452        let mut hmac_context = Context::new(&SHA512);
453        let mut buf = Cursor::new(Vec::new());
454        buf.write_u64::<LittleEndian>(self.index)?;
455        self.index += 1;
456        hmac_context.update(buf.get_ref());
457        hmac_context.update(&self.hmac_key_base);
458        let hmac_key = hmac_context.finish().as_ref().to_owned();
459        buf.write_u32::<LittleEndian>(block_size)?;
460        buf.write(&block)?;
461        let hmac_key = hmac::Key::new(hmac::HMAC_SHA256, &hmac_key);
462        println!("Verifying HMAC");
463        hmac::verify(&hmac_key, buf.get_ref(), &hmac_tag).unwrap();
464        println!("Complete");
465        self.buf = block.into();
466        Ok(())
467    }
468}
469
470impl<R: Read> Read for BlockReader<R> {
471    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
472        if self.complete {
473            return Ok(0);
474        } else if self.buf.len() == 0 {
475            self.load_next_block()?;
476        }
477        let mut index = 0;
478        if index >= buf.len() {
479            return Ok(index);
480        }
481        while let Some(val) = self.buf.pop_front() {
482            buf[index] = val;
483            index += 1;
484            if index >= buf.len() {
485                return Ok(index);
486            }
487        }
488        Ok(index)
489    }
490}
491
492struct BlockWriter<W: Write> {
493    index: u64,
494    block_size: u32,
495    hmac_key_base: Vec<u8>,
496    output: W,
497    buf: Vec<u8>,
498}
499
500impl<W: Write> BlockWriter<W> {
501    const DEFAULT_BLOCK_SIZE: u32 = 1024 * 1024;
502
503    fn new(key: &[u8], output: W) -> Self {
504        Self {
505            index: 0,
506            block_size: Self::DEFAULT_BLOCK_SIZE,
507            hmac_key_base: key.to_owned(),
508            output,
509            // buf: vec![0u8; 12],  /* Room for 64-bit block index and 32-bit size */
510            buf: Vec::new(),
511        }
512    }
513}
514
515impl<W: Write> Write for BlockWriter<W> {
516    fn flush(&mut self) -> io::Result<()> {
517        let mut hmac_context = Context::new(&SHA512);
518        let mut key_buf = Cursor::new(Vec::new());
519        key_buf.write_u64::<LittleEndian>(self.index)?;
520        self.index += 1;
521        hmac_context.update(key_buf.get_ref());
522        hmac_context.update(&self.hmac_key_base);
523        let hmac_key = hmac_context.finish().as_ref().to_owned();
524        key_buf.write_u32::<LittleEndian>(self.buf.len() as u32)?;
525        key_buf.write(&self.buf)?;
526        let hmac_key = hmac::Key::new(hmac::HMAC_SHA256, &hmac_key);
527        // println!("Verifying HMAC");
528        let hmac_tag = hmac::sign(&hmac_key, key_buf.get_ref());
529        // println!("Complete");
530        self.output.write(hmac_tag.as_ref())?;
531        self.output
532            .write_u32::<LittleEndian>(self.buf.len() as u32)?;
533        self.output.write(&self.buf)?;
534        self.buf.truncate(0);
535        Ok(())
536    }
537
538    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
539        let remaining = cmp::min(
540            self.block_size as usize - cmp::min(self.buf.len(), self.block_size as usize),
541            buf.len(),
542        );
543        self.buf.extend(&buf[..remaining]);
544        if self.buf.len() >= self.block_size as usize {
545            self.flush()?;
546        }
547        Ok(remaining)
548        // let mut offset = 0;
549        // while offset < self.buf.len() {
550        //     let mut count = std::cmp::max(Self::DEFAULT_BLOCK_SIZE as usize - offset;
551        //     if count > buf.len() {
552        //         count = buf.len();
553        //     }
554        //     self.buf.extend(&buf[offset..offset+count]);
555        //     offset += count;
556        //     if self.buf.len() >= Self::DEFAULT_BLOCK_SIZE as usize {
557        //         self.flush()?;
558        //     }
559        // }
560        // Ok(buf.len())
561    }
562}
563
564#[derive(Debug)]
565struct CryptoError {
566    _error: ErrorStack,
567}
568
569impl From<ErrorStack> for CryptoError {
570    fn from(error: ErrorStack) -> Self {
571        Self { _error: error }
572    }
573}
574
575struct Crypto<W: Write> {
576    crypter: Crypter,
577    output: W,
578    buf: Vec<u8>,
579    block_size: usize,
580}
581
582impl<W: Write> Crypto<W> {
583    fn new(cipher: Cipher, key: &[u8], iv: Option<&[u8]>, output: W) -> Result<Self, CryptoError> {
584        Ok(Self {
585            crypter: Crypter::new(cipher, Mode::Encrypt, key, iv)?,
586            output,
587            buf: Vec::new(),
588            block_size: cipher.block_size(),
589        })
590    }
591}
592
593impl<W: Write> Drop for Crypto<W> {
594    fn drop(&mut self) {
595        self.output.flush().unwrap();
596        // let rest = self
597        //     .crypter
598        //     .finalize(&mut self.buf)
599        //     .expect("Failed to finalize encryption");
600        // self.output
601        //     .write_all(&self.buf[..rest])
602        //     .expect("Failed to flush");
603    }
604}
605
606impl<W: Write> Write for Crypto<W> {
607    fn flush(&mut self) -> io::Result<()> {
608        self.buf = vec![0; self.block_size];
609        let rest = self
610            .crypter
611            .finalize(&mut self.buf)
612            .expect("Failed to finalize encryption");
613        self.output
614            .write_all(&self.buf[..rest])
615            .expect("Failed to flush");
616        self.buf = vec![];
617        self.output.flush()?;
618        // TODO Call lower layer
619        Ok(())
620    }
621
622    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
623        self.buf.resize(data.len() + self.block_size, 0);
624        let count = self.crypter.update(data, &mut self.buf)?;
625        self.output.write_all(&self.buf[..count])?;
626        self.buf = self.buf[count..].to_vec();
627        Ok(data.len())
628    }
629}
630
631struct CryptoReader<R: Read> {
632    crypter: Crypter,
633    output: R,
634    buf: Vec<u8>,
635    block_size: usize,
636}
637
638impl<R: Read> CryptoReader<R> {
639    fn new(cipher: Cipher, key: &[u8], iv: Option<&[u8]>, output: R) -> Result<Self, CryptoError> {
640        Ok(Self {
641            crypter: Crypter::new(cipher, Mode::Decrypt, key, iv)?,
642            output,
643            buf: Vec::new(),
644            block_size: cipher.block_size(),
645        })
646    }
647}
648
649// impl<R: Read> Drop for CryptoReader<R> {
650//     fn drop(&mut self) {
651//         let rest = self.crypter.finalize(&mut self.buf).expect("Failed to finalize encryption");
652//         self.output.write_all(&self.buf[..rest]).expect("Failed to flush");
653//     }
654// }
655
656// impl<R: Read> Read for CryptoReader<R> {
657//     fn read(&mut self, data: &mut [u8]) -> io::Result<usize> {
658//         self.buf.resize(data.len() + self.block_size, 0);
659//         let count = self.crypter.update(data, &mut self.buf)?;
660//         self.output.write_all(&self.buf[..count])?;
661//         self.buf = self.buf[count..].to_vec();
662//         Ok(data.len())
663//     }
664// }
665
666mod key;
667mod kdf;
668pub use kdf::*;
669pub use key::Key;
670
671pub const KDF_AES_KDBX3: Uuid = uuid!("c9d9f39a-628a-4460-bf74-0d08c18a4fea");
672const KDF_AES_KDBX4: Uuid = uuid!("7c02bb82-79a7-4ac0-927d-114a00648238");
673const KDF_ARGON2_D: Uuid = uuid!("ef636ddf-8c29-444b-91f7-a9a403e30a0c");
674const _KDF_ARGON2_ID: Uuid = uuid!("9e298b19-56db-4773-b23d-fc3ec6f0a1e6");
675
676const _CIPHER_ID_AES128_CBC: Uuid = uuid!("61ab05a1-9464-41c3-8d74-3a563df8dd35");
677const CIPHER_ID_AES256_CBC: Uuid = uuid!("31c1f2e6-bf71-4350-be58-05216afc5aff");
678const _CIPHER_ID_TWOFISH_CBC: Uuid = uuid!("ad68f29f-576f-4bb9-a36a-d47af965346c");
679const _CIPHER_ID_CHACHA20: Uuid = uuid!("d6038a2b-8b6f-4cb5-a524-339a31dbb59a");
680
681fn consume_element<R: Read>(
682    reader: &mut EventReader<R>,
683    name: OwnedName,
684    _attributes: Vec<OwnedAttribute>,
685) -> Result<Option<String>, String> {
686    let mut elements = vec![];
687    println!("A tag: {}", &name);
688    elements.push(name);
689
690    let mut string = None;
691
692    let mut event = reader
693        .next()
694        .map_err(|_| "Failed to retrieve next XML event")?;
695    loop {
696        match event {
697            XmlEvent::StartDocument { .. } => {
698                return Err("Malformed XML document, start of document".to_string());
699            }
700            XmlEvent::EndDocument { .. } => {
701                return Err("Malformed XML document, end of document".to_string());
702            }
703            XmlEvent::StartElement { name, .. } => {
704                elements.push(name);
705            }
706            XmlEvent::Characters(k) => {
707                string = Some(k);
708            }
709            XmlEvent::EndElement { name, .. } => {
710                let start_tag = elements.pop().expect("Can't consume a bare end element");
711                if start_tag != name {
712                    return Err(format!(
713                        "Start tag <{}> mismatches end tag </{}>",
714                        start_tag, name
715                    ));
716                }
717            }
718            _ => {
719                // Consume any PI, text, comment, or cdata node
720                //return Ok(());
721            }
722        };
723        if elements.len() == 0 {
724            return Ok(string);
725        }
726        event = reader
727            .next()
728            .map_err(|_| "Failed to retrieve next XML event")?;
729    }
730}
731
732pub enum ElementEvent {
733    StartElement {
734        name: OwnedName,
735        attributes: Vec<OwnedAttribute>,
736    },
737    EndElement {
738        name: OwnedName,
739    },
740}
741
742fn find_next_element<R: Read>(reader: &mut EventReader<R>) -> Result<ElementEvent, String> {
743    loop {
744        match reader
745            .next()
746            .map_err(|_| "Failed to retrieve next XML event")?
747        {
748            XmlEvent::StartDocument { .. } => {
749                return Err("Malformed XML document".to_string());
750            }
751            XmlEvent::EndDocument { .. } => {
752                return Err("Malformed XML document".to_string());
753            }
754            XmlEvent::StartElement {
755                name, attributes, ..
756            } => {
757                return Ok(ElementEvent::StartElement { name, attributes });
758            }
759            XmlEvent::Characters(_) => {}
760            XmlEvent::CData(_) => {}
761            XmlEvent::Whitespace(_) => {}
762            XmlEvent::ProcessingInstruction { .. } => {}
763            XmlEvent::EndElement { name, .. } => {
764                return Ok(ElementEvent::EndElement { name });
765            }
766            _ => {
767                // Consume any PI, text, comment, or cdata node
768                //return Ok(());
769            }
770        };
771    }
772}
773
774fn decode_optional_string<R: Read>(
775    reader: &mut EventReader<R>,
776    name: OwnedName,
777    _attributes: Vec<OwnedAttribute>,
778) -> Result<Option<String>, String> {
779    let mut elements = vec![];
780    elements.push(name);
781
782    let mut string = String::new();
783
784    let mut event = reader
785        .next()
786        .map_err(|_| "Failed to retrieve next XML event")?;
787    loop {
788        match event {
789            XmlEvent::StartDocument { .. } => {
790                return Err("Malformed XML document".to_string());
791            }
792            XmlEvent::EndDocument { .. } => {
793                return Err("Malformed XML document".to_string());
794            }
795            XmlEvent::StartElement { name, .. } => {
796                elements.push(name);
797            }
798            XmlEvent::Characters(k) => {
799                if elements.len() == 1 {
800                    string.push_str(&k);
801                }
802            }
803            XmlEvent::Whitespace(k) => {
804                if elements.len() == 1 {
805                    string.push_str(&k);
806                }
807            }
808            XmlEvent::CData(k) => {
809                if elements.len() == 1 {
810                    string.push_str(&k);
811                }
812            }
813            XmlEvent::EndElement { name, .. } => {
814                let start_tag = elements.pop().expect("Can't consume a bare end element");
815                if start_tag != name {
816                    return Err(format!(
817                        "Start tag <{}> mismatches end tag </{}>",
818                        start_tag, name
819                    ));
820                }
821            }
822            _ => {
823                // Consume any PI, text, comment, or cdata node
824                //return Ok(());
825            }
826        };
827        if elements.len() == 0 {
828            if string.len() == 0 {
829                return Ok(None);
830            } else {
831                return Ok(Some(string));
832            }
833        }
834        event = reader.next().map_err(|_| "")?;
835    }
836}
837
838fn encode_optional_string<W: Write>(
839    writer: &mut EventWriter<W>,
840    value: Option<&str>,
841) -> Result<(), String> {
842    if let Some(contents) = value {
843        writer
844            .write(xml::writer::XmlEvent::characters(contents))
845            .map_err(|_| "".to_string())
846    } else {
847        Ok(())
848    }
849}
850
851fn decode_string<R: Read>(
852    reader: &mut EventReader<R>,
853    name: OwnedName,
854    attributes: Vec<OwnedAttribute>,
855) -> Result<String, String> {
856    decode_optional_string(reader, name, attributes).map(|x| x.unwrap_or_else(|| "".into()))
857}
858
859impl<C> KdbxParse<C> for String {
860    fn parse<R: Read>(
861        reader: &mut EventReader<R>,
862        name: OwnedName,
863        attributes: Vec<OwnedAttribute>,
864        _context: &mut C,
865    ) -> Result<Option<Self>, String> {
866        decode_optional_string(reader, name, attributes)
867    }
868}
869
870fn encode_string<W: Write>(writer: &mut EventWriter<W>, value: &str) -> Result<(), String> {
871    encode_optional_string(writer, Some(value))
872}
873
874impl<C> KdbxSerialize<C> for String {
875    fn serialize2<W: Write>(
876        writer: &mut EventWriter<W>,
877        value: Self,
878        _context: &mut C,
879    ) -> Result<(), String> {
880        encode_string(writer, &value)
881    }
882}
883
884fn decode_optional_base64<R: Read>(
885    reader: &mut EventReader<R>,
886    name: OwnedName,
887    attributes: Vec<OwnedAttribute>,
888) -> Result<Option<Vec<u8>>, String> {
889    Ok(decode_optional_string(reader, name, attributes)?
890        .map(|x| base64.decode(&x).unwrap() /* .as_bytes().into() */))
891}
892
893fn encode_optional_base64<W: Write, T: AsRef<[u8]>>(
894    writer: &mut EventWriter<W>,
895    value: Option<T>,
896) -> Result<(), String> {
897    // let bytes = value.map(|x| base64.encode(x.as_ref()));
898    // encode_optional_string(writer, bytes.map(|x| x.as_str()))
899    encode_optional_string(writer, value.map(|x| base64.encode(x.as_ref())).as_deref())
900}
901
902fn decode_base64<R: Read>(
903    reader: &mut EventReader<R>,
904    name: OwnedName,
905    attributes: Vec<OwnedAttribute>,
906) -> Result<Vec<u8>, String> {
907    Ok(decode_optional_base64(reader, name, attributes)?.unwrap_or_default())
908}
909
910fn encode_base64<W: Write, T: AsRef<[u8]>>(
911    writer: &mut EventWriter<W>,
912    value: T,
913) -> Result<(), String> {
914    encode_optional_base64(writer, Some(value))
915}
916
917fn decode_optional_bool<R: Read>(
918    reader: &mut EventReader<R>,
919    name: OwnedName,
920    attributes: Vec<OwnedAttribute>,
921) -> Result<Option<bool>, String> {
922    decode_optional_string(reader, name, attributes)
923        .map(|x| x.map(|y| y.eq_ignore_ascii_case("true")))
924}
925
926fn encode_optional_bool<W: Write>(
927    writer: &mut EventWriter<W>,
928    value: Option<bool>,
929) -> Result<(), String> {
930    encode_optional_string(writer, value.map(|x| if x { "True" } else { "False" }))
931}
932
933// fn decode_bool<R: Read>(
934//     reader: &mut EventReader<R>,
935//     name: OwnedName,
936//     attributes: Vec<OwnedAttribute>,
937// ) -> Result<bool, String> {
938//     decode_optional_bool(reader, name, attributes).map(|x| x.unwrap_or(false))
939// }
940
941impl<C> KdbxParse<C> for bool {
942    fn parse<R: Read>(
943        reader: &mut EventReader<R>,
944        name: OwnedName,
945        attributes: Vec<OwnedAttribute>,
946        _context: &mut C,
947    ) -> Result<Option<Self>, String> {
948        decode_optional_bool(reader, name, attributes)
949    }
950}
951
952fn encode_bool<W: Write>(writer: &mut EventWriter<W>, value: bool) -> Result<(), String> {
953    encode_optional_bool(writer, Some(value))
954}
955
956impl<C> KdbxSerialize<C> for bool {
957    fn serialize2<W: Write>(
958        writer: &mut EventWriter<W>,
959        value: Self,
960        _context: &mut C,
961    ) -> Result<(), String> {
962        encode_bool(writer, value)
963    }
964}
965
966fn decode_optional_i64<R: Read>(
967    reader: &mut EventReader<R>,
968    name: OwnedName,
969    attributes: Vec<OwnedAttribute>,
970) -> Result<Option<i64>, String> {
971    decode_optional_string(reader, name, attributes).map(|x| x.map(|y| y.parse().unwrap_or(0)))
972}
973
974fn encode_optional_i64<W: Write>(
975    writer: &mut EventWriter<W>,
976    value: Option<i64>,
977) -> Result<(), String> {
978    encode_optional_string(writer, value.map(|x| format!("{}", x)).as_deref())
979}
980
981fn decode_i64<R: Read>(
982    reader: &mut EventReader<R>,
983    name: OwnedName,
984    attributes: Vec<OwnedAttribute>,
985) -> Result<i64, String> {
986    decode_optional_i64(reader, name, attributes).map(|x| x.unwrap_or(0))
987}
988
989impl<C> KdbxParse<C> for i64 {
990    fn parse<R: Read>(
991        reader: &mut EventReader<R>,
992        name: OwnedName,
993        attributes: Vec<OwnedAttribute>,
994        _context: &mut C,
995    ) -> Result<Option<Self>, String> {
996        Ok(Some(decode_i64(reader, name, attributes)?))
997    }
998}
999
1000fn encode_i64<W: Write>(writer: &mut EventWriter<W>, value: i64) -> Result<(), String> {
1001    encode_optional_i64(writer, Some(value))
1002}
1003
1004impl<C> KdbxSerialize<C> for i64 {
1005    fn serialize2<W: Write>(
1006        writer: &mut EventWriter<W>,
1007        value: Self,
1008        _context: &mut C,
1009    ) -> Result<(), String> {
1010        encode_i64(writer, value)
1011    }
1012}
1013
1014impl<C> KdbxParse<C> for i32 {
1015    fn parse<R: Read>(
1016        reader: &mut EventReader<R>,
1017        name: OwnedName,
1018        attributes: Vec<OwnedAttribute>,
1019        _context: &mut C,
1020    ) -> Result<Option<Self>, String> {
1021        //decode_i64(reader, name, attributes).map(|v| Some(v as i32))
1022        Ok(Some(decode_i64(reader, name, attributes)? as i32))
1023    }
1024}
1025
1026impl<C> KdbxSerialize<C> for i32 {
1027    fn serialize2<W: Write>(
1028        writer: &mut EventWriter<W>,
1029        value: Self,
1030        _context: &mut C,
1031    ) -> Result<(), String> {
1032        encode_i64(writer, value as i64)
1033    }
1034}
1035
1036impl<C> KdbxParse<C> for u32 {
1037    fn parse<R: Read>(
1038        reader: &mut EventReader<R>,
1039        name: OwnedName,
1040        attributes: Vec<OwnedAttribute>,
1041        _context: &mut C,
1042    ) -> Result<Option<Self>, String> {
1043        Ok(Some(decode_i64(reader, name, attributes)? as u32))
1044    }
1045}
1046
1047impl<C> KdbxSerialize<C> for u32 {
1048    fn serialize2<W: Write>(
1049        writer: &mut EventWriter<W>,
1050        value: Self,
1051        _context: &mut C,
1052    ) -> Result<(), String> {
1053        encode_i64(writer, value as i64)
1054    }
1055}
1056
1057static mut KDBX4: bool = true;
1058const KDBX4_TIME_OFFSET: i64 = 62135596800;
1059fn decode_optional_datetime<R: Read>(
1060    reader: &mut EventReader<R>,
1061    name: OwnedName,
1062    attributes: Vec<OwnedAttribute>,
1063) -> Result<Option<DateTime<Utc>>, String> {
1064    let is_new = unsafe { KDBX4 };
1065    if is_new {
1066        decode_optional_string(reader, name, attributes).map(|x| {
1067            x.map(|y| {
1068                Utc.timestamp_opt(
1069                    Cursor::new(base64.decode(&y).expect("Valid base64"))
1070                        .read_i64::<LittleEndian>()
1071                        .unwrap()
1072                        - KDBX4_TIME_OFFSET,
1073                    0,
1074                ).unwrap()
1075            })
1076        })
1077    } else {
1078        decode_optional_string(reader, name, attributes).map(|x| {
1079            x.map(|y| {
1080                if let Some(suffix) = y.chars().last() {
1081                    if suffix.to_ascii_uppercase() == 'Z' {
1082                        DateTime::parse_from_rfc3339(&y)
1083                            .expect(&format!("failed to parse timestamp: {}", y))
1084                            .with_timezone(&Utc)
1085                    } else {
1086                        NaiveDateTime::parse_from_str(&y, "%Y-%m-%dT%H:%M:%S").expect("invalid local date").and_local_timezone(Local).earliest().unwrap()
1087                            .with_timezone(&Utc)
1088                    }
1089                } else {
1090                    unreachable!("This shouldn't be possible");
1091                }
1092            })
1093        })
1094    }
1095}
1096
1097fn encode_optional_datetime<W: Write>(
1098    writer: &mut EventWriter<W>,
1099    value: Option<DateTime<Utc>>,
1100) -> Result<(), String> {
1101    encode_optional_string(
1102        writer,
1103        value
1104            .map(|x| base64.encode(&(x.timestamp() + KDBX4_TIME_OFFSET).to_le_bytes()))
1105            .as_deref(),
1106    )
1107}
1108
1109// fn decode_datetime<R: Read>(
1110//     reader: &mut EventReader<R>,
1111//     name: OwnedName,
1112//     attributes: Vec<OwnedAttribute>,
1113// ) -> Result<DateTime<Utc>, String> {
1114//     decode_optional_datetime(reader, name, attributes).map(|x| x.expect("missing date"))
1115// }
1116
1117//impl KdbxDefault for DateTime<Utc> {
1118//    fn provide_default() -> Self {
1119//        Utc::now()
1120//    }
1121//}
1122
1123struct KdbxContext {
1124    major_version: u16,
1125    inner_cipher_position: usize,
1126    binaries: Vec<Vec<u8>>,
1127}
1128
1129impl Default for KdbxContext {
1130    fn default() -> Self {
1131        KdbxContext {
1132            major_version: 4,
1133            inner_cipher_position: 0,
1134            binaries: vec![],
1135        }
1136    }
1137}
1138
1139impl KdbxParse<KdbxContext> for DateTime<Utc> {
1140    fn parse<R: Read>(
1141        reader: &mut EventReader<R>,
1142        name: OwnedName,
1143        attributes: Vec<OwnedAttribute>,
1144        context: &mut KdbxContext,
1145    ) -> Result<Option<Self>, String> {
1146        unsafe {
1147            KDBX4 = context.major_version >= 4;
1148        };
1149        decode_optional_datetime(reader, name, attributes)
1150    }
1151}
1152
1153fn encode_datetime<W: Write>(
1154    writer: &mut EventWriter<W>,
1155    value: DateTime<Utc>,
1156) -> Result<(), String> {
1157    encode_optional_datetime(writer, Some(value))
1158}
1159
1160impl KdbxSerialize<KdbxContext> for DateTime<Utc> {
1161    fn serialize2<W: Write>(
1162        writer: &mut EventWriter<W>,
1163        value: Self,
1164        context: &mut KdbxContext,
1165    ) -> Result<(), String> {
1166        if context.major_version >= 4 {
1167            encode_datetime(writer, value)
1168        } else {
1169            encode_string(writer, value.format("%FT%TZ").to_string().as_str())
1170        }
1171    }
1172}
1173
1174//fn decode_i64<R: Read>(reader: &mut EventReader<R>, name: OwnedName, attributes: Vec<OwnedAttribute>) -> Result<DateTime<Utc>, String> {
1175//decode_optional_i64(reader, name, attributes).map(|x| x.unwrap_or(0))
1176//}
1177
1178fn decode_optional_uuid<R: Read>(
1179    reader: &mut EventReader<R>,
1180    name: OwnedName,
1181    attributes: Vec<OwnedAttribute>,
1182) -> Result<Option<Uuid>, String> {
1183    decode_optional_string(reader, name, attributes)
1184        .map(|x| x.map(|y| Uuid::from_slice(&base64.decode(&y).expect("Valid base64")).unwrap()))
1185}
1186
1187fn encode_optional_uuid<W: Write>(
1188    writer: &mut EventWriter<W>,
1189    value: Option<Uuid>,
1190) -> Result<(), String> {
1191    encode_optional_string(writer, value.map(|x| base64.encode(x.as_ref())).as_deref())
1192}
1193
1194// fn decode_uuid<R: Read>(
1195//     reader: &mut EventReader<R>,
1196//     name: OwnedName,
1197//     attributes: Vec<OwnedAttribute>,
1198// ) -> Result<Uuid, String> {
1199//     decode_optional_uuid(reader, name, attributes).map(|x| x.unwrap_or_else(|| Uuid::default()))
1200// }
1201
1202fn encode_uuid<W: Write>(writer: &mut EventWriter<W>, value: Uuid) -> Result<(), String> {
1203    encode_optional_uuid(writer, Some(value))
1204}
1205
1206impl<C> KdbxParse<C> for Uuid {
1207    fn parse<R: Read>(
1208        reader: &mut EventReader<R>,
1209        name: OwnedName,
1210        attributes: Vec<OwnedAttribute>,
1211        _context: &mut C,
1212    ) -> Result<Option<Self>, String> {
1213        decode_optional_uuid(reader, name, attributes)
1214    }
1215}
1216
1217impl<C> KdbxSerialize<C> for Uuid {
1218    fn serialize2<W: Write>(
1219        writer: &mut EventWriter<W>,
1220        value: Self,
1221        _context: &mut C,
1222    ) -> Result<(), String> {
1223        encode_uuid(writer, value)
1224    }
1225}
1226
1227fn decode_item<R: Read>(
1228    reader: &mut EventReader<R>,
1229    _name: OwnedName,
1230    _attributes: Vec<OwnedAttribute>,
1231) -> Result<(String, String), String> {
1232    let mut key = String::new();
1233    let mut value = String::new();
1234
1235    loop {
1236        match find_next_element(reader)? {
1237            ElementEvent::StartElement { name, .. } if name.local_name == "Key" => {
1238                key = decode_string(reader, name, vec![])?;
1239            }
1240            ElementEvent::StartElement { name, .. } if name.local_name == "Value" => {
1241                value = decode_string(reader, name, vec![])?;
1242            }
1243            ElementEvent::StartElement { name, .. } => {
1244                consume_element(reader, name, vec![])?;
1245            }
1246            ElementEvent::EndElement { name, .. } if name.local_name == "Item" => {
1247                return Ok((key, value));
1248            }
1249            ElementEvent::EndElement { .. } => {
1250                return Err("Wrong ending".to_string());
1251            }
1252        }
1253    }
1254}
1255
1256fn encode_item<W: Write>(writer: &mut EventWriter<W>, value: (&str, &str)) -> Result<(), String> {
1257    writer
1258        .write(xml::writer::XmlEvent::start_element("Item"))
1259        .map_err(|_| "")?;
1260    writer
1261        .write(xml::writer::XmlEvent::start_element("Key"))
1262        .map_err(|_| "")?;
1263    encode_string(writer, value.0)?;
1264    writer
1265        .write(xml::writer::XmlEvent::end_element())
1266        .map_err(|_| "")?;
1267    writer
1268        .write(xml::writer::XmlEvent::start_element("Value"))
1269        .map_err(|_| "")?;
1270    encode_string(writer, value.1)?;
1271    writer
1272        .write(xml::writer::XmlEvent::end_element())
1273        .map_err(|_| "")?;
1274    writer
1275        .write(xml::writer::XmlEvent::end_element())
1276        .map_err(|_| "")?;
1277    Ok(())
1278}
1279
1280fn decode_custom_data<R: Read>(
1281    reader: &mut EventReader<R>,
1282    pname: OwnedName,
1283    _attributes: Vec<OwnedAttribute>,
1284) -> Result<HashMap<String, String>, String> {
1285    //let mut elements = vec![];
1286    //elements.push(name);
1287
1288    let mut data = HashMap::new();
1289
1290    loop {
1291        match find_next_element(reader)? {
1292            ElementEvent::StartElement { name, .. } if name.local_name == "Item" => {
1293                let (key, value) = decode_item(reader, name, vec![])?;
1294                //data[key] = value;
1295                data.insert(key, value);
1296            }
1297            ElementEvent::StartElement { name, .. } => {
1298                consume_element(reader, name, vec![])?;
1299            }
1300            ElementEvent::EndElement { name, .. } if name == pname => {
1301                return Ok(data);
1302            }
1303            ElementEvent::EndElement { .. } => {
1304                return Err("Wrong ending".to_string());
1305            }
1306        }
1307    }
1308}
1309
1310fn encode_custom_data<W: Write>(
1311    writer: &mut EventWriter<W>,
1312    map: HashMap<String, String>,
1313) -> Result<(), String> {
1314    for (key, value) in map.iter() {
1315        encode_item(writer, (key, value))?;
1316    }
1317    Ok(())
1318}
1319
1320#[derive(Clone, Debug, Default, KdbxParse, KdbxSerialize)]
1321struct MemoryProtection {
1322    protect_title: bool,
1323    protect_user_name: bool,
1324    protect_password: bool,
1325    #[keepass_db(element = "ProtectURL")]
1326    protect_url: bool,
1327    protect_notes: bool,
1328}
1329
1330#[derive(Clone, Debug, Default, KdbxParse, KdbxSerialize)]
1331struct Icon {
1332    #[keepass_db(element = "UUID")]
1333    uuid: Uuid,
1334    last_modification_time: Option<DateTime<Utc>>,
1335    data: Vec<u8>,
1336}
1337
1338#[derive(Clone, Debug, Default, KdbxParse, KdbxSerialize)]
1339#[cfg_attr(test, derive(PartialEq))]
1340pub struct Item {
1341    key: String,
1342    value: String,
1343    // This field only seems to be present on Meta data, not password entries
1344    last_modification_time: Option<DateTime<Utc>>,
1345}
1346
1347#[derive(Clone, Debug, Default, KdbxParse, KdbxSerialize)]
1348struct Meta {
1349    generator: String,
1350    header_hash: Option<[u8; 32]>,
1351    settings_changed: Option<DateTime<Utc>>,
1352    database_name: String,
1353    database_name_changed: Option<DateTime<Utc>>,
1354    database_description: String,
1355    database_description_changed: Option<DateTime<Utc>>,
1356    default_user_name: String,
1357    default_user_name_changed: Option<DateTime<Utc>>,
1358    maintenance_history_days: u32,
1359    color: String,
1360    master_key_changed: Option<DateTime<Utc>>,
1361    master_key_change_rec: i64,
1362    master_key_change_force: i64,
1363    master_key_change_force_once: bool,
1364    memory_protection: MemoryProtection,
1365    custom_icons: Vec<Icon>,
1366    recycle_bin_enabled: bool,
1367    #[keepass_db(element = "RecycleBinUUID")]
1368    recycle_bin_uuid: Option<Uuid>,
1369    recycle_bin_changed: DateTime<Utc>,
1370    entry_templates_group: Uuid,  // TODO should be optional?
1371    entry_templates_group_changed: DateTime<Utc>,
1372    history_max_items: i32,  // -1 = unlimited
1373    history_max_size: i64,  // -1 = unlimited
1374    last_selected_group: Uuid,  // TODO should be optional?
1375    last_top_visible_group: Uuid,  // TODO should be optional?
1376    //custom_data: HashMap<String, String>,
1377    custom_data: Vec<Item>,
1378}
1379
1380impl<C> KdbxParse<C> for [u8; 32] {
1381    fn parse<R: Read>(
1382        reader: &mut EventReader<R>,
1383        name: OwnedName,
1384        attributes: Vec<OwnedAttribute>,
1385        _context: &mut C,
1386    ) -> Result<Option<Self>, String> {
1387        //decode_optional_string(reader, name, attributes)
1388        //Ok(decode_base64(reader, name, attributes)?.map(|v| Some(v.try_into().map_err(|_| "")?))?)
1389        Ok(Some(
1390            decode_base64(reader, name, attributes)?
1391                .try_into()
1392                .map_err(|_| "")?,
1393        ))
1394    }
1395}
1396
1397impl<C> KdbxSerialize<C> for [u8; 32] {
1398    fn serialize2<W: Write>(
1399        writer: &mut EventWriter<W>,
1400        value: Self,
1401        _context: &mut C,
1402    ) -> Result<(), String> {
1403        encode_base64(writer, value)
1404    }
1405}
1406
1407impl<C> KdbxParse<C> for Vec<u8> {
1408    fn parse<R: Read>(
1409        reader: &mut EventReader<R>,
1410        name: OwnedName,
1411        attributes: Vec<OwnedAttribute>,
1412        _context: &mut C,
1413    ) -> Result<Option<Self>, String> {
1414        //decode_optional_string(reader, name, attributes)
1415        //Ok(decode_base64(reader, name, attributes)?.map(|v| Some(v.try_into().map_err(|_| "")?))?)
1416        Ok(Some(
1417            decode_base64(reader, name, attributes)?
1418                .try_into()
1419                .map_err(|_| "")?,
1420        ))
1421    }
1422}
1423
1424impl<C> KdbxSerialize<C> for Vec<u8> {
1425    fn serialize2<W: Write>(
1426        writer: &mut EventWriter<W>,
1427        value: Self,
1428        _context: &mut C,
1429    ) -> Result<(), String> {
1430        encode_base64(writer, value)
1431    }
1432}
1433
1434impl<C> KdbxParse<C> for HashMap<String, String> {
1435    fn parse<R: Read>(
1436        reader: &mut EventReader<R>,
1437        name: OwnedName,
1438        attributes: Vec<OwnedAttribute>,
1439        _context: &mut C,
1440    ) -> Result<Option<Self>, String> {
1441        Ok(Some(decode_custom_data(reader, name, attributes)?))
1442    }
1443}
1444
1445impl<C> KdbxSerialize<C> for HashMap<String, String> {
1446    fn serialize2<W: Write>(
1447        writer: &mut EventWriter<W>,
1448        value: Self,
1449        _context: &mut C,
1450    ) -> Result<(), String> {
1451        encode_custom_data(writer, value)
1452    }
1453}
1454
1455/// Various times about password or group item
1456#[derive(Clone, Debug, Default, KdbxParse, KdbxSerialize)]
1457//#[derive(Debug, Default, KdbxParse)]
1458#[cfg_attr(test, derive(PartialEq))]
1459pub struct Times {
1460    /// Time item was first created
1461    creation_time: DateTime<Utc>,
1462    /// Time item was last modified
1463    last_modification_time: DateTime<Utc>,
1464    /// Time item was last accessed
1465    last_access_time: DateTime<Utc>,
1466    /// Time item should expire or has expired
1467    expiry_time: DateTime<Utc>,
1468    /// Should item expire?
1469    expires: bool,
1470    /// Number of times item has been used
1471    usage_count: i32,
1472    /// Last time item has been moved in database
1473    location_changed: DateTime<Utc>,
1474}
1475
1476#[derive(Clone, Debug, Default, KdbxParse, KdbxSerialize)]
1477#[cfg_attr(test, derive(PartialEq))]
1478struct ProtectedString {
1479    key: String,
1480    value: ProtectedValue,
1481}
1482
1483#[derive(Clone, Debug)]
1484#[cfg_attr(test, derive(PartialEq))]
1485pub enum ProtectedValue {
1486    Unprotected(String),
1487    Protected(usize, Vec<u8>),
1488}
1489
1490use protected_stream::CipherValue;
1491
1492impl ProtectedValue {
1493    pub fn unprotect(&self, cipher: &mut CipherValue) -> Result<String, String> {
1494        match self {
1495            Self::Unprotected(ref v) => Ok(v.clone()),
1496            Self::Protected(offset, bytes) => {
1497                let mut value = bytes.clone();
1498                cipher.apply_keystream_pos(&mut value, *offset);
1499                String::from_utf8(value).map_err(|_| "Invalid UTF-8".to_string())
1500            }
1501        }
1502    }
1503}
1504
1505impl Default for ProtectedValue {
1506    fn default() -> Self {
1507        Self::Unprotected("".to_string())
1508    }
1509}
1510
1511impl KdbxParse<KdbxContext> for ProtectedValue {
1512    fn parse<R: Read>(
1513        reader: &mut EventReader<R>,
1514        name: OwnedName,
1515        attributes: Vec<OwnedAttribute>,
1516        context: &mut KdbxContext,
1517    ) -> Result<Option<Self>, String> {
1518        let protected = attributes.iter().filter(|a| a.name.local_name == "Protected").last().map(|v| v.value.to_ascii_lowercase() == "true").unwrap_or(false);
1519        if protected {
1520            decode_optional_base64(reader, name, attributes).map(|o| o.map(|v| { let offset = context.inner_cipher_position; context.inner_cipher_position += v.len(); Self::Protected(offset, v)}))
1521        } else {
1522            decode_optional_string(reader, name, attributes).map(|o| o.map(|v| Self::Unprotected(v)))
1523        }
1524    }
1525}
1526
1527impl<C> KdbxSerialize<C> for ProtectedValue {
1528    fn serialize2<W: Write>(
1529        _writer: &mut EventWriter<W>,
1530        _value: Self,
1531        _context: &mut C,
1532    ) -> Result<(), String> {
1533        //encode_string(writer, &value)
1534        Ok(())
1535    }
1536}
1537
1538#[derive(Clone, Debug, Default, KdbxParse, KdbxSerialize)]
1539#[cfg_attr(test, derive(PartialEq))]
1540struct ProtectedBinary {
1541    key: String,
1542    value: BinaryRef,
1543}
1544
1545#[derive(Clone, Debug)]
1546#[cfg_attr(test, derive(PartialEq))]
1547struct BinaryRef(Vec<u8>);
1548
1549impl BinaryRef {
1550}
1551
1552impl Default for BinaryRef {
1553    fn default() -> Self {
1554        Self(vec![])
1555    }
1556}
1557
1558impl KdbxParse<KdbxContext> for BinaryRef {
1559    fn parse<R: Read>(
1560        reader: &mut EventReader<R>,
1561        _name: OwnedName,
1562        attributes: Vec<OwnedAttribute>,
1563        context: &mut KdbxContext,
1564    ) -> Result<Option<Self>, String> {
1565        use std::str::FromStr;
1566        let id = attributes.iter().filter(|a| a.name.local_name == "Ref").last().and_then(|v| usize::from_str(v.value.as_str()).ok()).unwrap_or(0);
1567        loop {
1568            let event = reader.next().unwrap();
1569            match event {
1570                XmlEvent::StartDocument { .. } => {
1571                    return Err("Malformed XML document".to_string());
1572                }
1573                XmlEvent::EndDocument { .. } => {
1574                    return Err("Malformed XML document".to_string());
1575                }
1576                XmlEvent::StartElement { .. } => {
1577                    reader.skip().map_err(|e| format!("Malformed XML document: {e}"))?;
1578                }
1579                XmlEvent::EndElement { .. } => {
1580                    return Ok(Some(Self(context.binaries.get(id).map(|v| v.clone()).unwrap_or_else(|| vec![]))));
1581                }
1582                _ => {}
1583            }
1584        }
1585    }
1586}
1587
1588impl<C> KdbxSerialize<C> for BinaryRef {
1589    fn serialize2<W: Write>(
1590        _writer: &mut EventWriter<W>,
1591        _value: Self,
1592        _context: &mut C,
1593    ) -> Result<(), String> {
1594        //encode_string(writer, &value)
1595        Ok(())
1596    }
1597}
1598
1599
1600/// Group of password entries and subgroups
1601#[derive(Clone, Debug, Default, KdbxParse, KdbxSerialize, Getters)]
1602pub struct Group {
1603    #[keepass_db(element = "UUID")]
1604    uuid: Uuid,
1605    name: String,
1606    /// Additional notes about group
1607    notes: String,
1608    /// Group Icon unless a custom icon is provided
1609    #[keepass_db(element = "IconID")]
1610    icon_id: u32,
1611    /// Provides a custom icon for the group overiding icon_id
1612    #[keepass_db(element = "CustomIconUUID")]
1613    custom_icon_uuid: Option<Uuid>,
1614    times: Times,
1615    is_expanded: bool,
1616    default_auto_type_sequence: String,
1617    enable_auto_type: bool,
1618    enable_searching: bool,
1619    last_top_visible_entry: Uuid,
1620    // TODO custom_data: CustomData,
1621    previous_parent_group: Option<Uuid>,
1622    tags: Option<String>,  // TODO Should be a Vec
1623    #[keepass_db(flatten)]
1624    #[getter(rename = "entries")]
1625    entry: Vec<Entry>,
1626    #[keepass_db(flatten)]
1627    #[getter(rename = "groups")]
1628    group: Vec<Group>,
1629}
1630
1631impl Group {
1632//    pub fn groups(&self) -> Iter<'_, Group> {
1633//        self.group.iter()
1634//    }
1635//
1636//    pub fn entries(&self) -> Iter<'_, Entry> {
1637//        self.entry.iter()
1638//    }
1639
1640    // Iterate over all groups in database
1641    pub fn all_groups(&self) -> GroupIter {
1642        return GroupIter {
1643            first: true,
1644            group: self,
1645            children: self.group.iter(),
1646            next_group: None,
1647        }
1648    }
1649
1650    // Iterate over all password entries in database
1651    pub fn all_entries(&self) -> EntryIter {
1652        let mut groups = self.all_groups();
1653        return EntryIter {
1654            entries: groups.next().map(|e| e.entries().iter()),
1655            groups,
1656        }
1657    }
1658}
1659
1660pub struct GroupIter<'a> {
1661    first: bool,
1662    group: &'a Group,
1663    children: Iter<'a, Group>,
1664    next_group: Option<Box<GroupIter<'a>>>,
1665}
1666
1667impl<'a> Iterator for GroupIter<'a> {
1668    type Item = &'a Group;
1669
1670    fn next(&mut self) -> Option<Self::Item> {
1671        if self.first {
1672            self.first = false;
1673            self.next_group = self.children.next().map(|c| Box::new(c.all_groups()));
1674            Some(self.group)
1675        } else {
1676            if let Some(ref mut child) = self.next_group {
1677                if let Some(g) = child.next() {
1678                    Some(g)
1679                } else {
1680                    self.next_group = self.children.next().map(|c| Box::new(c.all_groups()));
1681                    if let Some(ref mut child) = self.next_group {
1682                        if let Some(g) = child.next() {
1683                            Some(g)
1684                        } else {
1685                            None
1686                        }
1687                    } else {
1688                        None
1689                    }
1690                }
1691            } else {
1692                None
1693            }
1694        }
1695    }
1696}
1697
1698/// Iterator over password [`Entry`]
1699pub struct EntryIter<'a> {
1700    entries: Option<Iter<'a, Entry>>,
1701    groups: GroupIter<'a>,
1702}
1703
1704impl<'a> Iterator for EntryIter<'a> {
1705    type Item = &'a Entry;
1706
1707    fn next(&mut self) -> Option<Self::Item> {
1708        while let Some(ref mut d) = self.entries {
1709            if let Some(e) = d.next() {
1710                return Some(e);
1711            } else {
1712                self.entries = self.groups.next().map(|e| e.entries().iter());
1713            }
1714        }
1715        None
1716    }
1717}
1718
1719#[derive(Clone, Debug, Default, KdbxParse, KdbxSerialize)]
1720#[cfg_attr(test, derive(PartialEq))]
1721struct Association {
1722    window: String,
1723    keystroke_sequence: String,
1724}
1725
1726#[derive(Clone, Debug, Default, KdbxParse, KdbxSerialize)]
1727#[cfg_attr(test, derive(PartialEq))]
1728struct AutoType {
1729    enabled: bool,
1730    data_transfer_obfuscation: i64,
1731    default_sequence: Option<String>,
1732    #[keepass_db(flatten)]
1733    association: Vec<Association>,
1734}
1735
1736/// Password entry
1737#[derive(Clone, Debug, Default, KdbxParse, KdbxSerialize, Getters)]
1738#[cfg_attr(test, derive(PartialEq))]
1739pub struct Entry {
1740    /// UUID for password entry
1741    #[keepass_db(element = "UUID")]
1742    uuid: Uuid,
1743    /// Entry Icon unless a custom icon is provided
1744    #[keepass_db(element = "IconID")]
1745    icon_id: u32,
1746    /// Provides a custom icon for the group overiding icon_id
1747    #[keepass_db(element = "CustomIconUUID")]
1748    custom_icon_uuid: Option<Uuid>,
1749    /// Foreground text color of entry
1750    foreground_color: String,
1751    /// Background text color of entry
1752    background_color: String,
1753    #[keepass_db(element = "OverrideURL")]
1754    override_url: String,
1755    quality_check: Option<bool>,
1756    /// Tags for password entry
1757    tags: String,
1758    previous_parent_group: Option<Uuid>,
1759    times: Times,
1760    custom_data: Vec<Item>,
1761    #[keepass_db(flatten)]
1762    #[getter(skip)]
1763    string: Vec<ProtectedString>,
1764    #[keepass_db(flatten)]
1765    #[getter(skip)]
1766    binary: Vec<ProtectedBinary>,
1767    #[getter(skip)]
1768    auto_type: AutoType,
1769    history: Option<Vec<Entry>>,
1770}
1771
1772const TITLE_FIELD: &str = "Title";
1773const USER_NAME_FIELD: &str = "UserName";
1774const PASSWORD_FIELD: &str = "Password";
1775const URL_FIELD: &str = "URL";
1776const NOTES_FIELD: &str = "Notes";
1777
1778impl Entry {
1779    pub fn title(&self) -> ProtectedValue {
1780        self.string.iter().find(|p| p.key == TITLE_FIELD).map(|p| p.value.clone()).unwrap_or(ProtectedValue::Unprotected("".to_string()))
1781    }
1782
1783    pub fn username(&self) -> ProtectedValue {
1784        self.string.iter().find(|p| p.key == USER_NAME_FIELD).map(|p| p.value.clone()).unwrap_or(ProtectedValue::Unprotected("".to_string()))
1785    }
1786
1787    pub fn password(&self) -> ProtectedValue {
1788        self.string.iter().find(|p| p.key == PASSWORD_FIELD).map(|p| p.value.clone()).unwrap_or(ProtectedValue::Unprotected("".to_string()))
1789    }
1790
1791    pub fn url(&self) -> ProtectedValue {
1792        self.string.iter().find(|p| p.key == URL_FIELD).map(|p| p.value.clone()).unwrap_or(ProtectedValue::Unprotected("".to_string()))
1793    }
1794
1795    pub fn notes(&self) -> ProtectedValue {
1796        self.string.iter().find(|p| p.key == NOTES_FIELD).map(|p| p.value.clone()).unwrap_or(ProtectedValue::Unprotected("".to_string()))
1797    }
1798
1799    pub fn get_binary(&self, index: usize) -> (&str, &[u8]) {
1800        (self.binary[index].key.as_ref(), self.binary[index].value.0.as_ref())
1801    }
1802}
1803
1804#[derive(Clone, Debug, Default, KdbxParse, KdbxSerialize)]
1805pub struct DeletedObject {
1806    #[keepass_db(element = "UUID")]
1807    uuid: Uuid,
1808    deletion_time: DateTime<Utc>,
1809}
1810
1811#[derive(Clone, Debug, Default, KdbxParse, KdbxSerialize, Getters)]
1812pub struct Root {
1813    #[keepass_db(flatten)]
1814    group: Group,
1815    deleted_objects: Vec<DeletedObject>,
1816}
1817
1818/// Testing doc macros
1819/// ```
1820/// assert!(true);
1821/// ```
1822/// Does it work?
1823#[derive(Clone, Debug, Default, KdbxParse, KdbxSerialize)]
1824pub struct KeePassFile {
1825    meta: Meta,
1826    root: Root,
1827}
1828
1829impl KeePassFile {
1830    pub fn root_group(&self) -> &Group {
1831        &self.root.group
1832    }
1833}
1834
1835const KDBX_MAGIC: u32 = 0x9AA2D903;
1836
1837const KDBX1_MAGIC_TYPE: u32 = 0xB54BFB65;
1838const KDBX2_BETA_MAGIC_TYPE: u32 = 0xB54BFB66;
1839const KDBX2_MAGIC_TYPE: u32 = 0xB54BFB67;
1840
1841/// A KeePass database
1842#[derive(Default)]
1843pub struct KeePassDoc {
1844    pub file: KeePassFile,
1845    pub cipher: CipherValue,
1846}
1847
1848impl KeePassDoc {
1849    /// Read in an existing KeePass database
1850    pub fn load_file(filename: &str, key: &Key) -> io::Result<Self> {
1851        let composite_key = key.composite_key();
1852
1853        let mut file = File::open(filename)?;
1854        let magic = file.read_u32::<LittleEndian>()?;
1855        let magic_type = file.read_u32::<LittleEndian>()?;
1856
1857        if magic != KDBX_MAGIC {
1858            eprintln!("Invalid database file\n");
1859            process::exit(1);
1860        }
1861
1862        let mut custom_data = HashMap::<String, Vec<u8>>::new();
1863        let mut custom_data2 = HashMap::<_, _>::new();
1864
1865        match magic_type {
1866            KDBX1_MAGIC_TYPE => {
1867                use kdb1::read_kdb1_header;
1868                read_kdb1_header(&mut file, &key)?;
1869                return Ok(KeePassDoc::default());
1870            }
1871            // KDBX2_BETA_MAGIC_TYPE => {
1872            //     // XXX Untested
1873            //     eprintln!("KeePass 2.x Beta files not supported\n");
1874            //     process::exit(1);
1875            // },
1876            KDBX2_MAGIC_TYPE | KDBX2_BETA_MAGIC_TYPE => {
1877                println!("Opening KeePass 2.x database");
1878            }
1879            _ => {
1880                // XXX Untested
1881                eprintln!("Unknown KeePass database format\n");
1882                process::exit(1);
1883            }
1884        };
1885
1886        // Version field is defined as uint32_t, but it's broken up into
1887        // major and minor 16-bit components. Due to the nature of little
1888        // endian, this puts the minor part first.
1889        let minor_version = file.read_u16::<LittleEndian>()?;
1890        let major_version = file.read_u16::<LittleEndian>()?;
1891        match major_version {
1892            3 => {
1893                unsafe {
1894                    KDBX4 = false;
1895                };
1896                custom_data.insert(
1897                    KDF_PARAM_UUID.to_string(),
1898                    KDF_AES_KDBX3.as_bytes().to_vec(),
1899                );
1900            }
1901            4 => {}
1902            1 => {
1903                custom_data.insert(
1904                    KDF_PARAM_UUID.to_string(),
1905                    KDF_AES_KDBX3.as_bytes().to_vec(),
1906                );
1907            }
1908            _ => {
1909                eprintln!(
1910                    "Unsupported KeePass 2.x database version ({}.{})\n",
1911                    major_version, minor_version
1912                );
1913                process::exit(1);
1914            }
1915        };
1916        let mut tlvs = HashMap::new();
1917        let mut inner_tlvs = BTreeMap::<u8, Vec<Vec<u8>>>::new();
1918        inner_tlvs.insert(3u8, vec![]);
1919        loop {
1920            let tlv_type = file.read_u8()?;
1921            let tlv_len = if major_version == 4 {
1922                file.read_u32::<LittleEndian>()?
1923            } else {
1924                // XXX Untested
1925                file.read_u16::<LittleEndian>()? as u32
1926            };
1927            let mut tlv_data = vec![0; tlv_len as usize];
1928            file.read_exact(&mut tlv_data)?;
1929            debug!("TLV({}, {}): {:?}", tlv_type, tlv_len, tlv_data);
1930            match tlv_type {
1931                0 => {
1932                    break;
1933                }
1934                5 => {
1935                    custom_data.insert(KDF_PARAM_SALT.to_string(), tlv_data.clone());
1936                    custom_data2.insert(KDF_PARAM_SALT.to_string(), MapValue::ByteArray(tlv_data));
1937                }
1938                6 => {
1939                    custom_data.insert(KDF_PARAM_ROUNDS.to_string(), tlv_data.clone());
1940                    custom_data2.insert(
1941                        KDF_PARAM_ROUNDS.to_string(),
1942                        MapValue::UInt64(u64::from_le_bytes(tlv_data[0..8].try_into().unwrap())),
1943                    );
1944                }
1945                8 => {
1946                    inner_tlvs.insert(2u8, vec![tlv_data]);
1947                }
1948                10 => {
1949                    inner_tlvs.insert(1u8, vec![tlv_data]);
1950                }
1951                11 => {
1952                    custom_data2 = load_map(&tlv_data).unwrap();
1953                    let kdf_parameters = &tlv_data;
1954                    let mut c = Cursor::new(kdf_parameters);
1955                    let variant_minor = c.read_u8()?;
1956                    let variant_major = c.read_u8()?;
1957                    if variant_major != 1 {
1958                        eprintln!(
1959                            "Unsupported variant dictionary version ({}.{})\n",
1960                            variant_major, variant_minor
1961                        );
1962                        process::exit(1);
1963                    };
1964
1965                    loop {
1966                        let item_type = c.read_u8()?;
1967                        if item_type == 0 {
1968                            break;
1969                        }
1970                        let item_key_len = c.read_u32::<LittleEndian>()?;
1971                        let mut item_key = vec![0; item_key_len as usize];
1972                        c.read_exact(&mut item_key)?;
1973                        let item_key_str = String::from_utf8_lossy(&item_key).to_owned();
1974                        let item_value_len = c.read_u32::<LittleEndian>()?;
1975                        let mut item_value = vec![0; item_value_len as usize];
1976                        c.read_exact(&mut item_value)?;
1977                        debug!("K: {}, V: {:0x?}", item_key_str, item_value);
1978                        custom_data.insert(item_key_str.to_owned().to_string(), item_value);
1979                    }
1980                }
1981                _ => {
1982                    tlvs.insert(tlv_type, tlv_data);
1983                }
1984            }
1985        }
1986
1987        //let src = &tlvs[&2u8];
1988        //let mut uuid = [0; 16];
1989        //let b = &src[..uuid.len()];
1990        //uuid.copy_from_slice(b);
1991        //let d = Builder::from_bytes(uuid).build();
1992        let cipher_id = Uuid::from_slice(&tlvs[&2u8]).unwrap();
1993        println!("D: {:?}", cipher_id);
1994        if cipher_id != CIPHER_ID_AES256_CBC {
1995            eprintln!("Unknown cipher\n");
1996            process::exit(1);
1997        }
1998        println!("AES");
1999        let mut c = Cursor::new(&tlvs[&3u8]);
2000        let compression_flags = c.read_u32::<LittleEndian>()?;
2001        enum Compression {
2002            None,
2003            Gzip,
2004        }
2005        let compress = match compression_flags {
2006            0 => {
2007                // XX Untested
2008                // eprintln!("Unsupported no compressed file\n");
2009                //process::exit(1);
2010                Compression::None
2011            }
2012            1 => {
2013                println!("Gzip compression");
2014                Compression::Gzip
2015            }
2016            _ => {
2017                // XX Untested
2018                eprintln!("Unsupported compression method\n");
2019                process::exit(1);
2020            }
2021        };
2022
2023        let master_seed = &tlvs[&4u8];
2024        let encryption_iv = &tlvs[&7u8];
2025
2026        //let mut header = vec![];
2027        let mut context = Context::new(&SHA256);
2028        let pos = file.seek(SeekFrom::Current(0))?;
2029        file.seek(SeekFrom::Start(0))?;
2030        let mut header = vec![0; (pos) as usize];
2031        file.read_exact(&mut header)?;
2032        file.seek(SeekFrom::Start(pos))?;
2033        context.update(&header);
2034        let digest = context.finish();
2035        if major_version == 4 {
2036            let mut expected_hash = [0; 32];
2037            file.read_exact(&mut expected_hash)?;
2038            if digest.as_ref() != expected_hash {
2039                eprintln!("Possible header corruption\n");
2040                process::exit(1);
2041            }
2042        }
2043
2044        let kdf_id = Uuid::from_slice(&custom_data[KDF_PARAM_UUID]).unwrap();
2045        println!("KDF: {:?}", kdf_id);
2046
2047        let transform_key = match kdf_id {
2048            x if x == KDF_AES_KDBX3 => {
2049                //unimplemented!("KDBX 3 AES-KDF not supported!");
2050                AesKdf::load(&custom_data2)?.transform_key(&composite_key)?
2051                // transform_aes_kdf(&composite_key, &custom_data)?
2052            }
2053            x if x == KDF_AES_KDBX4 => {
2054                unimplemented!("KDBX 4 AES-KDF not supported!");
2055            }
2056            x if x == KDF_ARGON2_D => {
2057                transform_argon2(&composite_key, &custom_data)?
2058                //unimplemented!("Argon2 KDF not supported!");
2059            }
2060            _ => {
2061                unimplemented!("Unknown");
2062            }
2063        };
2064
2065        println!("Key OUT: {:0x?}", transform_key);
2066
2067        println!("Calculating master key");
2068        let mut hmac_context = Context::new(&SHA512);
2069
2070        let mut master_key = master_seed.to_owned();
2071        master_key.extend(transform_key);
2072        let mut context = Context::new(&SHA256);
2073        context.update(&master_key);
2074        hmac_context.update(&master_key);
2075        hmac_context.update(&[1u8]);
2076        master_key = context.finish().as_ref().to_owned();
2077        let hmac_key_base = hmac_context.finish().as_ref().to_owned();
2078        println!("Master OUT: {:0x?}", master_key);
2079        println!("HMAC OUT: {:0x?}", hmac_key_base);
2080
2081        let mut hmac_context = Context::new(&SHA512);
2082        hmac_context.update(&[0xff; 8]);
2083        hmac_context.update(&hmac_key_base);
2084        let hmac_key = hmac_context.finish().as_ref().to_owned();
2085
2086        let mut hmac_tag = [0; 32];
2087        //println!("HMAC Tag: {:0x?}", hmac_tag);
2088        let hmac_key = hmac::Key::new(hmac::HMAC_SHA256, &hmac_key);
2089        if major_version == 4 {
2090            file.read_exact(&mut hmac_tag)?;
2091            println!("Verifying HMAC");
2092            hmac::verify(&hmac_key, &header, &hmac_tag).map_err(|_| io::Error::new(io::ErrorKind::Other, "Bad password or key file"))?;
2093            println!("Complete");
2094        }
2095
2096        let contents = if major_version == 4 {
2097            let mut ciphertext = vec![];
2098            for idx in 0.. {
2099                println!("Block {}", idx);
2100                file.read_exact(&mut hmac_tag)?;
2101                let block_size = file.read_u32::<LittleEndian>()?;
2102                if block_size == 0 {
2103                    break;
2104                }
2105                let mut block = vec![0; block_size as usize];
2106                file.read_exact(&mut block)?;
2107
2108                let mut hmac_context = Context::new(&SHA512);
2109                let mut buf = Cursor::new(Vec::new());
2110                buf.write_u64::<LittleEndian>(idx)?;
2111                hmac_context.update(buf.get_ref());
2112                hmac_context.update(&hmac_key_base);
2113                let hmac_key = hmac_context.finish().as_ref().to_owned();
2114                buf.write_u32::<LittleEndian>(block_size)?;
2115                buf.write(&block)?;
2116                let hmac_key = hmac::Key::new(hmac::HMAC_SHA256, &hmac_key);
2117                println!("Verifying HMAC");
2118                hmac::verify(&hmac_key, buf.get_ref(), &hmac_tag).unwrap();
2119                println!("Complete");
2120                ciphertext.extend(block);
2121            }
2122
2123            let data = decrypt(
2124                Cipher::aes_256_cbc(),
2125                &master_key,
2126                Some(encryption_iv),
2127                &ciphertext,
2128            )
2129            .unwrap();
2130            let mut gz: Box<dyn Read> = match compress {
2131                Compression::Gzip => Box::new(GzDecoder::new(Cursor::new(data))),
2132                Compression::None => Box::new(Cursor::new(data)),
2133            };
2134
2135            inner_tlvs = load_tlvs(&mut gz, major_version)?.0;
2136            let mut contents = String::new();
2137            gz.read_to_string(&mut contents)?;
2138            contents
2139        } else {
2140            /* KDBX 3.x format encrypts the database after breaking
2141             * the stream into blocks */
2142            let mut ciphertext = vec![];
2143            file.read_to_end(&mut ciphertext)?;
2144            let data = decrypt(
2145                Cipher::aes_256_cbc(),
2146                &master_key,
2147                Some(encryption_iv),
2148                &ciphertext,
2149            )
2150            .unwrap();
2151            let mut c = Cursor::new(data);
2152
2153            /* Start stream header is used to verify successful decrypt */
2154            let mut start_stream = vec![0; 32];
2155            c.read_exact(&mut start_stream)?;
2156            assert_eq!(&start_stream, &tlvs[&9u8]);
2157            println!("Master Key appears valid");
2158
2159            let mut buf = vec![];
2160            for idx in 0.. {
2161                println!("Block {}", idx);
2162                let block_id = c.read_u32::<LittleEndian>()?;
2163                assert_eq!(idx as u32, block_id);
2164                let mut block_hash_expected = vec![0; 32];
2165                c.read_exact(&mut block_hash_expected)?;
2166                let block_size = c.read_u32::<LittleEndian>()?;
2167                let mut block_data = vec![0; block_size as usize];
2168                c.read_exact(&mut block_data)?;
2169                let mut context = Context::new(&SHA256);
2170                context.update(&block_data);
2171                let block_hash = context.finish().as_ref().to_owned();
2172                if block_size == 0 {
2173                    break;
2174                }
2175                assert_eq!(block_hash_expected, block_hash, "Failed hash");
2176                buf.extend(block_data);
2177            }
2178            let mut gz: Box<dyn Read> = match compress {
2179                Compression::Gzip => Box::new(GzDecoder::new(Cursor::new(buf))),
2180                Compression::None => Box::new(Cursor::new(buf)),
2181            };
2182            let mut xml_file = File::create("data2.xml")?;
2183            let mut contents = String::new();
2184            gz.read_to_string(&mut contents)?;
2185            let _ = xml_file.write(&contents.as_bytes());
2186            // println!("{:#?}", &contents);
2187            if &contents[0..3] == "\u{feff}" {
2188                contents = contents[3..].to_string();
2189            }
2190            let package = parser::parse(&contents).unwrap();
2191            let document = package.as_document();
2192            let header_hash = evaluate_xpath(&document, "/KeePassFile/Meta/HeaderHash/text()")
2193                .expect("Missing header hash");
2194            if header_hash.string() != "" {
2195                println!("Header Hash: '{}'", header_hash.string());
2196                let expected_hash = base64.decode(&header_hash.string()).expect("Valid base64");
2197                if expected_hash != digest.as_ref() {
2198                    eprintln!("Possible header corruption\n");
2199                    process::exit(1);
2200                }
2201            }
2202            contents
2203        };
2204
2205        let default = vec![vec![1, 0, 0, 0]];
2206        let inner_stream_cipher = &inner_tlvs.get(&1u8).unwrap_or(&default)[0];  // Defaults to ARC4
2207        if inner_stream_cipher.len() != 4 {
2208            panic!("Invalid inner cipher");
2209        }
2210        let inner_cipher_type = u32::from_le_bytes(inner_stream_cipher[..].try_into().unwrap());
2211        println!("Inner Cipher: {inner_cipher_type}");
2212        let p_key = &inner_tlvs[&0x02u8][0];
2213        println!("p_key: {p_key:02x?} ({})", p_key.len());
2214        let mut inner_cipher = protected_stream::new_stream(inner_cipher_type, p_key).expect("Unknown inner cipher");
2215
2216        let mut xml_file = File::create("data.xml")?;
2217        let _ = xml_file.write(&contents.as_bytes());
2218        const KDBX4_TIME_OFFSET: i64 = 62135596800;
2219        println!("XML Body len: {}", contents.len());
2220        let package = parser::parse(&contents).unwrap();
2221        let document = package.as_document();
2222        println!(
2223            "Root element: {}",
2224            document.root().children()[0]
2225                .element()
2226                .unwrap()
2227                .name()
2228                .local_part()
2229        );
2230        let database_name_node = evaluate_xpath(&document, "/KeePassFile/Meta/DatabaseName/text()")
2231            .expect("Missing database name");
2232        println!("Database Name: {}", database_name_node.string());
2233        let database_name_changed_node =
2234            evaluate_xpath(&document, "/KeePassFile/Meta/DatabaseNameChanged/text()")
2235                .expect("Missing database name changed");
2236        let change_time = if database_name_changed_node.string() == "" {
2237            "<missing>".to_owned()
2238        } else {
2239            let datetime: DateTime<Local> = if major_version <= 3 {
2240                DateTime::parse_from_rfc3339(&database_name_changed_node.string())
2241                    .expect("failed to parse timestamp")
2242                    .with_timezone(&Local)
2243            } else {
2244                let timestamp =
2245                    Cursor::new(base64.decode(&database_name_changed_node.string()).expect("Valid base64"))
2246                        .read_i64::<LittleEndian>()?
2247                        - KDBX4_TIME_OFFSET;
2248                //let naive = NaiveDateTime::from_timestamp(timestamp, 0);
2249                //let datetime: DateTime<Utc> = DateTime::from_utc(naive, Utc);
2250                Local.timestamp_opt(timestamp, 0).unwrap()
2251            };
2252            datetime.format("%Y-%m-%d %l:%M:%S %p %Z").to_string()
2253        };
2254        println!("Database Name Changed: {}", change_time);
2255
2256        let xpath_context = XPathContext::new();
2257        let protected_nodes = evaluate_xpath(&document, "//Value[@Protected = 'True']/text()")
2258            .expect("Missing database entries");
2259        let xpath_current = Factory::new()
2260            .build(".")
2261            .expect("Failed to compile XPath")
2262            .expect("Empty XPath expression");
2263        let mut protected_offset = 0;
2264        match protected_nodes {
2265            Value::Nodeset(nodes) => {
2266                for entry in nodes.document_order() {
2267                    let p = xpath_current
2268                        .evaluate(&xpath_context, entry)
2269                        .expect("Missing entry text");
2270                    println!("P: {:?}, ('{}')", p, p.string());
2271                    let mut p_ciphertext = base64.decode(&p.string()).expect("Valid base64");
2272                    println!("Protected Value Ciphertext: {p_ciphertext:#04X?} (+{protected_offset})");
2273                    protected_offset += p_ciphertext.len();
2274                    inner_cipher.apply_keystream(&mut p_ciphertext);
2275                    println!("Protected Value Plaintext: {p_ciphertext:#04X?}");
2276                    let value = String::from_utf8(p_ciphertext)
2277                        .unwrap_or("«Failed to decrypt value»".to_owned());
2278                    println!("Protected Value: {:?}", &value);
2279                    match entry {
2280                        sxd_xpath::nodeset::Node::Text(t) => {
2281                            t.set_text(&value);
2282                        }
2283                        _ => {}
2284                    }
2285                }
2286            }
2287            _ => {
2288                panic!("XML corruption");
2289            }
2290        }
2291        let xpath_username = Factory::new()
2292            .build("String[Key/text() = 'UserName']/Value/text()")
2293            .expect("Failed to compile XPath")
2294            .expect("Empty XPath expression");
2295        let xpath_last_mod_time = Factory::new()
2296            .build("Times/LastModificationTime/text()")
2297            .expect("Failed to compile XPath")
2298            .expect("Empty XPath expression");
2299        let xpath_password = Factory::new()
2300            .build("String[Key/text() = 'Password']/Value[@Protected = 'True']/text()")
2301            .expect("Failed to compile XPath")
2302            .expect("Empty XPath expression");
2303        //let entry_nodes = evaluate_xpath(&document, "/KeePassFile/Root/Group/Entry").expect("Missing database entries");
2304        let entry_nodes = evaluate_xpath(&document, "//Entry").expect("Missing database entries");
2305        match entry_nodes {
2306            Value::Nodeset(nodes) => {
2307                for entry in nodes.document_order() {
2308                    //let n = evaluate_xpath(&document, "/KeePassFile/Root/Group/Entry/String[Key/text() = 'UserName']/Value/text()").expect("Missing entry username");
2309                    let n = xpath_username
2310                        .evaluate(&xpath_context, entry)
2311                        .expect("Missing entry username");
2312                    let t = xpath_last_mod_time
2313                        .evaluate(&xpath_context, entry)
2314                        .expect("Missing entry modification");
2315                    let p = xpath_password
2316                        .evaluate(&xpath_context, entry)
2317                        .expect("Missing entry password");
2318                    println!("Name: {}", n.string());
2319                    let change_time = if database_name_changed_node.string() == "" {
2320                        "<missing>".to_owned()
2321                    } else {
2322                        let datetime: DateTime<Local> = if major_version <= 3 {
2323                            DateTime::parse_from_rfc3339(&t.string())
2324                                .expect("failed to parse timestamp")
2325                                .with_timezone(&Local)
2326                        } else {
2327                            println!("Inner: {:?}", &t.string());
2328                            let timestamp =
2329                                Cursor::new(base64.decode(&t.string()).expect("Valid base64"))
2330                                    .read_i64::<LittleEndian>()?
2331                                    - KDBX4_TIME_OFFSET;
2332                            //let naive = NaiveDateTime::from_timestamp(timestamp, 0);
2333                            //let datetime: DateTime<Utc> = DateTime::from_utc(naive, Utc);
2334                            Local.timestamp_opt(timestamp, 0).unwrap()
2335                        };
2336                        datetime.format("%Y-%m-%d %l:%M:%S %p %Z").to_string()
2337                    };
2338                    println!("Changed: {}", change_time);
2339                    println!("Password: {:?}", p.string());
2340                }
2341            }
2342            _ => {
2343                panic!("XML corruption");
2344            }
2345        };
2346
2347        let content_cursor = Cursor::new(&contents);
2348        let mut reader = ParserConfig::new()
2349            .cdata_to_characters(true)
2350            .create_reader(content_cursor);
2351        let mut my_doc = None;
2352        loop {
2353            let event = reader.next().unwrap();
2354            match event {
2355                XmlEvent::StartDocument { .. } => {
2356                    println!("Start");
2357                }
2358                XmlEvent::StartElement {
2359                    name, attributes, ..
2360                } => {
2361                    // TODO Check top-level tag name
2362                    let mut context = KdbxContext::default();
2363                    context.major_version = major_version;
2364                    context.binaries = inner_tlvs.remove(&3u8).unwrap();
2365                    my_doc = Some(KeePassFile::parse(&mut reader, name, attributes, &mut context)
2366                        .map_err(|x| ::std::io::Error::new(::std::io::ErrorKind::Other, x))?
2367                        .unwrap());
2368                }
2369                XmlEvent::EndDocument => {
2370                    println!("End");
2371                    break;
2372                }
2373                _ => {}
2374            }
2375        }
2376
2377        Ok(KeePassDoc {
2378            file: my_doc.expect("Missing top-level element"),
2379            cipher: inner_cipher,
2380        })
2381    }
2382
2383    #[cfg(feature = "write")]
2384    pub fn save_file(&self, major_version: u16) -> io::Result<()> {
2385        let mut file = File::create("data-out.kdbx")?;
2386        let minor_version = 0;
2387        let mut header = vec![];
2388        header.write_u32::<LittleEndian>(KDBX_MAGIC)?;
2389        header.write_u32::<LittleEndian>(KDBX2_MAGIC_TYPE)?;
2390        header.write_u16::<LittleEndian>(minor_version)?;
2391        header.write_u16::<LittleEndian>(major_version)?;
2392        let mut key = Key::new();
2393        key.set_user_password("asdf");
2394        let composite_key = key.composite_key();
2395        let kdf = AesKdf::default();
2396        let mut custom_data = HashMap::new();
2397        custom_data.insert(
2398            KDF_PARAM_UUID.to_string(),
2399            MapValue::ByteArray(KDF_AES_KDBX3.into_bytes().to_vec()),
2400        );
2401        kdf.save(&mut custom_data);
2402        let transform_key = kdf
2403            .transform_key(&composite_key)
2404            .expect("Failed to transform key");
2405        let master_seed = [0u8; 32];
2406        let iv = [0u8; 16];
2407        let stream_cipher = 2u32;
2408        let stream_key = [0u8; 32];
2409        let mut tlvs = BTreeMap::new();
2410        tlvs.insert(
2411            TlvType::MasterSeed.to_u8().unwrap(),
2412            vec![master_seed.to_vec()],
2413        );
2414        tlvs.insert(
2415            TlvType::CipherId.to_u8().unwrap(),
2416            vec![CIPHER_ID_AES256_CBC.into_bytes().to_vec()],
2417        );
2418        tlvs.insert(TlvType::EncryptionIv.to_u8().unwrap(), vec![iv.to_vec()]);
2419        tlvs.insert(
2420            TlvType::CompressionFlags.to_u8().unwrap(),
2421            vec![Compression::None.to_u32().unwrap().to_le_bytes().to_vec()],
2422        );
2423        let start_stream = vec![0; 32]; // TODO Randomize this
2424        if major_version < 4 {
2425            tlvs.insert(
2426                TlvType::TransformSeed.to_u8().unwrap(),
2427                vec![master_seed.to_vec()],
2428            );
2429            tlvs.insert(
2430                TlvType::TransformRounds.to_u8().unwrap(),
2431                vec![match custom_data[KDF_PARAM_ROUNDS] {
2432                    MapValue::UInt64(x) => x.to_le_bytes().to_vec(),
2433                    _ => panic!("Wrong"),
2434                }],
2435            );
2436            tlvs.insert(
2437                TlvType::StreamStartBytes.to_u8().unwrap(),
2438                vec![start_stream.to_vec()],
2439            );
2440            tlvs.insert(
2441                TlvType::ProtectedStreamKey.to_u8().unwrap(),
2442                vec![stream_key.to_vec()],
2443            );
2444            tlvs.insert(
2445                TlvType::InnerRandomStreamId.to_u8().unwrap(),
2446                vec![stream_cipher.to_le_bytes().to_vec()],
2447            );
2448        } else {
2449            tlvs.insert(
2450                TlvType::KdfParameters.to_u8().unwrap(),
2451                vec![save_map(&custom_data)],
2452            );
2453        }
2454        header.append(&mut save_tlvs(&mut io::sink(), &tlvs, major_version).unwrap());
2455        file.write(&header)?;
2456        let mut context = Context::new(&SHA256);
2457        context.update(&header);
2458        let digest = context.finish();
2459        if major_version >= 4 {
2460            file.write(digest.as_ref())?;
2461            // header.append(&mut digest.as_ref().to_owned());
2462        }
2463
2464        let mut master_key = master_seed.to_vec();
2465        master_key.extend(transform_key);
2466        let mut context = Context::new(&SHA256);
2467        let mut hmac_context = Context::new(&SHA512);
2468        context.update(&master_key);
2469        hmac_context.update(&master_key);
2470        hmac_context.update(&[1u8]);
2471        master_key = context.finish().as_ref().to_owned();
2472        let hmac_key_base = hmac_context.finish().as_ref().to_owned();
2473
2474        let mut hmac_context = Context::new(&SHA512);
2475        hmac_context.update(&[0xff; 8]);
2476        hmac_context.update(&hmac_key_base);
2477        let hmac_key = hmac_context.finish().as_ref().to_owned();
2478
2479        let hmac_key = hmac::Key::new(hmac::HMAC_SHA256, &hmac_key);
2480        let hmac_tag = hmac::sign(&hmac_key, &header);
2481        if major_version >= 4 {
2482            file.write(hmac_tag.as_ref())?;
2483        } else {
2484            let output = Cursor::new(Vec::<u8>::new());
2485            let mut context = KdbxContext::default();
2486            context.major_version = major_version;
2487            let mut writer = xml::writer::EventWriter::new(output);
2488            writer
2489                .write(xml::writer::XmlEvent::start_element("KeePassFile"))
2490                .expect("Success!");
2491            KeePassFile::serialize2(&mut writer, self.file.clone(), &mut context).unwrap();
2492            writer
2493                .write(xml::writer::XmlEvent::end_element())
2494                .expect("Success!");
2495            let output = writer.into_inner().into_inner();
2496            let mut buf = Cursor::new(Vec::<u8>::new());
2497            buf.write_all(&start_stream).unwrap();
2498            buf.write_all(&0u32.to_le_bytes()).unwrap();
2499            let mut context = Context::new(&SHA256);
2500            context.update(&output);
2501            buf.write_all(&context.finish().as_ref().to_owned()).unwrap();
2502            buf.write_all(&(output.len() as u32).to_le_bytes()).unwrap();
2503            buf.write_all(&output).unwrap();
2504            buf.write_all(&1u32.to_le_bytes()).unwrap();
2505            let context = Context::new(&SHA256);
2506            buf.write_all(&context.finish().as_ref().to_owned()).unwrap();
2507            //buf.write_all(&[0u8; 32]).unwrap();
2508            buf.write_all(&0u32.to_le_bytes()).unwrap();
2509            let data = encrypt(
2510                Cipher::aes_256_cbc(),
2511                &master_key,
2512                Some(&iv),
2513                &buf.into_inner(),
2514            ).unwrap();
2515            file.write_all(&data).unwrap();
2516            return Ok(());
2517        }
2518
2519        let output = BlockWriter::new(&hmac_key_base, file);
2520        let cipher = Cipher::aes_256_cbc();
2521        let mut output = Crypto::new(cipher, &master_key, Some(&iv), output).unwrap();
2522
2523        if major_version >= 4 {
2524            let mut inner_tlvs = BTreeMap::new();
2525            inner_tlvs.insert(1, vec![stream_cipher.to_le_bytes().to_vec()]);
2526            inner_tlvs.insert(2, vec![stream_key.to_vec()]);
2527            save_tlvs(&mut output, &inner_tlvs, major_version).unwrap();
2528        }
2529        let mut writer = xml::writer::EventWriter::new(output);
2530        writer
2531            .write(xml::writer::XmlEvent::start_element("KeePassFile"))
2532            .expect("Success!");
2533        KeePassFile::serialize2(&mut writer, self.file.clone(), &mut KdbxContext::default()).unwrap();
2534        writer
2535            .write(xml::writer::XmlEvent::end_element())
2536            .expect("Success!");
2537        let mut output = writer.into_inner();
2538        output.flush()?;
2539        // output.flush()?;
2540        // drop(output);
2541
2542        Ok(())
2543    }
2544}
2545
2546impl std::fmt::Debug for KeePassDoc {
2547    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2548        f.debug_struct("KeePassDoc")
2549            .field("file", &self.file)
2550            .finish()
2551    }
2552}