subscribe.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
  1. /*
  2. * Presence Agent, subscribe handling
  3. *
  4. * $Id$
  5. *
  6. * Copyright (C) 2001-2003 FhG Fokus
  7. *
  8. * This file is part of ser, a free SIP server.
  9. *
  10. * ser is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version
  14. *
  15. * For a license to use the ser software under conditions
  16. * other than those described here, or to purchase support for this
  17. * software, please contact iptel.org by e-mail at the following addresses:
  18. * [email protected]
  19. *
  20. * ser is distributed in the hope that it will be useful,
  21. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23. * GNU General Public License for more details.
  24. *
  25. * You should have received a copy of the GNU General Public License
  26. * along with this program; if not, write to the Free Software
  27. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  28. *
  29. * History:
  30. * ---------
  31. * 2003-02-29 scratchpad compatibility abandoned
  32. * 2003-01-27 next baby-step to removing ZT - PRESERVE_ZT (jiri)
  33. */
  34. #include <string.h>
  35. #include <limits.h>
  36. #include "../../str.h"
  37. #include "../../dprint.h"
  38. #include "../../mem/mem.h"
  39. #include "../../parser/parse_uri.h"
  40. #include "../../parser/parse_from.h"
  41. #include "../../parser/parse_expires.h"
  42. #include "../../parser/parse_event.h"
  43. #include "../../data_lump_rpl.h"
  44. #include "presentity.h"
  45. #include "watcher.h"
  46. #include "notify.h"
  47. #include "paerrno.h"
  48. #include "pdomain.h"
  49. #include "pa_mod.h"
  50. #include "ptime.h"
  51. #include "reply.h"
  52. #include "subscribe.h"
  53. #include "auth.h"
  54. #include <cds/sstr.h>
  55. #include <cds/msg_queue.h>
  56. #include <cds/logger.h>
  57. #include <cds/sip_utils.h>
  58. #include <presence/utils.h>
  59. #include "offline_winfo.h"
  60. #include "mimetypes.h"
  61. #include <string.h>
  62. #include "../../mem/shm_mem.h"
  63. #include "../../dprint.h"
  64. #include "../../globals.h"
  65. #include "../../md5.h"
  66. #include "../../crc.h"
  67. #include "../../ip_addr.h"
  68. #include "../../socket_info.h"
  69. #include "../../modules/tm/ut.h"
  70. #include "../../modules/tm/h_table.h"
  71. #include "../../modules/tm/t_hooks.h"
  72. #include "../../modules/tm/t_funcs.h"
  73. #include "../../modules/tm/t_msgbuilder.h"
  74. #include "../../modules/tm/callid.h"
  75. #include "../../modules/tm/uac.h"
  76. #define DOCUMENT_TYPE "application/cpim-pidf+xml"
  77. #define DOCUMENT_TYPE_L (sizeof(DOCUMENT_TYPE) - 1)
  78. /*
  79. * Extract plain uri -- return URI without parameters
  80. * The uri will be in form username@domain
  81. *
  82. */
  83. static int extract_plain_uri(str* _uri)
  84. {
  85. struct sip_uri puri;
  86. int res = 0;
  87. if (parse_uri(_uri->s, _uri->len, &puri) < 0) {
  88. paerrno = PA_URI_PARSE;
  89. LOG(L_ERR, "extract_plain_uri(): Error while parsing URI\n");
  90. return -1;
  91. }
  92. /* _uri->s = puri.user.s;
  93. if ((!_uri->s) || (puri.user.len < 1)) {
  94. _uri->s = puri.host.s;
  95. _uri->len = puri.host.len;
  96. return -1;
  97. }*/
  98. if (puri.user.len < 1) {
  99. res = -1; /* it is uri without username ! */
  100. }
  101. _uri->len = puri.host.s + puri.host.len - _uri->s;
  102. return res;
  103. }
  104. /*
  105. * Get presentity URI, which is stored in R-URI
  106. */
  107. int get_pres_uri(struct sip_msg* _m, str* _puri)
  108. {
  109. if (_m->new_uri.s) {
  110. _puri->s = _m->new_uri.s;
  111. _puri->len = _m->new_uri.len;
  112. } else {
  113. _puri->s = _m->first_line.u.request.uri.s;
  114. _puri->len = _m->first_line.u.request.uri.len;
  115. }
  116. LOG(L_DBG, "get_pres_uri: _puri=%.*s\n", _puri->len, _puri->s);
  117. if (extract_plain_uri(_puri) < 0) {
  118. _puri->s = get_to(_m)->uri.s;
  119. _puri->len = get_to(_m)->uri.len;
  120. LOG(L_DBG, "get_pres_uri(2): _puri=%.*s\n", _puri->len, _puri->s);
  121. if (extract_plain_uri(_puri) < 0) {
  122. LOG(L_ERR, "get_pres_uri(): Error while extracting plain URI\n");
  123. return -1;
  124. }
  125. }
  126. return 0;
  127. }
  128. static int get_watch_uri(struct sip_msg* _m, str* _wuri, str *_dn)
  129. {
  130. _wuri->s = get_from(_m)->uri.s;
  131. _wuri->len = get_from(_m)->uri.len;
  132. _dn->s = get_from(_m)->body.s;
  133. _dn->len = get_from(_m)->body.len;
  134. if (extract_plain_uri(_wuri) < 0) {
  135. LOG(L_ERR, "get_watch_uri(): Error while extracting plain URI\n");
  136. return -1;
  137. }
  138. return 0;
  139. }
  140. static int get_dlg_id(struct sip_msg *_m, dlg_id_t *dst)
  141. {
  142. if (!dst) return -1;
  143. memset(dst, 0, sizeof(*dst));
  144. if (_m->to) dst->loc_tag = ((struct to_body*)_m->to->parsed)->tag_value;
  145. if (_m->from) dst->rem_tag = ((struct to_body*)_m->from->parsed)->tag_value;
  146. if (_m->callid) dst->call_id = _m->callid->body;
  147. return 0;
  148. }
  149. static time_t get_expires(struct sip_msg *_m)
  150. {
  151. time_t e;
  152. if (_m->expires) e = ((exp_body_t*)_m->expires->parsed)->val;
  153. else e = default_expires;
  154. if (e > max_subscription_expiration)
  155. e = max_subscription_expiration;
  156. return e;
  157. }
  158. /*
  159. * Parse all header fields that will be needed
  160. * to handle a SUBSCRIBE request
  161. */
  162. static int parse_hfs(struct sip_msg* _m, int accept_header_required)
  163. {
  164. int rc = 0;
  165. struct hdr_field *acc;
  166. /* EOH instead HDR_FROM_F | HDR_EVENT_F | HDR_EXPIRES_F | HDR_ACCEPT_F
  167. * because we need all Accept headers */
  168. if ( (rc = parse_headers(_m, HDR_EOH_F, 0)) == -1) {
  169. paerrno = PA_PARSE_ERR;
  170. LOG(L_ERR, "parse_hfs(): Error while parsing headers: rc=%d\n", rc);
  171. return -1;
  172. }
  173. if (!_m->from) {
  174. ERR("From header missing\n");
  175. return -1;
  176. }
  177. if (parse_from_header(_m) < 0) {
  178. paerrno = PA_FROM_ERR;
  179. LOG(L_ERR, "parse_hfs(): From malformed or missing\n");
  180. return -6;
  181. }
  182. if (_m->event) {
  183. if (parse_event(_m->event) < 0) {
  184. /* can not parse Event header */
  185. paerrno = PA_EVENT_PARSE;
  186. LOG(L_ERR, "parse_hfs(): Error while parsing Event header field\n");
  187. return -8;
  188. }
  189. }
  190. else {
  191. /* no Event header -> bad message */
  192. paerrno = PA_EVENT_PARSE;
  193. LOG(L_ERR, "parse_hfs(): Error while parsing Event header field\n");
  194. return -8;
  195. }
  196. if (_m->expires) {
  197. if (parse_expires(_m->expires) < 0) {
  198. paerrno = PA_EXPIRES_PARSE;
  199. LOG(L_ERR, "parse_hfs(): Error while parsing Expires header field\n");
  200. return -9;
  201. }
  202. }
  203. /* now look for Accept header */
  204. acc = _m->accept;
  205. if (accept_header_required && (!acc)) {
  206. LOG(L_ERR, "no accept header\n");
  207. return -11;
  208. }
  209. while (acc) { /* parse all accept headers */
  210. if (acc->type == HDR_ACCEPT_T) {
  211. DBG("parsing accept header: %.*s\n", FMT_STR(acc->body));
  212. if (parse_accept_body(acc) < 0) {
  213. paerrno = PA_ACCEPT_PARSE;
  214. LOG(L_ERR, "parse_hfs(): Error while parsing Accept header field\n");
  215. return -10;
  216. }
  217. }
  218. acc = acc->next;
  219. }
  220. return 0;
  221. }
  222. /* returns 0 if package supported by PA */
  223. static inline int verify_event_package(int et)
  224. {
  225. switch (et) {
  226. case EVENT_PRESENCE: return 0;
  227. case EVENT_PRESENCE_WINFO:
  228. if (watcherinfo_notify) return 0;
  229. else return -1;
  230. default: return -1;
  231. }
  232. }
  233. /* get_event MUST be parsed when calling get event -> done by parse_hfs! */
  234. #define get_event(_m) ((event_t*)(_m->event->parsed))->parsed
  235. /*
  236. * Check if a message received has been constructed properly
  237. */
  238. static int check_message(struct sip_msg* _m)
  239. {
  240. int eventtype = 0;
  241. int *accepts_mimes = NULL;
  242. event_mimetypes_t *em;
  243. struct hdr_field *acc;
  244. if ((!_m->event) || (!_m->event->parsed)) {
  245. paerrno = PA_EXPIRES_PARSE;
  246. ERR("Event header field not found\n");
  247. return -1; /* should be verified in parse_hfs before */
  248. }
  249. /* event package verification */
  250. eventtype = get_event(_m);
  251. if (verify_event_package(eventtype) != 0) {
  252. INFO("Unsupported event package\n");
  253. paerrno = PA_EVENT_UNSUPP;
  254. return -1;
  255. }
  256. em = find_event_mimetypes(eventtype);
  257. if (em)
  258. if (em->event_type == -1) em = NULL;
  259. if (!em) {
  260. paerrno = PA_EVENT_UNSUPP;
  261. ERR("Unsupported event package\n");
  262. return -1;
  263. }
  264. acc = _m->accept;
  265. if (!acc) return 0; /* default will be used */
  266. while (acc) { /* go through all Accept headers */
  267. if (acc->type == HDR_ACCEPT_T) {
  268. /* it MUST be parsed from parse_hdr !!! */
  269. accepts_mimes = acc->parsed;
  270. if (check_mime_types(accepts_mimes, em) == 0) return 0;
  271. /* else, none of the mimetypes accepted are generated for this event package */
  272. INFO("Accepts %.*s not valid for event package et=%.*s\n",
  273. acc->body.len, acc->body.s, _m->event->body.len, _m->event->body.s);
  274. }
  275. acc = acc->next;
  276. }
  277. paerrno = PA_WRONG_ACCEPTS;
  278. ERR("no satisfactory document type found\n");
  279. return -1;
  280. }
  281. static int create_watcher(struct sip_msg* _m, struct watcher** _w)
  282. {
  283. dlg_t* dialog;
  284. str server_contact = STR_NULL;
  285. int acc = 0;
  286. str watch_uri;
  287. str watch_dn;
  288. int et;
  289. time_t expires;
  290. et = get_event(_m);
  291. expires = get_expires(_m);
  292. if (expires) expires += act_time;
  293. if (get_watch_uri(_m, &watch_uri, &watch_dn) < 0) {
  294. paerrno = PA_URI_PARSE;
  295. ERR("Error while extracting watcher URI\n");
  296. return -1;
  297. }
  298. acc = get_preferred_event_mimetype(_m, et);
  299. if (tmb.new_dlg_uas(_m, 200, &dialog) < 0) {
  300. paerrno = PA_DIALOG_ERR;
  301. ERR("Error while creating dialog state\n");
  302. return -4;
  303. }
  304. if (extract_server_contact(_m, &server_contact, 1) != 0) {
  305. paerrno = PA_DIALOG_ERR;
  306. ERR("Error while extracting server contact\n");
  307. return -3;
  308. }
  309. if (new_watcher_no_wb(&watch_uri, expires, et, acc, dialog,
  310. &watch_dn, &server_contact, NULL, _w) < 0) {
  311. ERR("Error while creating watcher\n");
  312. tmb.free_dlg(dialog);
  313. if (server_contact.s) mem_free(server_contact.s);
  314. paerrno = PA_NO_MEMORY;
  315. return -5;
  316. }
  317. if (server_contact.s) mem_free(server_contact.s);
  318. (*_w)->flags |= WFLAG_SUBSCRIPTION_CHANGED;
  319. return 0;
  320. }
  321. static inline int add_rpl_expires(struct sip_msg *_m, watcher_t *w)
  322. {
  323. int i = 0;
  324. char tmp[64];
  325. /* add expires header field into response */
  326. if (w) i = w->expires - act_time;
  327. if (i < 0) i = 0;
  328. sprintf(tmp, "Expires: %d\r\n", i);
  329. if (!add_lump_rpl(_m, tmp, strlen(tmp), LUMP_RPL_HDR)) {
  330. ERR("Can't add Expires header to the response\n");
  331. return -1;
  332. }
  333. return 0;
  334. }
  335. int handle_renewal_subscription(struct sip_msg* _m, struct pdomain *d)
  336. {
  337. struct presentity *p = NULL;
  338. struct watcher* w = NULL;
  339. str uid = STR_NULL;
  340. dlg_id_t dlg_id;
  341. int et, e;
  342. if (get_presentity_uid(&uid, _m) < 0) {
  343. ERR("Error while extracting presentity UID\n");
  344. paerrno = PA_INTERNAL_ERROR;
  345. goto err;
  346. }
  347. /* needed to find watcher (better to set outside of crit. sect. due to
  348. * better performance) */
  349. et = get_event(_m);
  350. get_dlg_id(_m, &dlg_id);
  351. lock_pdomain(d);
  352. if (find_presentity_uid(d, &uid, &p) != 0) {
  353. /* presentity not found */
  354. INFO("resubscription to nonexisting presentity %.*s\n", FMT_STR(uid));
  355. paerrno = PA_SUBSCRIPTION_NOT_EXISTS;
  356. goto err2;
  357. }
  358. if (find_watcher_dlg(p, &dlg_id, et, &w) != 0) {
  359. /* watcher not found */
  360. INFO("resubscription for nonexisting watcher\n");
  361. paerrno = PA_SUBSCRIPTION_NOT_EXISTS;
  362. goto err2;
  363. }
  364. e = get_expires(_m);
  365. if (e) e += act_time;
  366. update_watcher(p, w, e, _m);
  367. set_last_subscription_status(w->status);
  368. add_rpl_expires(_m, w);
  369. if (send_reply(_m) >= 0) {
  370. /* we have successfully sent the response */
  371. if (send_notify(p, w) >= 0) {
  372. w->flags &= ~WFLAG_SUBSCRIPTION_CHANGED; /* notified */
  373. /* remove terminated watcher otherwise he will
  374. * receive another NOTIFY generated from timer_pdomain */
  375. if (is_watcher_terminated(w)) {
  376. remove_watcher(p, w);
  377. free_watcher(w);
  378. }
  379. }
  380. }
  381. else {
  382. ERR("Error while sending reply\n");
  383. }
  384. unlock_pdomain(d);
  385. return 1;
  386. err2:
  387. unlock_pdomain(d);
  388. err:
  389. set_last_subscription_status(WS_REJECTED);
  390. if (send_reply(_m) < 0) ERR("Error while sending reply\n");
  391. return -1;
  392. }
  393. presentity_t *get_presentity(struct sip_msg *_m, struct pdomain *d, int allow_creation)
  394. {
  395. str p_uri, uid;
  396. presentity_t *p = NULL;
  397. xcap_query_params_t xcap_params;
  398. /* presence_rules_t *auth_rules = NULL;*/
  399. if (get_presentity_uid(&uid, _m) < 0) {
  400. ERR("Error while extracting presentity UID\n");
  401. return NULL;
  402. }
  403. if (find_presentity_uid(d, &uid, &p) > 0) {
  404. if (allow_creation) {
  405. if (get_pres_uri(_m, &p_uri) < 0) {
  406. ERR("Error while extracting presentity URI\n");
  407. }
  408. else {
  409. /* presentity not found -> create new presentity */
  410. memset(&xcap_params, 0, sizeof(xcap_params));
  411. if (fill_xcap_params) fill_xcap_params(_m, &xcap_params);
  412. if (new_presentity(d, &p_uri, &uid, &xcap_params, &p) < 0)
  413. ERR("Error while creating new presentity\n");
  414. }
  415. }
  416. }
  417. return p;
  418. }
  419. int handle_new_subscription(struct sip_msg* _m, struct pdomain *d)
  420. {
  421. struct presentity *p;
  422. struct watcher* w;
  423. struct retr_buf *req;
  424. int is_terminated;
  425. if (create_watcher(_m, &w) < 0) {
  426. ERR("can't create watcher\n");
  427. goto err;
  428. }
  429. lock_pdomain(d);
  430. p = get_presentity(_m, d, 1);
  431. if (!p) goto err3;
  432. /* authorize watcher */
  433. w->status = authorize_watcher(p, w);
  434. switch (w->status) {
  435. case WS_REJECTED:
  436. unlock_pdomain(d);
  437. free_watcher(w);
  438. paerrno = PA_SUBSCRIPTION_REJECTED;
  439. INFO("watcher rejected\n");
  440. goto err;
  441. case WS_PENDING:
  442. case WS_PENDING_TERMINATED:
  443. paerrno = PA_OK_WAITING_FOR_AUTH;
  444. default:
  445. break;
  446. }
  447. if (w->expires <= act_time) {
  448. set_watcher_terminated_status(w);
  449. is_terminated = 1;
  450. }
  451. else {
  452. is_terminated = 0;
  453. if (append_watcher(p, w, 1) < 0) {
  454. ERR("can't add watcher\n");
  455. goto err3;
  456. }
  457. }
  458. if (prepare_notify(&req, p, w) < 0) {
  459. ERR("can't send notify\n");
  460. goto err4;
  461. }
  462. set_last_subscription_status(w->status);
  463. add_rpl_expires(_m, w);
  464. unlock_pdomain(d);
  465. send_reply(_m);
  466. if (req) {
  467. tmb.send_prepared_request(req);
  468. w->flags &= ~WFLAG_SUBSCRIPTION_CHANGED; /* notified */
  469. if (is_terminated) {
  470. free_watcher(w);
  471. w = NULL;
  472. }
  473. }
  474. return 1;
  475. err4:
  476. remove_watcher(p, w);
  477. err3:
  478. unlock_pdomain(d);
  479. free_watcher(w);
  480. paerrno = PA_INTERNAL_ERROR;
  481. err:
  482. set_last_subscription_status(WS_REJECTED);
  483. if (paerrno == PA_OK) paerrno = PA_INTERNAL_ERROR;
  484. if (send_reply(_m) < 0) ERR("Error while sending reply\n");
  485. return -1;
  486. }
  487. /*
  488. * Handle a subscribe Request
  489. */
  490. int handle_subscription(struct sip_msg* _m, char* _domain, char* _s2)
  491. {
  492. int res;
  493. PROF_START_DECL(pa_response_generation)
  494. PROF_START(pa_handle_subscription)
  495. get_act_time();
  496. paerrno = PA_OK;
  497. if (parse_hfs(_m, 0) < 0) {
  498. ERR("Error while parsing message header\n");
  499. goto error;
  500. }
  501. if (check_message(_m) < 0) {
  502. ERR("Error while checking message\n");
  503. goto error;
  504. }
  505. if (has_to_tag(_m))
  506. res = handle_renewal_subscription(_m, (struct pdomain*)_domain);
  507. else
  508. res = handle_new_subscription(_m, (struct pdomain*)_domain);
  509. PROF_STOP(pa_handle_subscription)
  510. return res;
  511. error:
  512. INFO("handle_subscription about to send_reply and return -2\n");
  513. send_reply(_m);
  514. set_last_subscription_status(WS_REJECTED);
  515. PROF_STOP(pa_handle_subscription)
  516. return -1;
  517. }