k/presence_xml/xcap_auth.c

Go to the documentation of this file.
00001 /*
00002  * $Id: xcap_auth.c 1337 2006-12-07 18:05:05Z bogdan_iancu $
00003  *
00004  * presence_xml module - 
00005  *
00006  * Copyright (C) 2007 Voice Sistem S.R.L.
00007  *
00008  * This file is part of Kamailio, a free SIP server.
00009  *
00010  * Kamailio is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version
00014  *
00015  * Kamailio is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License 
00021  * along with this program; if not, write to the Free Software 
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023  *
00024  * History:
00025  * --------
00026  *  2007-04-11  initial version (anca)
00027  */
00028 
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include <string.h>
00038 #include <time.h>
00039 #include <libxml/parser.h>
00040 
00041 #include "../../str.h"
00042 #include "../../dprint.h"
00043 #include "../../parser/parse_uri.h"
00044 #include "../presence/utils_func.h"
00045 #include "../presence/hash.h"
00046 #include "presence_xml.h"
00047 #include "xcap_auth.h"
00048 #include "pidf.h"
00049 
00050 int http_get_rules_doc(str user, str domain, str* rules_doc);
00051 
00052 int pres_watcher_allowed(subs_t* subs)
00053 {
00054         xmlDocPtr xcap_tree= NULL;
00055         xmlNodePtr node= NULL,  actions_node = NULL;
00056         xmlNodePtr sub_handling_node = NULL;
00057         char* sub_handling = NULL;
00058         
00059         /* if force_active set status to active*/
00060         if(force_active)
00061         {
00062                 subs->status= ACTIVE_STATUS;
00063                 subs->reason.s= NULL;
00064                 subs->reason.len= 0;
00065                 return 0;
00066         }
00067         subs->status= PENDING_STATUS;
00068         subs->reason.s= NULL;
00069         subs->reason.len= 0;
00070 
00071         if(subs->auth_rules_doc== NULL)
00072         {
00073                 return 0;
00074         }
00075 
00076         xcap_tree= xmlParseMemory(subs->auth_rules_doc->s,
00077                         subs->auth_rules_doc->len);
00078         if(xcap_tree== NULL)
00079         {
00080                 LM_ERR("parsing xml memory\n");
00081                 return -1;
00082         }
00083 
00084         node= get_rule_node(subs, xcap_tree);
00085         if(node== NULL)
00086         {
00087                 xmlFreeDoc(xcap_tree);
00088                 return 0;
00089         }
00090 
00091         /* process actions */   
00092         actions_node = xmlNodeGetChildByName(node, "actions");
00093         if(actions_node == NULL)
00094         {       
00095                 LM_DBG("actions_node NULL\n");
00096                 xmlFreeDoc(xcap_tree);
00097                 return 0;
00098         }
00099         LM_DBG("actions_node->name= %s\n",
00100                         actions_node->name);
00101                         
00102         sub_handling_node = xmlNodeGetChildByName(actions_node, "sub-handling");
00103         if(sub_handling_node== NULL)
00104         {       
00105                 LM_DBG("sub_handling_node NULL\n");
00106                 xmlFreeDoc(xcap_tree);
00107                 return 0;
00108         }
00109         sub_handling = (char*)xmlNodeGetContent(sub_handling_node);
00110                 LM_DBG("sub_handling_node->name= %s\n",
00111                         sub_handling_node->name);
00112         LM_DBG("sub_handling_node->content= %s\n",
00113                         sub_handling);
00114         
00115         if(sub_handling== NULL)
00116         {
00117                 LM_ERR("Couldn't get sub-handling content\n");
00118                 xmlFreeDoc(xcap_tree);
00119                 return -1;
00120         }
00121         if( strncmp((char*)sub_handling, "block",5 )==0)
00122         {       
00123                 subs->status = TERMINATED_STATUS;;
00124                 subs->reason.s= "rejected";
00125                 subs->reason.len = 8;
00126         }
00127         else    
00128         if( strncmp((char*)sub_handling, "confirm",7 )==0)
00129         {       
00130                 subs->status = PENDING_STATUS;
00131         }
00132         else
00133         if( strncmp((char*)sub_handling , "polite-block",12 )==0)
00134         {       
00135                 subs->status = ACTIVE_STATUS;
00136                 subs->reason.s= "polite-block";
00137                 subs->reason.len = 12;
00138         }
00139         else
00140         if( strncmp((char*)sub_handling , "allow",5 )==0)
00141         {
00142                 subs->status = ACTIVE_STATUS;
00143                 subs->reason.s = NULL;
00144         }
00145         else
00146         {
00147                 LM_ERR("unknown subscription handling action\n");
00148                 xmlFree(sub_handling);
00149                 xmlFreeDoc(xcap_tree);
00150                 return -1;
00151         }
00152 
00153         xmlFree(sub_handling);
00154         xmlFreeDoc(xcap_tree);
00155         return 0;
00156 
00157 }       
00158 
00159 xmlNodePtr get_rule_node(subs_t* subs, xmlDocPtr xcap_tree )
00160 {
00161         str w_uri= {0, 0};
00162         char* id = NULL, *domain = NULL, *time_cont= NULL;
00163         int apply_rule = -1;
00164         xmlNodePtr ruleset_node = NULL, node1= NULL, node2= NULL;
00165         xmlNodePtr cond_node = NULL, except_node = NULL;
00166         xmlNodePtr identity_node = NULL, sphere_node = NULL;
00167         xmlNodePtr iden_child;
00168         xmlNodePtr validity_node, time_node;
00169         time_t t_init, t_fin, t;
00170         int valid= 0;
00171 
00172 
00173         uandd_to_uri(subs->watcher_user, subs->watcher_domain, &w_uri);
00174         if(w_uri.s == NULL)
00175         {
00176                 LM_ERR("while creating uri\n");
00177                 return NULL;
00178         }
00179         ruleset_node = xmlDocGetNodeByName(xcap_tree, "ruleset", NULL);
00180         if(ruleset_node == NULL)
00181         {
00182                 LM_DBG("ruleset_node NULL\n");
00183                 goto error;
00184 
00185         }       
00186         for(node1 = ruleset_node->children ; node1; node1 = node1->next)
00187         {
00188                 if(xmlStrcasecmp(node1->name, (unsigned char*)"text")==0 )
00189                                 continue;
00190 
00191                 /* process conditions */
00192                 LM_DBG("node1->name= %s\n", node1->name);
00193 
00194                 cond_node = xmlNodeGetChildByName(node1, "conditions");
00195                 if(cond_node == NULL)
00196                 {       
00197                         LM_DBG("cond node NULL\n");
00198                         goto error;
00199                 }
00200                 LM_DBG("cond_node->name= %s\n", cond_node->name);
00201 
00202                 validity_node = xmlNodeGetChildByName(cond_node, "validity");
00203                 if(validity_node !=NULL)
00204                 {
00205                         LM_DBG("found validity tag\n");
00206                 
00207                         t= time(NULL);
00208                 
00209                         /* search all from-until pair */
00210                         for(time_node= validity_node->children; time_node;
00211                                         time_node= time_node->next)
00212                         {
00213                                 if(xmlStrcasecmp(time_node->name, (unsigned char*)"from")!= 0)
00214                                 {
00215                                         continue;
00216                                 }
00217                                 time_cont= (char*)xmlNodeGetContent(time_node);
00218                                 t_init= xml_parse_dateTime(time_cont);
00219                                 xmlFree(time_cont);
00220                                 if(t_init< 0)
00221                                 {
00222                                         LM_ERR("failed to parse xml dateTime\n");
00223                                         goto error;
00224                                 }
00225 
00226                                 if(t< t_init)
00227                                 {
00228                                         LM_DBG("the lower time limit is not respected\n");
00229                                         continue;
00230                                 }
00231                                 
00232                                 time_node= time_node->next;
00233                                 while(1)
00234                                 {
00235                                         if(time_node== NULL)
00236                                         {       
00237                                                 LM_ERR("bad formatted xml doc:until child not found in"
00238                                                                 " validity pair\n");
00239                                                 goto error;
00240                                         }
00241                                         if( xmlStrcasecmp(time_node->name, 
00242                                                                 (unsigned char*)"until")== 0)
00243                                                 break;
00244                                         time_node= time_node->next;
00245                                 }
00246                                 
00247                                 time_cont= (char*)xmlNodeGetContent(time_node);
00248                                 t_fin= xml_parse_dateTime(time_cont);
00249                                 xmlFree(time_cont);
00250 
00251                                 if(t_fin< 0)
00252                                 {
00253                                         LM_ERR("failed to parse xml dateTime\n");
00254                                         goto error;
00255                                 }
00256                         
00257                                 if(t <= t_fin)
00258                                 {
00259                                         LM_DBG("the rule is active at this time\n");
00260                                         valid= 1;
00261                                 }
00262                         
00263                         }
00264                 
00265                         if(!valid)
00266                         {
00267                                 LM_DBG("the rule is not active at this time\n");
00268                                 continue;
00269                         }
00270 
00271                 }       
00272         
00273                 sphere_node = xmlNodeGetChildByName(cond_node, "sphere");
00274                 if(sphere_node!= NULL)
00275                 {
00276                         /* check to see if matches presentity current sphere */
00277                         /* ask presence for sphere information */
00278                         
00279                         char* sphere= pres_get_sphere(&subs->pres_uri);
00280                         if(sphere)
00281                         {
00282                                 char* attr= (char*)xmlNodeGetContent(sphere_node);
00283                                 if(xmlStrcasecmp((unsigned char*)attr, (unsigned char*)sphere)!= 0)
00284                                 {
00285                                         LM_DBG("sphere condition not respected\n");
00286                                         pkg_free(sphere);
00287                                         xmlFree(attr);
00288                                         continue;
00289                                 }
00290                                 pkg_free(sphere);
00291                                 xmlFree(attr);
00292         
00293                         }
00294                                 
00295                         /* if the user has not define a sphere -> 
00296                          *                                              consider the condition true*/
00297                 }
00298 
00299                 identity_node = xmlNodeGetChildByName(cond_node, "identity");
00300                 if(identity_node == NULL)
00301                 {
00302                         LM_ERR("didn't find identity tag\n");
00303                         goto error;
00304                 }       
00305                 
00306                 iden_child= xmlNodeGetChildByName(identity_node, "one");
00307                 if(iden_child)  
00308                 {
00309                         for(node2 = identity_node->children; node2; node2 = node2->next)
00310                         {
00311                                 if(xmlStrcasecmp(node2->name, (unsigned char*)"one")!= 0)
00312                                         continue;
00313                                 
00314                                 id = xmlNodeGetAttrContentByName(node2, "id");  
00315                                 if(id== NULL)
00316                                 {
00317                                         LM_ERR("while extracting attribute\n");
00318                                         goto error;
00319                                 }
00320                                 if((strlen(id)== w_uri.len && 
00321                                                         (strncmp(id, w_uri.s, w_uri.len)==0)))  
00322                                 {
00323                                         apply_rule = 1;
00324                                         xmlFree(id);
00325                                         break;
00326                                 }
00327                                 xmlFree(id);
00328                         }
00329                 }       
00330 
00331                 /* search for many node*/
00332                 iden_child= xmlNodeGetChildByName(identity_node, "many");
00333                 if(iden_child)  
00334                 {
00335                         domain = NULL;
00336                         for(node2 = identity_node->children; node2; node2 = node2->next)
00337                         {
00338                                 if(xmlStrcasecmp(node2->name, (unsigned char*)"many")!= 0)
00339                                         continue;
00340         
00341                                 domain = xmlNodeGetAttrContentByName(node2, "domain");
00342                                 if(domain == NULL)
00343                                 {       
00344                                         LM_DBG("No domain attribute to many\n");
00345                                 }
00346                                 else    
00347                                 {
00348                                         LM_DBG("<many domain= %s>\n", domain);
00349                                         if((strlen(domain)!= subs->from_domain.len && 
00350                                                                 strncmp(domain, subs->from_domain.s,
00351                                                                         subs->from_domain.len) ))
00352                                         {
00353                                                 xmlFree(domain);
00354                                                 continue;
00355                                         }       
00356                                 }
00357                                 xmlFree(domain);
00358                                 apply_rule = 1;
00359                                 if(node2->children == NULL)       /* there is no exception */
00360                                         break;
00361 
00362                                 for(except_node = node2->children; except_node;
00363                                                 except_node= except_node->next)
00364                                 {
00365                                         if(xmlStrcasecmp(except_node->name, (unsigned char*)"except"))
00366                                                 continue;
00367 
00368                                         id = xmlNodeGetAttrContentByName(except_node, "id");    
00369                                         if(id!=NULL)
00370                                         {
00371                                                 if((strlen(id)- 1== w_uri.len && 
00372                                                                 (strncmp(id, w_uri.s, w_uri.len)==0)))  
00373                                                 {
00374                                                         xmlFree(id);
00375                                                         apply_rule = 0;
00376                                                         break;
00377                                                 }
00378                                                 xmlFree(id);
00379                                         }       
00380                                         else
00381                                         {
00382                                                 domain = NULL;
00383                                                 domain = xmlNodeGetAttrContentByName(except_node, "domain");
00384                                                 if(domain!=NULL)
00385                                                 {
00386                                                         LM_DBG("Found except domain= %s\n- strlen(domain)= %d\n",
00387                                                                         domain, (int)strlen(domain));
00388                                                         if(strlen(domain)==subs->from_domain.len &&
00389                                                                 (strncmp(domain,subs->from_domain.s , subs->from_domain.len)==0))       
00390                                                         {
00391                                                                 LM_DBG("except domain match\n");
00392                                                                 xmlFree(domain);
00393                                                                 apply_rule = 0;
00394                                                                 break;
00395                                                         }
00396                                                         xmlFree(domain);
00397                                                 }       
00398 
00399                                         }       
00400                                 }
00401                                 if(apply_rule== 1)  /* if a match was found no need to keep searching*/
00402                                         break;
00403 
00404                         }               
00405                 }
00406                 if(apply_rule ==1)
00407                         break;
00408         }
00409 
00410         LM_DBG("apply_rule= %d\n", apply_rule);
00411         if(w_uri.s!=NULL)
00412                 pkg_free(w_uri.s);
00413 
00414         if( !apply_rule || !node1)
00415                 return NULL;
00416 
00417         return node1;
00418 
00419 error:
00420         if(w_uri.s)
00421                 pkg_free(w_uri.s);
00422         return NULL;
00423 }       
00424 
00425 int pres_get_rules_doc(str* user, str* domain, str** rules_doc)
00426 {
00427         
00428         return get_rules_doc(user, domain, PRES_RULES, rules_doc);
00429 }
00430 
00431 int get_rules_doc(str* user, str* domain, int type, str** rules_doc)
00432 {
00433         db_key_t query_cols[5];
00434         db_val_t query_vals[5];
00435         db_key_t result_cols[3];
00436         int n_query_cols = 0;
00437         db1_res_t *result = 0;
00438         db_row_t *row;
00439         db_val_t *row_vals;
00440         str body;
00441         str* doc= NULL;
00442         int n_result_cols= 0, xcap_doc_col;
00443         static str tmp1 = str_init("username");
00444         static str tmp2 = str_init("domain");
00445         static str tmp3 = str_init("doc_type");
00446         static str tmp4 = str_init("doc");
00447 
00448         if(force_active)
00449         {
00450                 *rules_doc= NULL;
00451                 return 0;
00452         }
00453         LM_DBG("[user]= %.*s\t[domain]= %.*s", 
00454                         user->len, user->s,     domain->len, domain->s);
00455         /* first search in database */
00456         query_cols[n_query_cols] = &tmp1;
00457         query_vals[n_query_cols].type = DB1_STR;
00458         query_vals[n_query_cols].nul = 0;
00459         query_vals[n_query_cols].val.str_val = *user;
00460         n_query_cols++;
00461         
00462         query_cols[n_query_cols] = &tmp2;
00463         query_vals[n_query_cols].type = DB1_STR;
00464         query_vals[n_query_cols].nul = 0;
00465         query_vals[n_query_cols].val.str_val = *domain;
00466         n_query_cols++;
00467         
00468         query_cols[n_query_cols] = &tmp3;
00469         query_vals[n_query_cols].type = DB1_INT;
00470         query_vals[n_query_cols].nul = 0;
00471         query_vals[n_query_cols].val.int_val= type;
00472         n_query_cols++;
00473 
00474         result_cols[xcap_doc_col= n_result_cols++] = &tmp4;
00475         
00476         if (pxml_dbf.use_table(pxml_db, &xcap_table) < 0) 
00477         {
00478                 LM_ERR("in use_table-[table]= %.*s\n", xcap_table.len, xcap_table.s);
00479                 return -1;
00480         }
00481 
00482         if( pxml_dbf.query(pxml_db, query_cols, 0 , query_vals, result_cols, 
00483                                 n_query_cols, 1, 0, &result)<0)
00484         {
00485                 LM_ERR("while querying table xcap for [user]=%.*s\t[domain]= %.*s\n",
00486                                 user->len, user->s,     domain->len, domain->s);
00487                 if(result)
00488                         pxml_dbf.free_result(pxml_db, result);
00489                 return -1;
00490         }
00491         if(result== NULL)
00492                 return -1;
00493 
00494         if(result->n<= 0)
00495         {
00496                 LM_DBG("No document found in db table for [user]=%.*s"
00497                         "\t[domain]= %.*s\t[doc_type]= %d\n",user->len, user->s,
00498                         domain->len, domain->s, type);
00499                 
00500                 if(!integrated_xcap_server)
00501                 {
00502                         if(http_get_rules_doc(*user, *domain, &body)< 0)
00503                         {
00504                                 LM_ERR("sending http GET request to xcap server\n");            
00505                                 goto error;
00506                         }
00507                         if(body.s && body.len)
00508                                 goto done; 
00509                 }
00510                 pxml_dbf.free_result(pxml_db, result);
00511                 return 0;
00512         }       
00513         
00514         row = &result->rows[xcap_doc_col];
00515         row_vals = ROW_VALUES(row);
00516 
00517         body.s = (char*)row_vals[0].val.string_val;
00518         if(body.s== NULL)
00519         {
00520                 LM_ERR("Xcap doc NULL\n");
00521                 goto error;
00522         }       
00523         body.len = strlen(body.s);
00524         if(body.len== 0)
00525         {
00526                 LM_ERR("Xcap doc empty\n");
00527                 goto error;
00528         }                       
00529         LM_DBG("xcap document:\n%.*s", body.len,body.s);
00530 
00531 done:
00532         doc= (str*)pkg_malloc(sizeof(str));
00533         if(doc== NULL)
00534         {
00535                 ERR_MEM(PKG_MEM_STR);
00536         }
00537         doc->s= (char*)pkg_malloc(body.len* sizeof(char));
00538         if(doc->s== NULL)
00539         {
00540                 pkg_free(doc);
00541                 ERR_MEM(PKG_MEM_STR);
00542         }
00543         memcpy(doc->s, body.s, body.len);
00544         doc->len= body.len;
00545 
00546         *rules_doc= doc;
00547 
00548         if(result)
00549                 pxml_dbf.free_result(pxml_db, result);
00550 
00551         return 0;
00552 
00553 error:
00554         if(result)
00555                 pxml_dbf.free_result(pxml_db, result);
00556 
00557         return -1;
00558 
00559 }
00560 
00561 int http_get_rules_doc(str user, str domain, str* rules_doc)
00562 {
00563         str uri;
00564         xcap_doc_sel_t doc_sel;
00565         char* doc= NULL;
00566         xcap_serv_t* xs;
00567         xcap_get_req_t req;
00568 
00569         memset(&req, 0, sizeof(xcap_get_req_t));
00570         if(uandd_to_uri(user, domain, &uri)< 0)
00571         {
00572                 LM_ERR("constructing uri\n");
00573                 goto error;
00574         }
00575 
00576         doc_sel.auid.s= "pres-rules";
00577         doc_sel.auid.len= strlen("pres-rules");
00578         doc_sel.doc_type= PRES_RULES;
00579         doc_sel.type= USERS_TYPE;
00580         doc_sel.xid= uri;
00581         doc_sel.filename.s= "index";
00582         doc_sel.filename.len= 5;
00583 
00584         /* need the whole document so the node selector is NULL */
00585         /* don't know which is the authoritative server for the user
00586          * so send request to all in the list */
00587         req.doc_sel= doc_sel;
00588 
00589         xs= xs_list;
00590         while(xs)
00591         {
00592                 req.xcap_root= xs->addr;
00593                 req.port= xs->port;
00594                 doc= xcap_GetNewDoc(req, user, domain);
00595                 if(doc!=NULL)
00596                         break;
00597                 xs = xs->next;
00598         }
00599 
00600         rules_doc->s= doc;
00601         rules_doc->len= doc?strlen(doc):0;
00602         
00603         return 0;
00604 
00605 error:
00606         return -1;
00607 }