Kibou is a federated social networking server.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

validator.rs 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. use activitypub;
  2. use activitypub::activity::Activity;
  3. use activitypub::activity::Object;
  4. use activitypub::controller::actor_exists;
  5. use activitypub::controller::fetch_object_by_id;
  6. use activitypub::controller::object_exists;
  7. use actor;
  8. use database;
  9. use html;
  10. use regex::Regex;
  11. use url::Url;
  12. use web_handler;
  13. use web_handler::http_signatures::HTTPSignature;
  14. pub fn validate_activity(
  15. mut activity: serde_json::Value,
  16. signature: HTTPSignature,
  17. ) -> Result<serde_json::Value, &'static str> {
  18. let database = database::establish_connection();
  19. let known_type = if activity.get("type").is_some() {
  20. match activity["type"].as_str() {
  21. Some("Accept") => true,
  22. Some("Announce") => true,
  23. Some("Create") => true,
  24. Some("Follow") => true,
  25. Some("Like") => true,
  26. Some("Undo") => true,
  27. _ => false,
  28. }
  29. } else {
  30. false
  31. };
  32. let valid_actor = if activity.get("actor").is_some() {
  33. if actor_exists(activity["actor"].as_str().unwrap()) {
  34. activitypub::actor::refresh(activity["actor"].as_str().unwrap().to_string());
  35. true
  36. } else {
  37. fetch_object_by_id(activity["actor"].as_str().unwrap().to_string());
  38. actor_exists(activity["actor"].as_str().unwrap())
  39. }
  40. } else {
  41. false
  42. };
  43. let valid_signature = web_handler::http_signatures::validate(
  44. &mut actor::get_actor_by_uri(&database, activity["actor"].as_str().unwrap()).unwrap(),
  45. signature,
  46. );
  47. let valid_object = if activity["type"].as_str() == Some("Create") {
  48. if !object_exists(activity["object"]["id"].as_str().unwrap()) {
  49. match validate_object(activity["object"].clone(), valid_signature) {
  50. Ok(object) => {
  51. activity["object"] = object;
  52. true
  53. }
  54. Err(_) => false,
  55. }
  56. } else {
  57. false
  58. }
  59. } else {
  60. true
  61. };
  62. if known_type && valid_actor && valid_signature && valid_object {
  63. Ok(normalize_activity(activity))
  64. } else {
  65. Err("Activity could not be validated")
  66. }
  67. }
  68. pub fn validate_object(
  69. object: serde_json::Value,
  70. valid_signature: bool,
  71. ) -> Result<serde_json::Value, &'static str> {
  72. let known_type = if object.get("type").is_some() {
  73. match object["type"].as_str() {
  74. Some("Note") => true,
  75. Some("Article") => true,
  76. _ => false,
  77. }
  78. } else {
  79. false
  80. };
  81. let valid_id = if valid_signature {
  82. true
  83. } else {
  84. if object.get("id").is_some() {
  85. match parse_url(object["id"].as_str().unwrap()) {
  86. Ok(url) => valid_self_reference(&object, &url),
  87. Err(_) => false,
  88. }
  89. } else {
  90. false
  91. }
  92. };
  93. let valid_actor = if object.get("attributedTo").is_some() {
  94. if actor_exists(object["attributedTo"].as_str().unwrap()) {
  95. activitypub::actor::refresh(object["attributedTo"].as_str().unwrap().to_string());
  96. true
  97. } else {
  98. fetch_object_by_id(object["attributedTo"].as_str().unwrap().to_string());
  99. actor_exists(object["attributedTo"].as_str().unwrap())
  100. }
  101. } else {
  102. false
  103. };
  104. if known_type && valid_id && valid_actor {
  105. Ok(normalize_object(object))
  106. } else {
  107. Err("Object could not be validated")
  108. }
  109. }
  110. pub fn validate_actor(actor: serde_json::Value) -> Result<serde_json::Value, &'static str> {
  111. let known_type = if actor.get("type").is_some() {
  112. match actor["type"].as_str() {
  113. Some("Person") => true,
  114. _ => false,
  115. }
  116. } else {
  117. false
  118. };
  119. let valid_id = if actor.get("id").is_some() {
  120. match parse_url(actor["id"].as_str().unwrap()) {
  121. Ok(url) => valid_self_reference(&actor, &url),
  122. Err(_) => false,
  123. }
  124. } else {
  125. false
  126. };
  127. let valid_preferred_username = if actor.get("preferredUsername").is_some() {
  128. let username_regex = Regex::new(r"^[A-Za-z0-9_]{1,32}$").unwrap();
  129. username_regex.is_match(actor["preferredUsername"].as_str().unwrap())
  130. } else {
  131. false
  132. };
  133. let valid_inbox = if actor.get("inbox").is_some() {
  134. match parse_url(actor["inbox"].as_str().unwrap()) {
  135. Ok(_) => true,
  136. Err(_) => false,
  137. }
  138. } else {
  139. false
  140. };
  141. let valid_public_key = if actor.get("publicKey").is_some() {
  142. match pem::parse(actor["publicKey"]["publicKeyPem"].as_str().unwrap()) {
  143. Ok(_) => true,
  144. Err(_) => false,
  145. }
  146. } else {
  147. false
  148. };
  149. if known_type && valid_id && valid_preferred_username && valid_inbox && valid_public_key {
  150. Ok(actor)
  151. } else {
  152. Err("Object could not be validated")
  153. }
  154. }
  155. fn normalize_activity(mut activity: serde_json::Value) -> serde_json::Value {
  156. let mut new_activity: Activity;
  157. if activity.get("cc").is_none() {
  158. let new_cc_tag: Vec<String> = vec![];
  159. activity["cc"] = serde_json::json!(new_cc_tag);
  160. }
  161. new_activity = serde_json::from_value(activity.clone()).unwrap();
  162. new_activity.context = None;
  163. new_activity.to = normalize_public_addressing(new_activity.to);
  164. new_activity.cc = normalize_public_addressing(new_activity.cc);
  165. serde_json::to_value(new_activity).unwrap()
  166. }
  167. fn normalize_object(mut object: serde_json::Value) -> serde_json::Value {
  168. let mut new_object: Object;
  169. if object.get("cc").is_none() {
  170. let new_cc_tag: Vec<String> = vec![];
  171. object["cc"] = serde_json::json!(new_cc_tag);
  172. }
  173. new_object = serde_json::from_value(object.clone()).unwrap();
  174. new_object.content = html::strip_tags(&new_object.content);
  175. new_object.context = None;
  176. new_object.to = normalize_public_addressing(new_object.to);
  177. new_object.cc = normalize_public_addressing(new_object.cc);
  178. serde_json::to_value(new_object).unwrap()
  179. }
  180. fn normalize_public_addressing(mut collection: Vec<String>) -> Vec<String> {
  181. let alternative_public_address = vec![
  182. "https://www.w3.org/ns/activitystreams",
  183. "Public",
  184. "as:Public",
  185. ];
  186. for address in alternative_public_address {
  187. if collection.contains(&address.to_string()) {
  188. let index = collection
  189. .iter()
  190. .position(|receipient| receipient == &address.to_string())
  191. .unwrap();
  192. collection[index] = String::from("https://www.w3.org/ns/activitystreams#Public");
  193. }
  194. }
  195. return collection;
  196. }
  197. fn parse_url(url: &str) -> Result<String, url::ParseError> {
  198. let mut parsed_url = String::new();
  199. let stripped_characters = "\"";
  200. for character in url.chars() {
  201. if !stripped_characters.contains(character) {
  202. parsed_url.push(character);
  203. }
  204. }
  205. match Url::parse(&parsed_url) {
  206. Ok(remote_url) => Ok(remote_url.to_string()),
  207. Err(e) => Err(e),
  208. }
  209. }
  210. fn valid_self_reference(object: &serde_json::Value, url: &str) -> bool {
  211. match web_handler::fetch_remote_object(url) {
  212. Ok(remote_object) => {
  213. let json_object: serde_json::Value = serde_json::from_str(&remote_object).unwrap();
  214. &json_object == object
  215. }
  216. Err(_) => false,
  217. }
  218. }