authentication.rs 6.2 KB

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