h350: coherent indentation, removed dead code and init lenght for str
[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                 LM_ERR("pv_printf_s failed\n");
62                 return E_H350_INTERNAL;
63         }
64
65         /*
66          * ldap filter escape sip_uri
67          */
68         sip_uri_escaped.s = sip_uri_escaped_buf;
69         sip_uri_escaped.len = SIP_URI_ESCAPED_MAX_LEN - 1;
70         if(ldap_api.ldap_rfc4515_escape(&sip_uri, &sip_uri_escaped, 0)) {
71                 LM_ERR("ldap_rfc4515_escape failed\n");
72                 return E_H350_INTERNAL;
73         }
74
75         /*
76          * do ldap search
77          */
78         if(ldap_api.ldap_params_search(&ld_result_count, h350_ldap_session,
79                            h350_base_dn, h350_search_scope_int, NULL,
80                            H350_SIPURI_LOOKUP_LDAP_FILTER, sip_uri_escaped.s)
81                         != 0) {
82                 LM_ERR("ldap search failed\n");
83                 return E_H350_INTERNAL;
84         }
85
86         if(ld_result_count < 1) {
87                 return E_H350_NO_SUCCESS;
88         }
89
90         return ld_result_count;
91 }
92
93 int h350_auth_lookup(struct sip_msg *_msg, pv_elem_t *_digest_username,
94                 struct h350_auth_lookup_avp_params *_avp_specs)
95 {
96         str digest_username, digest_username_escaped, digest_password;
97         static char digest_username_buf[DIGEST_USERNAME_BUF_SIZE],
98                         username_avp_name_buf[AVP_NAME_STR_BUF_LEN],
99                         password_avp_name_buf[AVP_NAME_STR_BUF_LEN];
100         struct berval **attr_vals = NULL;
101         int_str username_avp_name, password_avp_name, avp_val;
102         unsigned short username_avp_type, password_avp_type;
103         int rc, ld_result_count;
104
105         /*
106          * get digest_username str
107          */
108         if(_digest_username) {
109                 if(pv_printf_s(_msg, _digest_username, &digest_username) != 0) {
110                         LM_ERR("pv_printf_s failed\n");
111                         return E_H350_INTERNAL;
112                 }
113         } else {
114                 LM_ERR("empty digest username\n");
115                 return E_H350_NO_SUCCESS;
116         }
117
118         /*
119          * get AVP names for username and password
120          */
121
122         if(pv_get_avp_name(_msg, &(_avp_specs->username_avp_spec.pvp),
123                            &username_avp_name, &username_avp_type)
124                         != 0) {
125                 LM_ERR("error getting AVP name - pv_get_avp_name failed\n");
126                 return E_H350_INTERNAL;
127         }
128         if(username_avp_type & AVP_NAME_STR) {
129                 if(username_avp_name.s.len >= AVP_NAME_STR_BUF_LEN) {
130                         LM_ERR("username AVP name too long\n");
131                         return E_H350_INTERNAL;
132                 }
133                 strncpy(username_avp_name_buf, username_avp_name.s.s,
134                                 username_avp_name.s.len);
135                 username_avp_name_buf[username_avp_name.s.len] = '\0';
136                 username_avp_name.s.s = username_avp_name_buf;
137         }
138
139         if(pv_get_avp_name(_msg, &(_avp_specs->password_avp_spec.pvp),
140                            &password_avp_name, &password_avp_type)
141                         != 0) {
142                 LM_ERR("error getting AVP name - pv_get_avp_name failed\n");
143                 return E_H350_INTERNAL;
144         }
145         if(password_avp_type & AVP_NAME_STR) {
146                 if(password_avp_name.s.len >= AVP_NAME_STR_BUF_LEN) {
147                         LM_ERR("password AVP name too long\n");
148                         return E_H350_INTERNAL;
149                 }
150                 strncpy(password_avp_name_buf, password_avp_name.s.s,
151                                 password_avp_name.s.len);
152                 password_avp_name_buf[password_avp_name.s.len] = '\0';
153                 password_avp_name.s.s = password_avp_name_buf;
154         }
155
156
157         /* 
158          * search for sip digest username in H.350, store digest password
159          */
160
161         /* ldap filter escape digest username */
162         digest_username_escaped.s = digest_username_buf;
163         digest_username_escaped.len = DIGEST_USERNAME_BUF_SIZE - 1;
164         if(ldap_api.ldap_rfc4515_escape(
165                            &digest_username, &digest_username_escaped, 0)) {
166                 LM_ERR("ldap_rfc4515_escape() failed\n");
167                 return E_H350_INTERNAL;
168         }
169
170         /* do ldap search */
171         if(ldap_api.ldap_params_search(&ld_result_count, h350_ldap_session,
172                            h350_base_dn, h350_search_scope_int, NULL,
173                            H350_AUTH_FILTER_PATTERN, digest_username_escaped.s)
174                         != 0) {
175                 LM_ERR("LDAP search failed\n");
176                 return E_H350_INTERNAL;
177         }
178
179         if(ld_result_count < 1) {
180                 LM_INFO("no H.350 entry found for username [%s]\n",
181                                 digest_username_escaped.s);
182                 return E_H350_NO_SUCCESS;
183         }
184         if(ld_result_count > 1) {
185                 LM_WARN("more than one [%d] H.350 entry found for username [%s]\n",
186                                 ld_result_count, digest_username_escaped.s);
187         }
188
189         /* get ldap result values */
190         rc = ldap_api.ldap_result_attr_vals(&h350_sip_pwd_name, &attr_vals);
191         if(rc < 0) {
192                 LM_ERR("getting LDAP attribute values failed\n");
193                 ldap_api.ldap_value_free_len(attr_vals);
194                 return E_H350_INTERNAL;
195         }
196         if((rc > 0) || (attr_vals == NULL)) {
197                 LM_INFO("no values found in LDAP entry for username [%s]\n",
198                                 digest_username_escaped.s);
199                 ldap_api.ldap_value_free_len(attr_vals);
200                 return E_H350_INTERNAL;
201         }
202
203         digest_password.s = attr_vals[0]->bv_val;
204         digest_password.len = attr_vals[0]->bv_len;
205
206         /*
207          * write AVPs
208          */
209
210         avp_val.s = digest_username;
211         if(add_avp(username_avp_type | AVP_VAL_STR, username_avp_name, avp_val)
212                         < 0) {
213                 LM_ERR("failed to create new AVP\n");
214                 ldap_api.ldap_value_free_len(attr_vals);
215                 return E_H350_INTERNAL;
216         }
217
218         avp_val.s = digest_password;
219         if(add_avp(password_avp_type | AVP_VAL_STR, password_avp_name, avp_val)
220                         < 0) {
221                 LM_ERR("failed to create new AVP\n");
222                 ldap_api.ldap_value_free_len(attr_vals);
223                 return E_H350_INTERNAL;
224         }
225
226         ldap_api.ldap_value_free_len(attr_vals);
227         return E_H350_SUCCESS;
228 }
229
230 int h350_call_preferences(struct sip_msg *_msg, pv_elem_t *_avp_name_prefix)
231 {
232         int rc, i, avp_count = 0;
233         struct berval **attr_vals;
234         size_t nmatch = 5;
235         regmatch_t pmatch[5];
236         int_str avp_name, avp_val;
237         str avp_val_str, avp_name_str, avp_name_prefix_str, call_pref_timeout_str;
238         int call_pref_timeout;
239         static char call_pref_avp_name[AVP_NAME_STR_BUF_LEN];
240
241         /*
242          * get avp_name_prefix_str
243          */
244         if(pv_printf_s(_msg, _avp_name_prefix, &avp_name_prefix_str) != 0) {
245                 LM_ERR("pv_printf_s failed\n");
246                 return E_H350_INTERNAL;
247         }
248
249
250         /*
251          * get LDAP attribute values
252          */
253         if((rc = ldap_api.ldap_result_attr_vals(&h350_call_pref_name, &attr_vals))
254                         < 0) {
255                 LM_ERR("Getting LDAP attribute values failed\n");
256                 return E_H350_INTERNAL;
257         }
258
259         if(rc > 0) {
260                 /* no LDAP values found */
261                 return E_H350_NO_SUCCESS;
262         }
263
264         /*
265          * loop through call pref values and add AVP(s)
266          */
267
268         /* copy avp name prefix into call_pref_avp_name */
269         if(avp_name_prefix_str.len < AVP_NAME_STR_BUF_LEN) {
270                 memcpy(call_pref_avp_name, avp_name_prefix_str.s,
271                                 avp_name_prefix_str.len);
272         } else {
273                 LM_ERR("AVP name prefix too long [%d] (max [%d])",
274                                 avp_name_prefix_str.len, AVP_NAME_STR_BUF_LEN);
275                 return E_H350_INTERNAL;
276         }
277
278         for(i = 0; attr_vals[i] != NULL; i++) {
279                 if((rc = regexec(
280                                         call_pref_preg, attr_vals[i]->bv_val, nmatch, pmatch, 0))
281                                 != 0) {
282                         switch(rc) {
283                                 case REG_NOMATCH:
284                                         LM_INFO("no h350 call preference regex match for [%s]\n",
285                                                         attr_vals[i]->bv_val);
286                                         continue;
287                                 case REG_ESPACE:
288                                         LM_ERR("regexec returned REG_ESPACE - out of memory\n");
289                                         ldap_api.ldap_value_free_len(attr_vals);
290                                         return E_H350_INTERNAL;
291                                 default:
292                                         LM_ERR("regexec failed\n");
293                                         ldap_api.ldap_value_free_len(attr_vals);
294                                         return E_H350_INTERNAL;
295                         }
296                 }
297
298                 /* calculate call preference sip uri */
299                 if(avp_name_prefix_str.len + pmatch[2].rm_eo - pmatch[2].rm_so
300                                 >= AVP_NAME_STR_BUF_LEN) {
301                         LM_ERR("AVP name too long for [%s]", attr_vals[i]->bv_val);
302                         continue;
303                 }
304                 avp_val_str.s = attr_vals[i]->bv_val + pmatch[1].rm_so;
305                 avp_val_str.len = pmatch[1].rm_eo - pmatch[1].rm_so;
306
307                 avp_val.s = avp_val_str;
308
309                 /* calculate call preference avp name */
310                 memcpy(call_pref_avp_name + avp_name_prefix_str.len,
311                                 attr_vals[i]->bv_val + pmatch[2].rm_so,
312                                 pmatch[2].rm_eo - pmatch[2].rm_so);
313
314                 avp_name_str.s = call_pref_avp_name;
315                 avp_name_str.len =
316                                 avp_name_prefix_str.len + pmatch[2].rm_eo - pmatch[2].rm_so;
317
318                 avp_name.s = avp_name_str;
319
320                 /* add avp */
321                 if(add_avp(AVP_NAME_STR | AVP_VAL_STR, avp_name, avp_val) < 0) {
322                         LM_ERR("failed to create new AVP\n");
323                         ldap_api.ldap_value_free_len(attr_vals);
324                         return E_H350_INTERNAL;
325                 }
326
327                 avp_count++;
328
329                 /* check for call preference timeout */
330                 if((pmatch[4].rm_eo - pmatch[4].rm_so) == 0) {
331                         continue;
332                 }
333
334                 /* calculate call preference timeout avp name */
335                 memcpy(avp_name_str.s + avp_name_str.len, "_t", 2);
336                 avp_name_str.len += 2;
337                 avp_name.s = avp_name_str;
338
339                 /* calculate timeout avp value */
340                 call_pref_timeout_str.s = attr_vals[i]->bv_val + pmatch[4].rm_so;
341                 call_pref_timeout_str.len = pmatch[4].rm_eo - pmatch[4].rm_so;
342                 if(str2sint(&call_pref_timeout_str, &call_pref_timeout) != 0) {
343                         LM_ERR("str2sint failed\n");
344                         ldap_api.ldap_value_free_len(attr_vals);
345                         return E_H350_INTERNAL;
346                 }
347                 call_pref_timeout = call_pref_timeout / 1000;
348
349                 /* add timeout avp */
350                 avp_val.n = call_pref_timeout;
351                 if(add_avp(AVP_NAME_STR, avp_name, avp_val) < 0) {
352                         LM_ERR("failed to create new AVP\n");
353                         ldap_api.ldap_value_free_len(attr_vals);
354                         return E_H350_INTERNAL;
355                 }
356         }
357
358         ldap_api.ldap_value_free_len(attr_vals);
359         if(avp_count > 0) {
360                 return avp_count;
361         } else {
362                 return E_H350_NO_SUCCESS;
363         }
364 }
365
366 int h350_service_level(struct sip_msg *_msg, pv_elem_t *_avp_name_prefix)
367 {
368         int i, rc, avp_count = 0;
369         str avp_name_prefix;
370         int_str avp_name, avp_val;
371         struct berval **attr_vals;
372         static char service_level_avp_name[AVP_NAME_STR_BUF_LEN];
373
374         /*
375          * get service_level
376          */
377         if(pv_printf_s(_msg, _avp_name_prefix, &avp_name_prefix) != 0) {
378                 LM_ERR("pv_printf_s failed\n");
379                 return E_H350_INTERNAL;
380         }
381
382         /*
383          * get LDAP attribute values
384          */
385         if((rc = ldap_api.ldap_result_attr_vals(
386                                 &h350_service_level_name, &attr_vals))
387                         < 0) {
388                 LM_ERR("Getting LDAP attribute values failed\n");
389                 return E_H350_INTERNAL;
390         }
391         if(rc > 0) {
392                 /* no LDAP values found */
393                 return E_H350_NO_SUCCESS;
394         }
395
396         /* copy avp name prefix into service_level_avp_name */
397         if(avp_name_prefix.len < AVP_NAME_STR_BUF_LEN) {
398                 memcpy(service_level_avp_name, avp_name_prefix.s, avp_name_prefix.len);
399         } else {
400                 LM_ERR("AVP name prefix too long [%d] (max [%d])\n",
401                                 avp_name_prefix.len, AVP_NAME_STR_BUF_LEN);
402                 ldap_api.ldap_value_free_len(attr_vals);
403                 return E_H350_INTERNAL;
404         }
405
406
407         /*
408          * loop through service level values and add AVP(s)
409          */
410
411         for(i = 0; attr_vals[i] != NULL; i++) {
412                 /* get avp name */
413                 if(avp_name_prefix.len + attr_vals[i]->bv_len >= AVP_NAME_STR_BUF_LEN) {
414                         LM_ERR("AVP name too long for [%s]\n", attr_vals[i]->bv_val);
415                         continue;
416                 }
417                 memcpy(service_level_avp_name + avp_name_prefix.len,
418                                 attr_vals[i]->bv_val, attr_vals[i]->bv_len);
419                 avp_name.s.s = service_level_avp_name;
420                 avp_name.s.len = avp_name_prefix.len + attr_vals[i]->bv_len;
421
422                 /* avp value = 1 */
423                 avp_val.n = 1;
424
425                 if(add_avp(AVP_NAME_STR, avp_name, avp_val) < 0) {
426                         LM_ERR("failed to create new AVP\n");
427                         ldap_api.ldap_value_free_len(attr_vals);
428                         return E_H350_INTERNAL;
429                 }
430                 avp_count++;
431         }
432
433         ldap_api.ldap_value_free_len(attr_vals);
434         if(avp_count > 0) {
435                 return avp_count;
436         } else {
437                 return E_H350_NO_SUCCESS;
438         }
439 }
440
441 int h350_exp_fn_init(void)
442 {
443         int rc;
444
445         if((call_pref_preg = pkg_malloc(sizeof(regex_t))) == 0) {
446                 LM_ERR("allocating memory for regex failed\n");
447                 return -1;
448         }
449
450         if((rc = regcomp(call_pref_preg, H350_CALL_PREF_REGEX, REG_EXTENDED))
451                         != 0) {
452                 pkg_free(call_pref_preg);
453                 LM_ERR("regcomp failed - returned [%d]\n", rc);
454                 return -1;
455         }
456         return 0;
457 }