00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00037 #include <stdio.h>
00038 #include <stdlib.h>
00039 #include <string.h>
00040 #include <time.h>
00041 #include <libxml/parser.h>
00042
00043 #include "../../str.h"
00044 #include "../../dprint.h"
00045 #include "../../pvar.h"
00046 #include "../../parser/parse_uri.h"
00047 #include "../../modules_k/presence/subscribe.h"
00048 #include "../../modules_k/presence/utils_func.h"
00049 #include "../../modules_k/presence/hash.h"
00050 #include "../../modules_k/xcap_client/xcap_callbacks.h"
00051 #include "utils.h"
00052 #include "pidf.h"
00053
00054 xmlNodePtr get_rule_node(subs_t* subs, xmlDocPtr xcap_tree)
00055 {
00056 str w_uri = {0, 0};
00057 char* id = NULL, *domain = NULL, *time_cont= NULL;
00058 int apply_rule = -1;
00059 xmlNodePtr ruleset_node = NULL, node1= NULL, node2= NULL;
00060 xmlNodePtr cond_node = NULL, except_node = NULL;
00061 xmlNodePtr identity_node = NULL;
00062 xmlNodePtr iden_child;
00063 xmlNodePtr validity_node, time_node;
00064 time_t t_init, t_fin, t;
00065 int valid= 0;
00066
00067 uandd_to_uri(subs->from_user, subs->from_domain, &w_uri);
00068 if (w_uri.s == NULL) {
00069 LM_ERR("while creating uri\n");
00070 return NULL;
00071 }
00072 ruleset_node = xmlDocGetNodeByName(xcap_tree, "ruleset", NULL);
00073 if (ruleset_node == NULL) {
00074 LM_DBG("ruleset_node NULL\n");
00075 goto error;
00076 }
00077 for (node1 = ruleset_node->children; node1; node1 = node1->next) {
00078 if (xmlStrcasecmp(node1->name, (unsigned char*)"text") == 0)
00079 continue;
00080
00081
00082 LM_DBG("node1->name= %s\n", node1->name);
00083
00084 cond_node = xmlNodeGetChildByName(node1, "conditions");
00085 if(cond_node == NULL) {
00086 LM_DBG("cond node NULL\n");
00087 goto error;
00088 }
00089 LM_DBG("cond_node->name= %s\n", cond_node->name);
00090
00091 validity_node = xmlNodeGetChildByName(cond_node, "validity");
00092 if (validity_node != NULL) {
00093 LM_DBG("found validity tag\n");
00094
00095 t= time(NULL);
00096
00097
00098 for (time_node = validity_node->children; time_node;
00099 time_node = time_node->next) {
00100 if (xmlStrcasecmp(time_node->name, (unsigned char*)"from")!= 0)
00101 continue;
00102
00103 time_cont= (char*)xmlNodeGetContent(time_node);
00104 t_init= xml_parse_dateTime(time_cont);
00105 xmlFree(time_cont);
00106 if (t_init< 0) {
00107 LM_ERR("failed to parse xml dateTime\n");
00108 goto error;
00109 }
00110
00111 if (t< t_init) {
00112 LM_DBG("the lower time limit is not respected\n");
00113 continue;
00114 }
00115
00116 time_node= time_node->next;
00117 while (1) {
00118 if (time_node == NULL) {
00119 LM_ERR("bad formatted xml doc:until child not found in"
00120 " validity pair\n");
00121 goto error;
00122 }
00123 if( xmlStrcasecmp(time_node->name,
00124 (unsigned char*)"until")== 0)
00125 break;
00126 time_node= time_node->next;
00127 }
00128
00129 time_cont = (char*)xmlNodeGetContent(time_node);
00130 t_fin= xml_parse_dateTime(time_cont);
00131 xmlFree(time_cont);
00132
00133 if (t_fin< 0) {
00134 LM_ERR("failed to parse xml dateTime\n");
00135 goto error;
00136 }
00137
00138 if (t <= t_fin) {
00139 LM_DBG("the rule is active at this time\n");
00140 valid= 1;
00141 }
00142
00143 }
00144
00145 if (!valid) {
00146 LM_DBG("the rule is not active at this time\n");
00147 continue;
00148 }
00149
00150 }
00151
00152 identity_node = xmlNodeGetChildByName(cond_node, "identity");
00153 if (identity_node == NULL) {
00154 LM_ERR("didn't find identity tag\n");
00155 goto error;
00156 }
00157
00158 iden_child = xmlNodeGetChildByName(identity_node, "one");
00159 if(iden_child) {
00160 for (node2 = identity_node->children; node2; node2 = node2->next) {
00161 if(xmlStrcasecmp(node2->name, (unsigned char*)"one")!= 0)
00162 continue;
00163
00164 id = xmlNodeGetAttrContentByName(node2, "id");
00165 if(id== NULL) {
00166 LM_ERR("while extracting attribute\n");
00167 goto error;
00168 }
00169 if ((strlen(id)== w_uri.len &&
00170 (strncmp(id, w_uri.s, w_uri.len)==0))) {
00171 apply_rule = 1;
00172 xmlFree(id);
00173 break;
00174 }
00175 xmlFree(id);
00176 }
00177 }
00178
00179
00180 iden_child = xmlNodeGetChildByName(identity_node, "many");
00181 if (iden_child) {
00182 domain = NULL;
00183 for (node2 = identity_node->children; node2; node2 = node2->next) {
00184 if (xmlStrcasecmp(node2->name, (unsigned char*)"many") != 0)
00185 continue;
00186
00187 domain = xmlNodeGetAttrContentByName(node2, "domain");
00188 if(domain == NULL) {
00189 LM_DBG("No domain attribute to many\n");
00190 } else {
00191 LM_DBG("<many domain= %s>\n", domain);
00192 if((strlen(domain)!= subs->from_domain.len &&
00193 strncmp(domain, subs->from_domain.s,
00194 subs->from_domain.len) )) {
00195 xmlFree(domain);
00196 continue;
00197 }
00198 }
00199 xmlFree(domain);
00200 apply_rule = 1;
00201 if (node2->children == NULL)
00202 break;
00203
00204 for (except_node = node2->children; except_node;
00205 except_node= except_node->next) {
00206 if(xmlStrcasecmp(except_node->name,
00207 (unsigned char*)"except"))
00208 continue;
00209
00210 id = xmlNodeGetAttrContentByName(except_node, "id");
00211 if (id != NULL) {
00212 if((strlen(id)- 1== w_uri.len &&
00213 (strncmp(id, w_uri.s, w_uri.len)==0))) {
00214 xmlFree(id);
00215 apply_rule = 0;
00216 break;
00217 }
00218 xmlFree(id);
00219 } else {
00220 domain = NULL;
00221 domain = xmlNodeGetAttrContentByName(except_node,
00222 "domain");
00223 if(domain!=NULL) {
00224 LM_DBG("Found except domain= %s\n- strlen(domain)= %d\n",
00225 domain, (int)strlen(domain));
00226 if (strlen(domain)==subs->from_domain.len &&
00227 (strncmp(domain,subs->from_domain.s ,
00228 subs->from_domain.len)==0)) {
00229 LM_DBG("except domain match\n");
00230 xmlFree(domain);
00231 apply_rule = 0;
00232 break;
00233 }
00234 xmlFree(domain);
00235 }
00236 }
00237 }
00238 if (apply_rule == 1)
00239 break;
00240 }
00241 }
00242 if (apply_rule ==1)
00243 break;
00244 }
00245
00246 LM_DBG("apply_rule= %d\n", apply_rule);
00247 if(w_uri.s!=NULL)
00248 pkg_free(w_uri.s);
00249
00250 if( !apply_rule || !node1)
00251 return NULL;
00252
00253 return node1;
00254
00255 error:
00256 if(w_uri.s)
00257 pkg_free(w_uri.s);
00258 return NULL;
00259 }
00260
00261 int pres_watcher_allowed(subs_t* subs)
00262 {
00263 xmlDocPtr xcap_tree= NULL;
00264 xmlNodePtr node= NULL, actions_node = NULL;
00265 xmlNodePtr sub_handling_node = NULL;
00266 char* sub_handling = NULL;
00267
00268 subs->status= PENDING_STATUS;
00269 subs->reason.s= NULL;
00270 subs->reason.len= 0;
00271
00272 if (subs->auth_rules_doc== NULL)
00273 return 0;
00274
00275 xcap_tree= xmlParseMemory(subs->auth_rules_doc->s,
00276 subs->auth_rules_doc->len);
00277 if (xcap_tree== NULL) {
00278 LM_ERR("parsing xml memory\n");
00279 return -1;
00280 }
00281
00282 node= get_rule_node(subs, xcap_tree);
00283 if (node== NULL) {
00284 xmlFreeDoc(xcap_tree);
00285 return 0;
00286 }
00287
00288
00289 actions_node = xmlNodeGetChildByName(node, "actions");
00290 if (actions_node == NULL) {
00291 LM_DBG("actions_node NULL\n");
00292 xmlFreeDoc(xcap_tree);
00293 return 0;
00294 }
00295 LM_DBG("actions_node->name= %s\n", actions_node->name);
00296
00297 sub_handling_node = xmlNodeGetChildByName(actions_node, "sub-handling");
00298 if (sub_handling_node== NULL) {
00299 LM_DBG("sub_handling_node NULL\n");
00300 xmlFreeDoc(xcap_tree);
00301 return 0;
00302 }
00303 sub_handling = (char*)xmlNodeGetContent(sub_handling_node);
00304 LM_DBG("sub_handling_node->name= %s\n", sub_handling_node->name);
00305 LM_DBG("sub_handling_node->content= %s\n", sub_handling);
00306
00307 if (sub_handling == NULL) {
00308 LM_ERR("Couldn't get sub-handling content\n");
00309 xmlFreeDoc(xcap_tree);
00310 return -1;
00311 }
00312 if (strncmp((char*)sub_handling, "block", 5) == 0) {
00313 subs->status = TERMINATED_STATUS;;
00314 subs->reason.s= "rejected";
00315 subs->reason.len = 8;
00316 } else
00317 if (strncmp((char*)sub_handling, "confirm", 7) == 0) {
00318 subs->status = PENDING_STATUS;
00319 } else
00320 if (strncmp((char*)sub_handling , "polite-block", 12) == 0) {
00321 subs->status = ACTIVE_STATUS;
00322 subs->reason.s= "polite-block";
00323 subs->reason.len = 12;
00324 }
00325 else
00326 if (strncmp((char*)sub_handling, "allow", 5) == 0) {
00327 subs->status = ACTIVE_STATUS;
00328 subs->reason.s = NULL;
00329 }
00330 else {
00331 LM_ERR("unknown subscription handling action\n");
00332 xmlFreeDoc(xcap_tree);
00333 xmlFree(sub_handling);
00334 return -1;
00335 }
00336
00337 xmlFreeDoc(xcap_tree);
00338 xmlFree(sub_handling);
00339
00340 return 0;
00341
00342 }
00343
00344 int get_rules_doc(str* user, str* domain, int type, str** rules_doc)
00345 {
00346 db_key_t query_cols[5];
00347 db_val_t query_vals[5];
00348 db_key_t result_cols[3];
00349 int n_query_cols = 0;
00350 db1_res_t *result = 0;
00351 db_row_t *row;
00352 db_val_t *row_vals;
00353 str body;
00354 str* doc= NULL;
00355 int n_result_cols= 0, xcap_doc_col;
00356 static str tmp1 = str_init("username");
00357 static str tmp2 = str_init("domain");
00358 static str tmp3 = str_init("doc_type");
00359 static str tmp4 = str_init("doc");
00360
00361 LM_DBG("[user]= %.*s\t[domain]= %.*s",
00362 user->len, user->s, domain->len, domain->s);
00363
00364 query_cols[n_query_cols] = &tmp1;
00365 query_vals[n_query_cols].type = DB1_STR;
00366 query_vals[n_query_cols].nul = 0;
00367 query_vals[n_query_cols].val.str_val = *user;
00368 n_query_cols++;
00369
00370 query_cols[n_query_cols] = &tmp2;
00371 query_vals[n_query_cols].type = DB1_STR;
00372 query_vals[n_query_cols].nul = 0;
00373 query_vals[n_query_cols].val.str_val = *domain;
00374 n_query_cols++;
00375
00376 query_cols[n_query_cols] = &tmp3;
00377 query_vals[n_query_cols].type = DB1_INT;
00378 query_vals[n_query_cols].nul = 0;
00379 query_vals[n_query_cols].val.int_val= type;
00380 n_query_cols++;
00381
00382 result_cols[xcap_doc_col= n_result_cols++] = &tmp4;
00383
00384 if (pres_dbf.query(pres_dbh, query_cols, 0 , query_vals, result_cols,
00385 n_query_cols, 1, 0, &result) < 0) {
00386 LM_ERR("while querying table xcap for [user]=%.*s\t[domain]= %.*s\n",
00387 user->len, user->s, domain->len, domain->s);
00388 if (result)
00389 pres_dbf.free_result(pres_dbh, result);
00390 return -1;
00391 }
00392
00393 if(result == NULL)
00394 return -1;
00395
00396 if (result->n <= 0) {
00397 LM_DBG("No document found in db table for [user]=%.*s"
00398 "\t[domain]= %.*s\t[doc_type]= %d\n",user->len, user->s,
00399 domain->len, domain->s, type);
00400 pres_dbf.free_result(pres_dbh, result);
00401 return 0;
00402 }
00403
00404 row = &result->rows[xcap_doc_col];
00405 row_vals = ROW_VALUES(row);
00406
00407 body.s = (char*)row_vals[0].val.string_val;
00408 if (body.s== NULL) {
00409 LM_ERR("Xcap doc NULL\n");
00410 goto error;
00411 }
00412 body.len = strlen(body.s);
00413 if (body.len== 0) {
00414 LM_ERR("Xcap doc empty\n");
00415 goto error;
00416 }
00417 LM_DBG("xcap document:\n%.*s", body.len,body.s);
00418
00419 doc= (str*)pkg_malloc(sizeof(str));
00420 if (doc== NULL) {
00421 ERR_MEM(PKG_MEM_STR);
00422 }
00423 doc->s= (char*)pkg_malloc(body.len* sizeof(char));
00424 if (doc->s== NULL) {
00425 pkg_free(doc);
00426 ERR_MEM(PKG_MEM_STR);
00427 }
00428 memcpy(doc->s, body.s, body.len);
00429 doc->len= body.len;
00430
00431 *rules_doc= doc;
00432
00433 if (result)
00434 pres_dbf.free_result(pres_dbh, result);
00435
00436 return 0;
00437
00438 error:
00439 if (result)
00440 pres_dbf.free_result(pres_dbh, result);
00441
00442 return -1;
00443
00444 }
00445
00446
00447
00448
00449
00450
00451 int xcap_auth_status(struct sip_msg* _msg, char* _sp1, char* _sp2)
00452 {
00453 pv_spec_t *sp;
00454 pv_value_t pv_val;
00455 str watcher_uri, presentity_uri;
00456 struct sip_uri uri;
00457 str* rules_doc = NULL;
00458 subs_t subs;
00459 int res;
00460
00461 if (pres_dbh == 0) {
00462 LM_ERR("function is disabled, to enable define pres_db_url\n");
00463 return -1;
00464 }
00465
00466 sp = (pv_spec_t *)_sp1;
00467
00468 if (sp && (pv_get_spec_value(_msg, sp, &pv_val) == 0)) {
00469 if (pv_val.flags & PV_VAL_STR) {
00470 watcher_uri = pv_val.rs;
00471 if (watcher_uri.len == 0 || watcher_uri.s == NULL) {
00472 LM_ERR("missing watcher uri\n");
00473 return -1;
00474 }
00475 } else {
00476 LM_ERR("watcher pseudo variable value is not string\n");
00477 return -1;
00478 }
00479 } else {
00480 LM_ERR("cannot get watcher pseudo variable value\n");
00481 return -1;
00482 }
00483
00484 sp = (pv_spec_t *)_sp2;
00485
00486 if (sp && (pv_get_spec_value(_msg, sp, &pv_val) == 0)) {
00487 if (pv_val.flags & PV_VAL_STR) {
00488 presentity_uri = pv_val.rs;
00489 if (presentity_uri.len == 0 || presentity_uri.s == NULL) {
00490 LM_DBG("missing presentity uri\n");
00491 return -1;
00492 }
00493 } else {
00494 LM_ERR("presentity pseudo variable value is not string\n");
00495 return -1;
00496 }
00497 } else {
00498 LM_ERR("cannot get presentity pseudo variable value\n");
00499 return -1;
00500 }
00501
00502 if (parse_uri(presentity_uri.s, presentity_uri.len, &uri) < 0) {
00503 LM_ERR("failed to parse presentity uri\n");
00504 return -1;
00505 }
00506 res = get_rules_doc(&uri.user, &uri.host, PRES_RULES, &rules_doc);
00507 if ((res < 0) || (rules_doc == NULL) || (rules_doc->s == NULL)) {
00508 LM_DBG("no xcap rules doc found for presentity uri\n");
00509 return PENDING_STATUS;
00510 }
00511
00512 if (parse_uri(watcher_uri.s, watcher_uri.len, &uri) < 0) {
00513 LM_ERR("failed to parse watcher uri\n");
00514 goto err;
00515 }
00516
00517 subs.from_user = uri.user;
00518 subs.from_domain = uri.host;
00519 subs.pres_uri = presentity_uri;
00520 subs.auth_rules_doc = rules_doc;
00521 if (pres_watcher_allowed(&subs) < 0) {
00522 LM_ERR("getting status from rules document\n");
00523 goto err;
00524 }
00525 LM_DBG("auth status of watcher <%.*s> on presentity <%.*s> is %d\n",
00526 watcher_uri.len, watcher_uri.s, presentity_uri.len, presentity_uri.s,
00527 subs.status);
00528 pkg_free(rules_doc->s);
00529 pkg_free(rules_doc);
00530 return subs.status;
00531
00532 err:
00533 pkg_free(rules_doc->s);
00534 pkg_free(rules_doc);
00535 return -1;
00536 }