09c5c49aa2dcd7b1c1bb474d453bfe0a8cdb5d14
[sip-router] / src / modules / h350 / h350_exp_fn.c
1 /*
2  * Kamailio H.350 Module
3  *
4  * Copyright (C) 2007 University of North Carolina
5  *
6  * Original author: Christian Schlatter, cs@unc.edu
7  *
8  * This file is part of Kamailio, a free SIP server.
9  *
10  * Kamailio 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  * Kamailio is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
23  *
24  */
25
26 #include <regex.h>
27 #include "ldap.h"
28
29 #include "h350_mod.h"
30 #include "h350_exp_fn.h"
31
32 #include "../../core/pvar.h"
33 #include "../../core/ut.h"
34 #include "../../core/mem/mem.h"
35
36 #define H350_SIPURI_LOOKUP_LDAP_FILTER "(&(objectClass=SIPIdentity)(SIPIdentitySIPURI=%s))"
37 #define H350_AUTH_FILTER_PATTERN "(&(objectClass=SIPIdentity)(SIPIdentityUserName=%s))"
38
39 static str h350_call_pref_name = str_init("callPreferenceURI");
40 static str h350_sip_pwd_name = str_init("SIPIdentityPassword");
41 static str h350_service_level_name = str_init("SIPIdentityServiceLevel");
42
43 #define H350_CALL_PREF_REGEX "^([^ ]+) +([a-zA-Z]+)(:([0-9]+))?$"
44
45 #define SIP_URI_ESCAPED_MAX_LEN 1024
46 #define AVP_NAME_STR_BUF_LEN 1024
47 #define DIGEST_USERNAME_BUF_SIZE 2048
48
49 static regex_t* call_pref_preg;
50
51 int h350_sipuri_lookup(struct sip_msg* _msg, pv_elem_t* _sip_uri)
52 {
53         str sip_uri, sip_uri_escaped;
54         int ld_result_count;
55         static char sip_uri_escaped_buf[SIP_URI_ESCAPED_MAX_LEN];
56
57         /*
58          * get sip_uri
59          */
60         if (pv_printf_s(_msg, _sip_uri, &sip_uri) != 0)
61         {
62                 LM_ERR("pv_printf_s failed\n");
63                 return E_H350_INTERNAL;
64         }
65
66         /*
67          * ldap filter escape sip_uri
68          */
69         sip_uri_escaped.s = sip_uri_escaped_buf;
70         sip_uri_escaped.len = SIP_URI_ESCAPED_MAX_LEN - 1;
71         if (ldap_api.ldap_rfc4515_escape(&sip_uri, &sip_uri_escaped, 0))
72         {
73                 LM_ERR("ldap_rfc4515_escape failed\n");
74                 return E_H350_INTERNAL;
75         }
76         
77         /*
78          * do ldap search
79          */
80         if (ldap_api.ldap_params_search(&ld_result_count,
81                                         h350_ldap_session,
82                                         h350_base_dn,
83                                         h350_search_scope_int,
84                                         NULL,
85                                         H350_SIPURI_LOOKUP_LDAP_FILTER,
86                                         sip_uri_escaped.s)
87             != 0)
88         {
89                 LM_ERR("ldap search failed\n");
90                 return E_H350_INTERNAL;
91         }
92         
93         if (ld_result_count < 1)
94         {
95                 return E_H350_NO_SUCCESS;
96         }
97
98         return ld_result_count;
99 }
100
101 int h350_auth_lookup(
102         struct sip_msg* _msg,
103         pv_elem_t* _digest_username,
104         struct h350_auth_lookup_avp_params* _avp_specs)
105 {
106         str                digest_username,
107                            digest_username_escaped,
108                            digest_password;
109         static char        digest_username_buf[DIGEST_USERNAME_BUF_SIZE],
110                            username_avp_name_buf[AVP_NAME_STR_BUF_LEN],
111                            password_avp_name_buf[AVP_NAME_STR_BUF_LEN];
112         struct berval      **attr_vals = NULL;
113         int_str            username_avp_name, password_avp_name, avp_val;
114         unsigned short     username_avp_type, password_avp_type;
115         int                rc, ld_result_count;
116
117         /*
118          * get digest_username str
119          */
120         if (_digest_username) 
121         {
122                 if (pv_printf_s(_msg, _digest_username, &digest_username) != 0) 
123                 {
124                         LM_ERR("pv_printf_s failed\n");
125                         return E_H350_INTERNAL;
126                 }
127         } else
128         {
129                 LM_ERR("empty digest username\n");
130                 return E_H350_NO_SUCCESS;
131         }
132
133         /*
134          * get AVP names for username and password
135          */
136
137         if (pv_get_avp_name(    _msg,
138                                 &(_avp_specs->username_avp_spec.pvp),
139                                 &username_avp_name,
140                                 &username_avp_type)
141                 != 0)
142         {
143                 LM_ERR("error getting AVP name - pv_get_avp_name failed\n");
144                 return E_H350_INTERNAL;
145         }
146         if (username_avp_type & AVP_NAME_STR)
147         {
148                 if (username_avp_name.s.len >= AVP_NAME_STR_BUF_LEN)
149                 {
150                         LM_ERR("username AVP name too long\n");
151                         return E_H350_INTERNAL;
152                 }
153                 strncpy(username_avp_name_buf, username_avp_name.s.s, username_avp_name.s.len);
154                 username_avp_name_buf[username_avp_name.s.len] = '\0';
155                 username_avp_name.s.s = username_avp_name_buf;
156         }
157
158         if (pv_get_avp_name(_msg,
159                                                 &(_avp_specs->password_avp_spec.pvp),
160                                                 &password_avp_name,
161                                                 &password_avp_type)
162                 != 0)
163         {
164                 LM_ERR("error getting AVP name - pv_get_avp_name failed\n");
165                 return E_H350_INTERNAL;
166         }
167         if (password_avp_type & AVP_NAME_STR)
168         {
169                 if (password_avp_name.s.len >= AVP_NAME_STR_BUF_LEN)
170                 {
171                         LM_ERR("password AVP name too long\n");
172                         return E_H350_INTERNAL;
173                 }
174                 strncpy(password_avp_name_buf, 
175                                                 password_avp_name.s.s, 
176                                                 password_avp_name.s.len);
177                 password_avp_name_buf[password_avp_name.s.len] = '\0';
178                 password_avp_name.s.s = password_avp_name_buf;
179         }
180         
181
182         /* 
183          * search for sip digest username in H.350, store digest password
184          */
185         
186         /* ldap filter escape digest username */
187         digest_username_escaped.s = digest_username_buf;
188         digest_username_escaped.len = DIGEST_USERNAME_BUF_SIZE - 1;
189         if (ldap_api.ldap_rfc4515_escape(
190                 &digest_username, 
191                 &digest_username_escaped, 
192                 0)
193            )
194         {
195                 LM_ERR("ldap_rfc4515_escape() failed\n");
196                 return E_H350_INTERNAL;
197         }
198
199         /* do ldap search */
200         if (ldap_api.ldap_params_search(&ld_result_count,
201                                         h350_ldap_session,
202                                         h350_base_dn,
203                                         h350_search_scope_int,
204                                         NULL,
205                                         H350_AUTH_FILTER_PATTERN,
206                                         digest_username_escaped.s)
207             != 0)
208         {
209                 LM_ERR("LDAP search failed\n");
210                 return E_H350_INTERNAL;
211         }
212
213         if (ld_result_count < 1)
214         {
215                 LM_INFO("no H.350 entry found for username [%s]\n",
216                         digest_username_escaped.s);
217                 return E_H350_NO_SUCCESS;
218         }
219         if (ld_result_count > 1)
220         {
221                 LM_WARN("more than one [%d] H.350 entry found for username [%s]\n",
222                         ld_result_count,
223                         digest_username_escaped.s);
224         }
225
226         /* get ldap result values */
227         rc = ldap_api.ldap_result_attr_vals(&h350_sip_pwd_name, &attr_vals);
228         if (rc < 0) 
229         {
230                 LM_ERR("getting LDAP attribute values failed\n");
231                 ldap_api.ldap_value_free_len(attr_vals);
232                 return E_H350_INTERNAL;
233         }
234         if ((rc > 0) || (attr_vals == NULL)) 
235         {
236                 LM_INFO("no values found in LDAP entry for username [%s]\n",
237                         digest_username_escaped.s);
238                 ldap_api.ldap_value_free_len(attr_vals);
239                 return E_H350_INTERNAL;
240         }
241
242         digest_password.s = attr_vals[0]->bv_val;
243         digest_password.len = attr_vals[0]->bv_len;
244
245         /*
246          * write AVPs
247          */
248         
249         avp_val.s = digest_username;
250         if (add_avp(    username_avp_type | AVP_VAL_STR, 
251                         username_avp_name, 
252                         avp_val) 
253                 < 0)
254         {
255                 LM_ERR("failed to create new AVP\n");
256                 ldap_api.ldap_value_free_len(attr_vals);
257                 return E_H350_INTERNAL;
258         }
259
260         avp_val.s = digest_password;
261         if (add_avp(    password_avp_type | AVP_VAL_STR,
262                         password_avp_name,
263                         avp_val)
264                 < 0)
265         {
266                 LM_ERR("failed to create new AVP\n");
267                 ldap_api.ldap_value_free_len(attr_vals);
268                 return E_H350_INTERNAL;
269         }
270
271         ldap_api.ldap_value_free_len(attr_vals);
272         return E_H350_SUCCESS;
273 }
274
275 int h350_call_preferences(struct sip_msg* _msg, pv_elem_t* _avp_name_prefix)
276 {
277         int           rc, i, avp_count = 0;
278         struct berval **attr_vals;
279         size_t        nmatch = 5;
280         regmatch_t    pmatch[5];
281         int_str       avp_name, avp_val;
282         str           avp_val_str, avp_name_str, 
283                       avp_name_prefix_str, call_pref_timeout_str;
284         int           call_pref_timeout;
285         static char   call_pref_avp_name[AVP_NAME_STR_BUF_LEN];
286
287         /*
288          * get avp_name_prefix_str
289          */
290         if (pv_printf_s(_msg, _avp_name_prefix, &avp_name_prefix_str) != 0)
291         {
292                 LM_ERR("pv_printf_s failed\n");
293                 return E_H350_INTERNAL;
294         }
295
296         
297         /*
298          * get LDAP attribute values
299          */
300         if ((rc = ldap_api.ldap_result_attr_vals(
301                         &h350_call_pref_name, &attr_vals)) < 0)
302         {
303                 LM_ERR("Getting LDAP attribute values failed\n");
304                 return E_H350_INTERNAL;
305         }
306
307         if (rc > 0)
308         {
309                 /* no LDAP values found */
310                 return E_H350_NO_SUCCESS;
311         }
312
313         /*
314          * loop through call pref values and add AVP(s)
315          */
316
317         /* copy avp name prefix into call_pref_avp_name */
318         if (avp_name_prefix_str.len < AVP_NAME_STR_BUF_LEN)
319         {
320                 memcpy(call_pref_avp_name, avp_name_prefix_str.s, avp_name_prefix_str.len);
321         } else
322         {
323                 LM_ERR("AVP name prefix too long [%d] (max [%d])", 
324                         avp_name_prefix_str.len, 
325                         AVP_NAME_STR_BUF_LEN);
326                 return E_H350_INTERNAL;
327         }
328
329         for (i = 0; attr_vals[i] != NULL; i++)
330         {
331                 if ((rc = regexec(call_pref_preg, attr_vals[i]->bv_val, nmatch, pmatch, 0)) != 0)
332                 {
333                         switch (rc)
334                         {
335                         case REG_NOMATCH:
336                                 LM_INFO("no h350 call preference regex match for [%s]\n", 
337                                                 attr_vals[i]->bv_val);
338                                 continue;
339                         case REG_ESPACE:
340                                 LM_ERR("regexec returned REG_ESPACE - out of memory\n");
341                         default:
342                                 LM_ERR("regexec failed\n");
343                                 ldap_api.ldap_value_free_len(attr_vals);
344                                 return E_H350_INTERNAL;
345                         }
346                 }
347
348                 /* calculate call preference sip uri */
349                 if (avp_name_prefix_str.len + pmatch[2].rm_eo - pmatch[2].rm_so 
350                         >= AVP_NAME_STR_BUF_LEN)
351                 {
352                         LM_ERR("AVP name too long for [%s]", attr_vals[i]->bv_val);
353                         continue;
354                 }
355                 avp_val_str.s = attr_vals[i]->bv_val + pmatch[1].rm_so;
356                 avp_val_str.len = pmatch[1].rm_eo - pmatch[1].rm_so;
357
358                 avp_val.s = avp_val_str;
359                 
360                 /* calculate call preference avp name */
361                 memcpy( call_pref_avp_name + avp_name_prefix_str.len, 
362                         attr_vals[i]->bv_val + pmatch[2].rm_so,
363                         pmatch[2].rm_eo - pmatch[2].rm_so);
364
365                 avp_name_str.s = call_pref_avp_name;
366                 avp_name_str.len = avp_name_prefix_str.len + pmatch[2].rm_eo - pmatch[2].rm_so;
367
368                 avp_name.s = avp_name_str;
369                 
370                 /* add avp */
371                 if (add_avp(AVP_NAME_STR | AVP_VAL_STR, avp_name, avp_val) < 0)
372                 {
373                         LM_ERR("failed to create new AVP\n");
374                         ldap_api.ldap_value_free_len(attr_vals);
375                         return E_H350_INTERNAL;
376                 }
377
378                 avp_count++;
379                 
380                 /* check for call preference timeout */
381                 if ((pmatch[4].rm_eo - pmatch[4].rm_so) == 0)
382                 {
383                         continue;
384                 }
385                 
386                 /* calculate call preference timeout avp name */
387                 memcpy( avp_name_str.s + avp_name_str.len, "_t", 2);
388                 avp_name_str.len += 2;
389                 avp_name.s = avp_name_str;
390
391                 /* calculate timeout avp value */
392                 call_pref_timeout_str.s = attr_vals[i]->bv_val + pmatch[4].rm_so;
393                 call_pref_timeout_str.len = pmatch[4].rm_eo - pmatch[4].rm_so;
394                 if (str2sint(&call_pref_timeout_str, &call_pref_timeout) != 0)
395                 {
396                         LM_ERR("str2sint failed\n");
397                         ldap_api.ldap_value_free_len(attr_vals);
398                         return E_H350_INTERNAL;
399                 }
400                 call_pref_timeout = call_pref_timeout / 1000;
401
402                 /* add timeout avp */
403                 avp_val.n = call_pref_timeout;
404                 if (add_avp(AVP_NAME_STR, avp_name, avp_val) < 0)
405                 {
406                         LM_ERR("failed to create new AVP\n");
407                         ldap_api.ldap_value_free_len(attr_vals);
408                         return E_H350_INTERNAL;
409                 }               
410         }
411
412         ldap_api.ldap_value_free_len(attr_vals);
413         if (avp_count > 0)
414         {
415                 return avp_count;
416         } else 
417         {
418                 return E_H350_NO_SUCCESS;
419         }
420 }
421
422 int h350_service_level(struct sip_msg* _msg, pv_elem_t* _avp_name_prefix)
423 {
424         int           i, rc, avp_count = 0;
425         str           avp_name_prefix;
426         int_str       avp_name, avp_val;
427         struct berval **attr_vals;
428         static char   service_level_avp_name[AVP_NAME_STR_BUF_LEN];
429
430         /*
431          * get service_level
432          */
433         if (pv_printf_s(_msg, _avp_name_prefix, &avp_name_prefix) != 0)
434         {
435                 LM_ERR("pv_printf_s failed\n");
436                 return E_H350_INTERNAL;
437         }
438
439         /*
440          * get LDAP attribute values
441          */
442         if ((rc = ldap_api.ldap_result_attr_vals(&h350_service_level_name, &attr_vals)) < 0)
443         {
444                 LM_ERR("Getting LDAP attribute values failed\n");
445                 return E_H350_INTERNAL;
446         }
447         if (rc > 0)
448         {
449                 /* no LDAP values found */
450                 return E_H350_NO_SUCCESS;
451         }
452
453         /* copy avp name prefix into service_level_avp_name */
454         if (avp_name_prefix.len < AVP_NAME_STR_BUF_LEN)
455         {
456                 memcpy(service_level_avp_name, avp_name_prefix.s, avp_name_prefix.len);
457         } else
458         {
459                 LM_ERR("AVP name prefix too long [%d] (max [%d])\n",
460                         avp_name_prefix.len,
461                         AVP_NAME_STR_BUF_LEN);
462                 ldap_api.ldap_value_free_len(attr_vals);
463                 return E_H350_INTERNAL;
464         }       
465         
466
467         /*
468          * loop through service level values and add AVP(s)
469          */
470
471         for (i = 0; attr_vals[i] != NULL; i++)
472         {
473                 /* get avp name */
474                 if (avp_name_prefix.len + attr_vals[i]->bv_len >= AVP_NAME_STR_BUF_LEN)
475                 {
476                         LM_ERR("AVP name too long for [%s]\n", attr_vals[i]->bv_val);
477                         continue;
478                 }
479                 memcpy( service_level_avp_name + avp_name_prefix.len, 
480                         attr_vals[i]->bv_val,
481                         attr_vals[i]->bv_len);
482                 avp_name.s.s = service_level_avp_name;
483                 avp_name.s.len = avp_name_prefix.len + attr_vals[i]->bv_len;
484                 
485                 /* avp value = 1 */
486                 avp_val.n = 1;
487
488                 if (add_avp(AVP_NAME_STR, avp_name, avp_val) < 0)
489                 {
490                         LM_ERR("failed to create new AVP\n");
491                         ldap_api.ldap_value_free_len(attr_vals);
492                         return E_H350_INTERNAL;
493                 }
494                 avp_count++;
495         }
496
497         ldap_api.ldap_value_free_len(attr_vals);
498         if (avp_count > 0)
499         {
500                 return avp_count;
501         } else
502         {
503                 return E_H350_NO_SUCCESS;
504         }
505 }
506
507 int h350_exp_fn_init(void)
508 {
509         int rc;
510
511         if ((call_pref_preg = pkg_malloc(sizeof(regex_t))) == 0)
512         {
513                 LM_ERR("allocating memory for regex failed\n");
514                 return -1;
515         }
516
517         if ((rc = regcomp(call_pref_preg, H350_CALL_PREF_REGEX, REG_EXTENDED)) != 0)
518         {
519                 pkg_free(call_pref_preg);
520                 LM_ERR("regcomp failed - returned [%d]\n", rc);
521                 return -1;
522         }
523         return 0;
524 }