mod.rs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. use byteorder::{BigEndian, ByteOrder};
  2. use crypto;
  3. use crypto::aes;
  4. use crypto::digest::Digest;
  5. use crypto::hmac::Hmac;
  6. use crypto::pbkdf2::pbkdf2;
  7. use crypto::sha1::Sha1;
  8. use protobuf::ProtobufEnum;
  9. use rpassword;
  10. use serde;
  11. use serde_json;
  12. use std::io::{self, stderr, Read, Write};
  13. use std::fs::File;
  14. use std::path::Path;
  15. use rustc_serialize::base64::{self, FromBase64, ToBase64};
  16. use protocol::authentication::AuthenticationType;
  17. #[derive(Debug, Clone)]
  18. #[derive(Serialize, Deserialize)]
  19. pub struct Credentials {
  20. pub username: String,
  21. #[serde(serialize_with="serialize_protobuf_enum")]
  22. #[serde(deserialize_with="deserialize_protobuf_enum")]
  23. pub auth_type: AuthenticationType,
  24. #[serde(serialize_with="serialize_base64")]
  25. #[serde(deserialize_with="deserialize_base64")]
  26. pub auth_data: Vec<u8>,
  27. }
  28. impl Credentials {
  29. pub fn with_password(username: String, password: String) -> Credentials {
  30. Credentials {
  31. username: username,
  32. auth_type: AuthenticationType::AUTHENTICATION_USER_PASS,
  33. auth_data: password.into_bytes(),
  34. }
  35. }
  36. pub fn with_blob(username: String, encrypted_blob: &str, device_id: &str) -> Credentials {
  37. fn read_u8<R: Read>(stream: &mut R) -> io::Result<u8> {
  38. let mut data = [0u8];
  39. try!(stream.read_exact(&mut data));
  40. Ok(data[0])
  41. }
  42. fn read_int<R: Read>(stream: &mut R) -> io::Result<u32> {
  43. let lo = try!(read_u8(stream)) as u32;
  44. if lo & 0x80 == 0 {
  45. return Ok(lo);
  46. }
  47. let hi = try!(read_u8(stream)) as u32;
  48. Ok(lo & 0x7f | hi << 7)
  49. }
  50. fn read_bytes<R: Read>(stream: &mut R) -> io::Result<Vec<u8>> {
  51. let length = try!(read_int(stream));
  52. let mut data = vec![0u8; length as usize];
  53. try!(stream.read_exact(&mut data));
  54. Ok(data)
  55. }
  56. let encrypted_blob = encrypted_blob.from_base64().unwrap();
  57. let secret = {
  58. let mut data = [0u8; 20];
  59. let mut h = crypto::sha1::Sha1::new();
  60. h.input(device_id.as_bytes());
  61. h.result(&mut data);
  62. data
  63. };
  64. let key = {
  65. let mut data = [0u8; 24];
  66. let mut mac = Hmac::new(Sha1::new(), &secret);
  67. pbkdf2(&mut mac, username.as_bytes(), 0x100, &mut data[0..20]);
  68. let mut hash = Sha1::new();
  69. hash.input(&data[0..20]);
  70. hash.result(&mut data[0..20]);
  71. BigEndian::write_u32(&mut data[20..], 20);
  72. data
  73. };
  74. let blob = {
  75. // Anyone know what this block mode is ?
  76. let mut data = vec![0u8; encrypted_blob.len()];
  77. let mut cipher = aes::ecb_decryptor(aes::KeySize::KeySize192,
  78. &key,
  79. crypto::blockmodes::NoPadding);
  80. cipher.decrypt(&mut crypto::buffer::RefReadBuffer::new(&encrypted_blob),
  81. &mut crypto::buffer::RefWriteBuffer::new(&mut data),
  82. true)
  83. .unwrap();
  84. let l = encrypted_blob.len();
  85. for i in 0..l - 0x10 {
  86. data[l - i - 1] ^= data[l - i - 0x11];
  87. }
  88. data
  89. };
  90. let mut cursor = io::Cursor::new(&blob);
  91. read_u8(&mut cursor).unwrap();
  92. read_bytes(&mut cursor).unwrap();
  93. read_u8(&mut cursor).unwrap();
  94. let auth_type = read_int(&mut cursor).unwrap();
  95. let auth_type = AuthenticationType::from_i32(auth_type as i32).unwrap();
  96. read_u8(&mut cursor).unwrap();
  97. let auth_data = read_bytes(&mut cursor).unwrap();;
  98. Credentials {
  99. username: username,
  100. auth_type: auth_type,
  101. auth_data: auth_data,
  102. }
  103. }
  104. pub fn from_reader<R: Read>(mut reader: R) -> Credentials {
  105. let mut contents = String::new();
  106. reader.read_to_string(&mut contents).unwrap();
  107. serde_json::from_str(&contents).unwrap()
  108. }
  109. pub fn from_file<P: AsRef<Path>>(path: P) -> Option<Credentials> {
  110. File::open(path).ok().map(Credentials::from_reader)
  111. }
  112. pub fn save_to_writer<W: Write>(&self, writer: &mut W) {
  113. let contents = serde_json::to_string(&self.clone()).unwrap();
  114. writer.write_all(contents.as_bytes()).unwrap();
  115. }
  116. pub fn save_to_file<P: AsRef<Path>>(&self, path: P) {
  117. let mut file = File::create(path).unwrap();
  118. self.save_to_writer(&mut file)
  119. }
  120. }
  121. fn serialize_protobuf_enum<T, S>(v: &T, ser: &mut S) -> Result<(), S::Error>
  122. where T: ProtobufEnum, S: serde::Serializer {
  123. serde::Serialize::serialize(&v.value(), ser)
  124. }
  125. fn deserialize_protobuf_enum<T, D>(de: &mut D) -> Result<T, D::Error>
  126. where T: ProtobufEnum, D: serde::Deserializer {
  127. let v : i32 = try!(serde::Deserialize::deserialize(de));
  128. T::from_i32(v).ok_or(serde::Error::invalid_value("Invalid enum value"))
  129. }
  130. fn serialize_base64<T, S>(v: &T, ser: &mut S) -> Result<(), S::Error>
  131. where T: AsRef<[u8]>, S: serde::Serializer {
  132. serde::Serialize::serialize(&v.as_ref().to_base64(base64::STANDARD), ser)
  133. }
  134. fn deserialize_base64<D>(de: &mut D) -> Result<Vec<u8>, D::Error>
  135. where D: serde::Deserializer {
  136. let v : String = try!(serde::Deserialize::deserialize(de));
  137. v.from_base64().map_err(|e| serde::Error::custom(e.to_string()))
  138. }
  139. mod discovery;
  140. pub use self::discovery::discovery_login;
  141. pub fn get_credentials(device_name: &str, device_id: &str,
  142. username: Option<String>, password: Option<String>,
  143. cached_credentials: Option<Credentials>)
  144. -> Credentials
  145. {
  146. match (username, password, cached_credentials) {
  147. (Some(username), Some(password), _)
  148. => Credentials::with_password(username, password),
  149. (Some(ref username), _, Some(ref credentials))
  150. if *username == credentials.username => credentials.clone(),
  151. (Some(username), None, _) => {
  152. write!(stderr(), "Password for {}: ", username).unwrap();
  153. stderr().flush().unwrap();
  154. let password = rpassword::read_password().unwrap();
  155. Credentials::with_password(username.clone(), password)
  156. }
  157. (None, _, Some(credentials))
  158. => credentials,
  159. (None, _, None) => {
  160. info!("No username provided and no stored credentials, starting discovery ...");
  161. discovery_login(device_name.clone(), device_id.clone()).unwrap()
  162. }
  163. }
  164. }