wala-rust

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

main.rs (6896B)


      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 
     40 use ureq::{Agent, AgentBuilder};
     41 
     42 use clap::{
     43     App, 
     44     Arg,
     45 };
     46 
     47 use sequoia_openpgp::packet::prelude::*;
     48 use sequoia_openpgp::cert::prelude::CertParser;
     49 use sequoia_openpgp::serialize::Serialize;
     50 use sequoia_openpgp::parse::Parse;
     51 use sequoia_openpgp::parse::PacketParser;
     52 use sequoia_openpgp::policy::StandardPolicy;
     53 use sequoia_openpgp::packet::Key;
     54 use sequoia_openpgp::packet::key::SecretParts;
     55 use sequoia_openpgp::packet::key::PublicParts;
     56 use sequoia_openpgp::packet::key::UnspecifiedRole;
     57 use sequoia_openpgp::packet::key::PrimaryRole;
     58 use sequoia_openpgp::serialize::stream::Message;
     59 use sequoia_openpgp::serialize::stream::Signer;
     60 use sequoia_openpgp::serialize::stream::LiteralWriter;
     61 
     62 use base64::encode;
     63 
     64 use wala::record::{ResourceKey};
     65 use wala::auth::{AuthResult};
     66 
     67 
     68 #[doc(hidden)]
     69 fn main() {
     70     env_logger::init();
     71 
     72     let mut o = App::new("wala_send");
     73     o = o.version("0.1.0");
     74     o = o.author("Louis Holbrook <dev@holbrook.no>");
     75 
     76     o = o.arg(Arg::with_name("DATA")
     77               .required(true)
     78               );
     79 
     80     o = o.arg(Arg::with_name("url")
     81               .short("u")
     82               .long("url")
     83               .takes_value(true)
     84               .required(true)
     85               );
     86 
     87     o = o.arg(Arg::with_name("ref_id")
     88               .short("i")
     89               .long("id")
     90               .takes_value(true)
     91               .multiple(true)
     92               .number_of_values(1)
     93               );
     94 
     95     o = o.arg(Arg::with_name("key")
     96               .short("k")
     97               .long("key")
     98               .takes_value(true)
     99               );
    100 
    101 
    102     let args = o.get_matches();
    103 
    104     let mut d: Vec<u8> = vec!();
    105     let mut nv = String::from("0");
    106 
    107     match args.values_of("ref_id") {
    108         Some(vs) => {
    109             for mut v in vs {
    110                 if v.len() < 2 {
    111                     continue;
    112                 }
    113                 if &v[..2] == "0x" {
    114                     v = &v[2..];
    115                     if v.len() % 2 > 0 {
    116                         nv.push_str(v);
    117                         v = nv.as_ref();
    118                     }
    119                     debug!("hex input {:?}", &v);
    120                     let mut r = hex::decode(v).unwrap();
    121                     d.append(&mut r);
    122                 } else {
    123                     d.append(&mut v.as_bytes().to_vec());
    124                 }
    125             }
    126         },
    127         None => {},
    128     }
    129     
    130     let data = args.value_of("DATA").unwrap();
    131     
    132     let mut auth: Option<AuthResult> = None;
    133 
    134     let url_src = args.value_of("url").unwrap();
    135     let mut url = Url::parse(url_src).unwrap();
    136 
    137     let mut have_auth = false;
    138     let mut rk = ResourceKey {
    139         v: Vec::new(),
    140     };
    141     let mut auth_data = AuthResult {
    142         identity: Vec::new(),
    143         error: false,
    144     };
    145 
    146     match args.value_of("key") {
    147         Some(mut v) => {
    148             if v.len() > 1 {
    149                 if &v[..2] == "0x" {
    150                     v = &v[2..];
    151                 }
    152             }
    153             if v.len() % 2 > 0 {
    154                 nv.push_str(v);
    155                 v = nv.as_ref();
    156             }
    157             auth_data.identity = hex::decode(&v).unwrap();
    158             rk.v = d.clone();
    159             let url_postfix = rk.pointer_for(&auth_data);
    160             let url_postfix_hex = hex::encode(url_postfix);
    161             url = url.join(&url_postfix_hex).unwrap();
    162         },
    163         None => {},
    164     }
    165 
    166     let mut sk: Option<Key<SecretParts, PrimaryRole>> = None;
    167     let p = StandardPolicy::new();
    168     if rk.v.len() > 0 {
    169         let fp_stem = home_dir().unwrap();
    170         let fp = fp_stem.join(".gnupg/secring.gpg");
    171         let pp = PacketParser::from_file(fp).unwrap();
    172 
    173         // find a way to stop iter when key found
    174         for v in CertParser::from(pp) {
    175             match v {
    176                 Ok(r) => {
    177                     for k in r.keys()
    178                         .with_policy(&p, None)
    179                         .alive()
    180                         .revoked(false)
    181                         .for_signing()
    182                         .secret()
    183                         .map(|kk| kk.key()) {
    184                             if k.fingerprint().as_bytes() == auth_data.identity {
    185                                 sk = Some(k.clone().role_into_primary());
    186                             }
    187                         }
    188                    
    189                 },
    190                 Err(e) => {
    191                     panic!("keyparse fail: {:?}", e);
    192                 }
    193             };
    194         }
    195     }
    196 
    197     let mut sig_bsf = String::new();
    198     let mut pubkey_bsf = String::new();
    199 
    200     match sk {
    201         Some(mut k) => {
    202             let mut sig_sink = vec!();
    203             let mut pubkey_sink = vec!();
    204 
    205             let mut pwd = String::new();
    206             if k.secret().is_encrypted() {
    207                 pwd = rpassword::prompt_password("Key passphrase: ").unwrap();
    208                 let algo = k.pk_algo();
    209                 k.secret_mut()
    210                     .decrypt_in_place(algo, &pwd.into());
    211 
    212             }
    213 
    214             let mut sig_msg = Message::new(&mut sig_sink);
    215 
    216             let kp =  k.clone().into_keypair().unwrap();
    217             let pk: Key<PublicParts, PrimaryRole> = kp.public().clone().role_into_primary();
    218             let mut signer = Signer::new(sig_msg, kp)
    219                 .detached()
    220                 .build()
    221                 .unwrap();
    222             signer.write_all(&data.as_bytes());
    223             signer.finalize();
    224 
    225             Packet::from(pk).serialize(&mut pubkey_sink);
    226            
    227             sig_bsf = base64::encode(sig_sink);
    228             pubkey_bsf = base64::encode(pubkey_sink);
    229         }, 
    230         None => {},
    231     };
    232 
    233     let ua = AgentBuilder::new().build();
    234     let mut rq = ua.put(url.as_str());
    235 
    236     if sig_bsf.len() > 0 {
    237         let hdr_val = format!("PUBSIG pgp:{}:{}", pubkey_bsf, sig_bsf);
    238         rq = rq.set("Authorization", hdr_val.as_str());
    239     }
    240     let rs = rq.send_bytes(&data.as_bytes());
    241 
    242     println!("{}", rs.unwrap().into_string().unwrap());
    243 }