wala-rust

Content-adressed HTTP file server
Info | Log | Files | Refs | README | LICENSE

main.rs (7057B)


      1 #![crate_name = "wala_send"]
      2 
      3 //! This is a convenience tool to upload content to wala under mutable references.
      4 //!
      5 //! It is still in a very unsophisticated state, and has two notable limitations:
      6 //!
      7 //! - Content to upload must be provided as a literal argument
      8 //! - It only uses gnupg private keys stored in the keyring in `~/.gnupg/`.
      9 //!
     10 //! ## Examples
     11 //!
     12 //! Assuming that `wala` is running on default host and port - localhost:8000.
     13 //!
     14 //! ### Upload content to a content address
     15 //!
     16 //! ``` ignore,
     17 //! wala_send -u http://localhost:8000 foo
     18 //! ```
     19 //!
     20 //! ### Upload content to a mutable reference 
     21 //!
     22 //! ``` ignore,
     23 //! wala_send -u http://localhost:8000 -k <pgp_fingerprint> -i <keyword> foo
     24 //! ```
     25 //!
     26 //! For more details on what funcionality [wala](wala) provides, please consult the
     27 //! [library crate documentation](wala).
     28 
     29 //use std::env::home_dir;
     30 //use std::io::stdout;
     31 //use std::io::copy;
     32 use std::io::Write;
     33 
     34 use env_logger;
     35 
     36 use url::Url;
     37 
     38 //use log::{info, debug};
     39 use log::{debug};
     40 
     41 //use ureq::{Agent, AgentBuilder};
     42 use ureq::AgentBuilder;
     43 
     44 use clap::{
     45     App, 
     46     Arg,
     47 };
     48 
     49 use xdg_home::home_dir;
     50 
     51 use sequoia_openpgp::packet::prelude::*;
     52 use sequoia_openpgp::cert::prelude::CertParser;
     53 use sequoia_openpgp::serialize::Serialize;
     54 use sequoia_openpgp::parse::Parse;
     55 use sequoia_openpgp::parse::PacketParser;
     56 use sequoia_openpgp::policy::StandardPolicy;
     57 use sequoia_openpgp::packet::Key;
     58 use sequoia_openpgp::packet::key::SecretParts;
     59 use sequoia_openpgp::packet::key::PublicParts;
     60 //use sequoia_openpgp::packet::key::UnspecifiedRole;
     61 use sequoia_openpgp::packet::key::PrimaryRole;
     62 use sequoia_openpgp::serialize::stream::Message;
     63 use sequoia_openpgp::serialize::stream::Signer;
     64 //use sequoia_openpgp::serialize::stream::LiteralWriter;
     65 
     66 //use base64::encode;
     67 
     68 use wala::record::{ResourceKey};
     69 use wala::auth::{AuthResult};
     70 
     71 
     72 #[doc(hidden)]
     73 fn main() {
     74     env_logger::init();
     75 
     76     let mut o = App::new("wala_send");
     77     o = o.version("0.1.0");
     78     o = o.author("Louis Holbrook <dev@holbrook.no>");
     79 
     80     o = o.arg(Arg::with_name("DATA")
     81               .required(true)
     82               );
     83 
     84     o = o.arg(Arg::with_name("url")
     85               .short("u")
     86               .long("url")
     87               .takes_value(true)
     88               .required(true)
     89               );
     90 
     91     o = o.arg(Arg::with_name("ref_id")
     92               .short("i")
     93               .long("id")
     94               .takes_value(true)
     95               .multiple(true)
     96               .number_of_values(1)
     97               );
     98 
     99     o = o.arg(Arg::with_name("key")
    100               .short("k")
    101               .long("key")
    102               .takes_value(true)
    103               );
    104 
    105 
    106     let args = o.get_matches();
    107 
    108     let mut d: Vec<u8> = vec!();
    109     let mut nv = String::from("0");
    110 
    111     match args.values_of("ref_id") {
    112         Some(vs) => {
    113             for mut v in vs {
    114                 if v.len() < 2 {
    115                     continue;
    116                 }
    117                 if &v[..2] == "0x" {
    118                     v = &v[2..];
    119                     if v.len() % 2 > 0 {
    120                         nv.push_str(v);
    121                         v = nv.as_ref();
    122                     }
    123                     debug!("hex input {:?}", &v);
    124                     let mut r = hex::decode(v).unwrap();
    125                     d.append(&mut r);
    126                 } else {
    127                     d.append(&mut v.as_bytes().to_vec());
    128                 }
    129             }
    130         },
    131         None => {},
    132     }
    133     
    134     let data = args.value_of("DATA").unwrap();
    135     
    136     //let mut auth: Option<AuthResult> = None;
    137     //let auth: Option<AuthResult> = None;
    138 
    139     let url_src = args.value_of("url").unwrap();
    140     let mut url = Url::parse(url_src).unwrap();
    141 
    142     //let have_auth = false;
    143     let mut rk = ResourceKey {
    144         v: Vec::new(),
    145     };
    146     let mut auth_data = AuthResult {
    147         identity: Vec::new(),
    148         error: false,
    149     };
    150 
    151     match args.value_of("key") {
    152         Some(mut v) => {
    153             if v.len() > 1 {
    154                 if &v[..2] == "0x" {
    155                     v = &v[2..];
    156                 }
    157             }
    158             if v.len() % 2 > 0 {
    159                 nv.push_str(v);
    160                 v = nv.as_ref();
    161             }
    162             auth_data.identity = hex::decode(&v).unwrap();
    163             rk.v = d.clone();
    164             let url_postfix = rk.pointer_for(&auth_data);
    165             let url_postfix_hex = hex::encode(url_postfix);
    166             url = url.join(&url_postfix_hex).unwrap();
    167         },
    168         None => {},
    169     }
    170 
    171     let mut sk: Option<Key<SecretParts, PrimaryRole>> = None;
    172     let p = StandardPolicy::new();
    173     if rk.v.len() > 0 {
    174         let fp_stem = home_dir().unwrap();
    175         let fp = fp_stem.join(".gnupg/secring.gpg");
    176         let pp = PacketParser::from_file(fp).unwrap();
    177 
    178         // find a way to stop iter when key found
    179         for v in CertParser::from(pp) {
    180             match v {
    181                 Ok(r) => {
    182                     for k in r.keys()
    183                         .with_policy(&p, None)
    184                         .alive()
    185                         .revoked(false)
    186                         .for_signing()
    187                         .secret()
    188                         .map(|kk| kk.key()) {
    189                             if k.fingerprint().as_bytes() == auth_data.identity {
    190                                 sk = Some(k.clone().role_into_primary());
    191                             }
    192                         }
    193                    
    194                 },
    195                 Err(e) => {
    196                     panic!("keyparse fail: {:?}", e);
    197                 }
    198             };
    199         }
    200     }
    201 
    202     let mut sig_bsf = String::new();
    203     let mut pubkey_bsf = String::new();
    204 
    205     match sk {
    206         Some(mut k) => {
    207             let mut sig_sink = vec!();
    208             let mut pubkey_sink = vec!();
    209 
    210             if k.secret().is_encrypted() {
    211                 let pwd = rpassword::prompt_password("Key passphrase: ").unwrap();
    212                 let algo = k.pk_algo();
    213                 _ = k.secret_mut()
    214                     .decrypt_in_place(algo, &pwd.into());
    215             }
    216 
    217             //let mut sig_msg = Message::new(&mut sig_sink);
    218             let sig_msg = Message::new(&mut sig_sink);
    219 
    220             let kp =  k.clone().into_keypair().unwrap();
    221             let pk: Key<PublicParts, PrimaryRole> = kp.public().clone().role_into_primary();
    222             let mut signer = Signer::new(sig_msg, kp)
    223                 .detached()
    224                 .build()
    225                 .unwrap();
    226             _ = signer.write_all(&data.as_bytes());
    227             _ = signer.finalize();
    228 
    229             _ = Packet::from(pk).serialize(&mut pubkey_sink);
    230            
    231             sig_bsf = base64::encode(sig_sink);
    232             pubkey_bsf = base64::encode(pubkey_sink);
    233         }, 
    234         None => {},
    235     };
    236 
    237     let ua = AgentBuilder::new().build();
    238     let mut rq = ua.put(url.as_str());
    239 
    240     if sig_bsf.len() > 0 {
    241         let hdr_val = format!("PUBSIG pgp:{}:{}", pubkey_bsf, sig_bsf);
    242         rq = rq.set("Authorization", hdr_val.as_str());
    243     }
    244     let rs = rq.send_bytes(&data.as_bytes());
    245 
    246     println!("{}", rs.unwrap().into_string().unwrap());
    247 }