1 /* ====================================================================
2 * The Kannel Software License, Version 1.0
3 *
4 * Copyright (c) 2001-2014 Kannel Group
5 * Copyright (c) 1998-2001 WapIT Ltd.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. The end-user documentation included with the redistribution,
21 * if any, must include the following acknowledgment:
22 * "This product includes software developed by the
23 * Kannel Group (http://www.kannel.org/)."
24 * Alternately, this acknowledgment may appear in the software itself,
25 * if and wherever such third-party acknowledgments normally appear.
26 *
27 * 4. The names "Kannel" and "Kannel Group" must not be used to
28 * endorse or promote products derived from this software without
29 * prior written permission. For written permission, please
30 * contact org@kannel.org.
31 *
32 * 5. Products derived from this software may not be called "Kannel",
33 * nor may "Kannel" appear in their name, without prior written
34 * permission of the Kannel Group.
35 *
36 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39 * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47 * ====================================================================
48 *
49 * This software consists of voluntary contributions made by many
50 * individuals on behalf of the Kannel Group. For more information on
51 * the Kannel Group, please see <http://www.kannel.org/>.
52 *
53 * Portions of this software are based upon software originally written at
54 * WapIT Ltd., Helsinki, Finland for the Kannel project.
55 */
56
57 /*
58 * wap_push_ppg_pushuser.c: Implementation of wap_push_ppg_pushuser.h header.
59 *
60 * By Aarno Syv�nen for Wiral Ltd and Global Networks Inc.
61 */
62
63 #include "wap_push_ppg_pushuser.h"
64 #include "numhash.h"
65 #include "gwlib/regex.h"
66
67 /***************************************************************************
68 *
69 * Global data structures
70 *
71 * Hold user specific data for one ppg user
72 */
73
74 struct WAPPushUser {
75 Octstr *name; /* the name of the user */
76 Octstr *username; /* the username of this ppg user */
77 Octstr *password; /* and password */
78 Octstr *country_prefix;
79 Octstr *allowed_prefix; /* phone number prefixes allowed by
80 this user when pushing*/
81 regex_t *allowed_prefix_regex;
82
83 Octstr *denied_prefix; /* and denied ones */
84 regex_t *denied_prefix_regex;
85
86 Numhash *white_list; /* phone numbers of this user, used for
87 push*/
88 regex_t *white_list_regex;
89 Numhash *black_list; /* numbers should not be used for push*/
90 regex_t *black_list_regex;
91
92 Octstr *user_deny_ip; /* this user allows pushes from these
93 IPs*/
94 Octstr *user_allow_ip; /* and denies them from these*/
95 Octstr *smsc_id; /* force push SMs to this smsc */
96 Octstr *default_smsc_id; /* use this smsc as a default for push SMs */
97 Octstr *dlr_url; /* default dlr url from this user */
98 Octstr *smsbox_id; /* use this smsbox for sending dlrs back*/
99 };
100
101 typedef struct WAPPushUser WAPPushUser;
102
103 /*
104 * Hold user specific data of all ppg users
105 */
106
107 struct WAPPushUserList {
108 List *list;
109 Dict *names;
110 };
111
112 typedef struct WAPPushUserList WAPPushUserList;
113
114 static WAPPushUserList *users = NULL;
115
116 /*
117 * This hash table stores time when a specific ip is allowed to try next time.
118 */
119 static Dict *next_try = NULL;
120
121 /***********************************************************************************
122 *
123 * Prototypes of internal functions
124 */
125
126 static void destroy_users_list(void *l);
127 static WAPPushUserList *pushusers_create(long number_of_users);
128 static WAPPushUser *create_oneuser(CfgGroup *grp);
129 static void destroy_oneuser(void *p);
130 static int oneuser_add(CfgGroup *cfg);
131 static void oneuser_dump(WAPPushUser *u);
132 static WAPPushUser *user_find_by_username(Octstr *username);
133 static int password_matches(WAPPushUser *u, Octstr *password);
134 static int ip_allowed_by_user(WAPPushUser *u, Octstr *ip);
135 static int prefix_allowed(WAPPushUser *u, Octstr *number);
136 static int whitelisted(WAPPushUser *u, Octstr *number);
137 static int blacklisted(WAPPushUser *u, Octstr *number);
138 static int wildcarded_ip_found(Octstr *ip, Octstr *needle, Octstr *ip_sep);
139 static int response(List *push_headers, Octstr **username, Octstr **password);
140 static void challenge(HTTPClient *c, List *push_headers);
141 static void reply(HTTPClient *c, List *push_headers);
142 static int parse_cgivars_for_username(List *cgivars, Octstr **username);
143 static int parse_cgivars_for_password(List *cgivars, Octstr **password);
144 static int compare_octstr_sequence(Octstr *os1, Octstr *os2, long start);
145 static Octstr *forced_smsc(WAPPushUser *u);
146 static Octstr *default_smsc(WAPPushUser *u);
147
148 /****************************************************************************
149 *
150 * Implementation of external functions
151 */
152
153 /*
154 * Initialize the whole module and fill the push users list.
155 */
wap_push_ppg_pushuser_list_add(List * list,long number_of_pushes,long number_of_users)156 int wap_push_ppg_pushuser_list_add(List *list, long number_of_pushes,
157 long number_of_users)
158 {
159 CfgGroup *grp;
160
161 next_try = dict_create(number_of_pushes, octstr_destroy_item);
162 users = pushusers_create(number_of_users);
163 gw_assert(list);
164 while (list && (grp = gwlist_extract_first(list))) {
165 if (oneuser_add(grp) == -1) {
166 gwlist_destroy(list, NULL);
167 return 0;
168 }
169 }
170 gwlist_destroy(list, NULL);
171
172 return 1;
173 }
174
wap_push_ppg_pushuser_list_destroy(void)175 void wap_push_ppg_pushuser_list_destroy(void)
176 {
177 dict_destroy(next_try);
178 if (users == NULL)
179 return;
180
181 gwlist_destroy(users->list, destroy_oneuser);
182 dict_destroy(users->names);
183 gw_free(users);
184 }
185
186 enum {
187 NO_USERNAME = -1,
188 NO_PASSWORD = 0,
189 HEADER_AUTHENTICATION = 1
190 };
191
192 #define ADDITION 0.1
193
194 /*
195 * This function does authentication possible before compiling the control
196 * document. This means:
197 * a) password authentication by url or by headers (it is, by basic
198 * authentication response, see rfc 2617, chapter 2)
199 * b) if this does not work, basic authentication by challenge -
200 * response
201 * c) enforcing various ip lists
202 *
203 * Check does ppg allows a connection from this at all, then try to find username
204 * and password from headers, then from url. If both fails, try basic authentica-
205 * tion. Then check does this user allow a push from this ip, then check the pass-
206 * word.
207 *
208 * For protection against brute force and partial protection for denial of serv-
209 * ice attacks, an exponential backup algorithm is used. Time when a specific ip
210 * is allowed to reconnect, is stored in Dict next_try. If an ip tries to recon-
211 * nect before this (three attemps are allowed, then exponential seconds are add-
212 * ed to the limit) we make a new challenge. We do the corresponding check before
213 * testing passwords; after all, it is an authorization failure that causes a new
214 * challenge.
215 *
216 * Rfc 2617, chapter 1 states that if we do not accept credentials of an user's,
217 * we must send a new challenge to the user.
218 *
219 * Output an authenticated username.
220 * This function should be called only when there are a push users list; the
221 * caller is responsible for this.
222 */
wap_push_ppg_pushuser_authenticate(HTTPClient * c,List * cgivars,Octstr * ip,List * push_headers,Octstr ** username)223 int wap_push_ppg_pushuser_authenticate(HTTPClient *c, List *cgivars, Octstr *ip,
224 List *push_headers, Octstr **username) {
225 time_t now;
226 static long next = 0L; /* used only in this thread (and this
227 function) */
228 long next_time;
229 Octstr *next_time_os;
230 static long multiplier = 1L; /* ditto */
231 WAPPushUser *u;
232 Octstr *copy,
233 *password;
234 int ret;
235
236 copy = octstr_duplicate(ip);
237 time(&now);
238 next_time_os = NULL;
239
240 if ((ret = response(push_headers, username, &password)) == NO_USERNAME) {
241 if (!parse_cgivars_for_username(cgivars, username)) {
242 error(0, "no user specified, challenging regardless");
243 goto listed;
244 }
245 }
246
247 if (password == NULL)
248 parse_cgivars_for_password(cgivars, &password);
249
250 u = user_find_by_username(*username);
251 if (!ip_allowed_by_user(u, ip)) {
252 goto not_listed;
253 }
254
255 next = 0;
256
257 if ((next_time_os = dict_get(next_try, ip)) != NULL) {
258 octstr_parse_long(&next_time, next_time_os, 0, 10);
259 if (difftime(now, (time_t) next_time) < 0) {
260 error(0, "another try from %s, not much time used",
261 octstr_get_cstr(copy));
262 goto listed;
263 }
264 }
265
266 if (u == NULL) {
267 error(0, "user %s is not allowed by users list, challenging",
268 octstr_get_cstr(*username));
269 goto listed;
270 }
271
272 if (!password_matches(u, password)) {
273 error(0, "wrong or missing password in request from %s, challenging" ,
274 octstr_get_cstr(copy));
275 goto listed;
276 }
277
278 dict_remove(next_try, ip); /* no restrictions after authentica-
279 tion */
280 octstr_destroy(password);
281 octstr_destroy(copy);
282 octstr_destroy(next_time_os);
283 return 1;
284
285 not_listed:
286 octstr_destroy(password);
287 octstr_destroy(copy);
288 reply(c, push_headers);
289 octstr_destroy(next_time_os);
290 return 0;
291
292 listed:
293 challenge(c, push_headers);
294
295 multiplier <<= 1;
296 next = next + multiplier * ADDITION;
297 next += now;
298 next_time_os = octstr_format("%ld", next);
299 dict_put(next_try, ip, next_time_os);
300
301 octstr_destroy(copy);
302 octstr_destroy(password);
303
304 return 0;
305 }
306
307 /*
308 * This function checks phone number for allowed prefixes, black lists and white
309 * lists. Note that the phone number necessarily follows the international format
310 * (a requirement by our pap compiler).
311 */
wap_push_ppg_pushuser_client_phone_number_acceptable(Octstr * username,Octstr * number)312 int wap_push_ppg_pushuser_client_phone_number_acceptable(Octstr *username,
313 Octstr *number)
314 {
315 WAPPushUser *u;
316
317 u = user_find_by_username(username);
318 if (!prefix_allowed(u, number)) {
319 error(0, "Number %s not allowed by user %s (wrong prefix)",
320 octstr_get_cstr(number), octstr_get_cstr(username));
321 return 0;
322 }
323
324 if (blacklisted(u, number)) {
325 error(0, "Number %s not allowed by user %s (blacklisted)",
326 octstr_get_cstr(number), octstr_get_cstr(username) );
327 return 0;
328 }
329
330 if (!whitelisted(u, number)) {
331 error(0, "Number %s not allowed by user %s (not whitelisted)",
332 octstr_get_cstr(number), octstr_get_cstr(username) );
333 return 0;
334 }
335
336 return 1;
337 }
338
wap_push_ppg_pushuser_search_ip_from_wildcarded_list(Octstr * haystack,Octstr * needle,Octstr * gwlist_sep,Octstr * ip_sep)339 int wap_push_ppg_pushuser_search_ip_from_wildcarded_list(Octstr *haystack,
340 Octstr *needle, Octstr *gwlist_sep, Octstr *ip_sep)
341 {
342 List *ips;
343 long i;
344 Octstr *configured_ip;
345
346 gw_assert(haystack);
347 gw_assert(gwlist_sep);
348 gw_assert(ip_sep);
349
350 /*There are no wildcards in the list*/
351 if (octstr_search_char(haystack, '*', 0) < 0) {
352 if (octstr_search(haystack, needle, 0) >= 0) {
353 return 1;
354 } else {
355 return 0;
356 }
357 }
358
359 /*There are wildcards in the list*/
360 configured_ip = NULL;
361 ips = octstr_split(haystack, gwlist_sep);
362 for (i = 0; i < gwlist_len(ips); ++i) {
363 configured_ip = gwlist_get(ips, i);
364 if (wildcarded_ip_found(configured_ip, needle, ip_sep))
365 goto found;
366 }
367
368 gwlist_destroy(ips, octstr_destroy_item);
369 return 0;
370
371 found:
372 gwlist_destroy(ips, octstr_destroy_item);
373 return 1;
374 }
375
376 /*
377 * Returns smsc-id that pushes by this user must use,
378 * NULL when there was an error.
379 */
wap_push_ppg_pushuser_smsc_id_get(Octstr * username)380 Octstr *wap_push_ppg_pushuser_smsc_id_get(Octstr *username)
381 {
382 WAPPushUser *u;
383 Octstr *smsc_id;
384
385 if ((u = user_find_by_username(username)) == NULL) {
386 /* no user found with this username */
387 return NULL;
388 }
389
390 if ((smsc_id = forced_smsc(u)) != NULL)
391 return octstr_duplicate(smsc_id);
392
393 smsc_id = default_smsc(u);
394 return octstr_duplicate(smsc_id);
395 }
396
397 /*
398 * Returns default dlr url for this user.
399 */
wap_push_ppg_pushuser_dlr_url_get(Octstr * username)400 Octstr *wap_push_ppg_pushuser_dlr_url_get(Octstr *username)
401 {
402 WAPPushUser *u;
403 Octstr *dlr_url;
404
405 u = user_find_by_username(username);
406 dlr_url = u->dlr_url;
407
408 return octstr_duplicate(dlr_url);
409 }
410
411 /*
412 * Returns default dlr smsbox id for this user.
413 */
wap_push_ppg_pushuser_smsbox_id_get(Octstr * username)414 Octstr *wap_push_ppg_pushuser_smsbox_id_get(Octstr *username)
415 {
416 WAPPushUser *u;
417 Octstr *smsbox_id;
418
419 u = user_find_by_username(username);
420 smsbox_id = u->smsbox_id;
421
422 return octstr_duplicate(smsbox_id);
423 }
424
425
426 /***************************************************************************
427 *
428 * Implementation of internal functions
429 */
430
destroy_users_list(void * l)431 static void destroy_users_list(void *l)
432 {
433 gwlist_destroy(l, NULL);
434 }
435
pushusers_create(long number_of_users)436 static WAPPushUserList *pushusers_create(long number_of_users)
437 {
438 users = gw_malloc(sizeof(WAPPushUserList));
439 users->list = gwlist_create();
440 users->names = dict_create(number_of_users, destroy_users_list);
441
442 return users;
443 }
444
445 /*
446 * Allocate memory for one push user and read configuration data to it. We initial-
447 * ize all fields to NULL, because the value NULL means that the configuration did
448 * not have this variable.
449 * Return NULL when failure, a pointer to the data structure otherwise.
450 */
create_oneuser(CfgGroup * grp)451 static WAPPushUser *create_oneuser(CfgGroup *grp)
452 {
453 WAPPushUser *u;
454 Octstr *grpname,
455 *os;
456
457 grpname = cfg_get(grp, octstr_imm("wap-push-user"));
458 if (grpname == NULL) {
459 error(0, "all users group (wap-push-user) are missing");
460 goto no_grpname;
461 }
462
463 u = gw_malloc(sizeof(WAPPushUser));
464 u->name = NULL;
465 u->username = NULL;
466 u->allowed_prefix = NULL;
467 u->allowed_prefix_regex = NULL;
468 u->denied_prefix = NULL;
469 u->denied_prefix_regex = NULL;
470 u->white_list = NULL;
471 u->white_list_regex = NULL;
472 u->black_list = NULL;
473 u->black_list_regex = NULL;
474 u->user_deny_ip = NULL;
475 u->user_allow_ip = NULL;
476 u->smsc_id = NULL;
477 u->default_smsc_id = NULL;
478
479 u->name = cfg_get(grp, octstr_imm("wap-push-user"));
480
481 if (u->name == NULL) {
482 warning(0, "user name missing, dump follows");
483 oneuser_dump(u);
484 goto error;
485 }
486
487 u->username = cfg_get(grp, octstr_imm("ppg-username"));
488 u->password = cfg_get(grp, octstr_imm("ppg-password"));
489
490 if (u->username == NULL) {
491 warning(0, "login name for user %s missing, dump follows",
492 octstr_get_cstr(u->name));
493 oneuser_dump(u);
494 goto error;
495 }
496
497 if (u->password == NULL) {
498 warning(0, "password for user %s missing, dump follows",
499 octstr_get_cstr(u->name));
500 oneuser_dump(u);
501 goto error;
502 }
503
504 u->user_deny_ip = cfg_get(grp, octstr_imm("deny-ip"));
505 u->user_allow_ip = cfg_get(grp, octstr_imm("allow-ip"));
506 u->country_prefix = cfg_get(grp, octstr_imm("country-prefix"));
507 u->allowed_prefix = cfg_get(grp, octstr_imm("allowed-prefix"));
508 u->denied_prefix = cfg_get(grp, octstr_imm("denied-prefix"));
509 u->smsc_id = cfg_get(grp, octstr_imm("forced-smsc"));
510 u->default_smsc_id = cfg_get(grp, octstr_imm("default-smsc"));
511 u->dlr_url = cfg_get(grp, octstr_imm("dlr-url"));
512 u->smsbox_id = cfg_get(grp, octstr_imm("smsbox-id"));
513
514 os = cfg_get(grp, octstr_imm("white-list"));
515 if (os != NULL) {
516 u->white_list = numhash_create(octstr_get_cstr(os));
517 octstr_destroy(os);
518 }
519 os = cfg_get(grp, octstr_imm("black-list"));
520 if (os != NULL) {
521 u->black_list = numhash_create(octstr_get_cstr(os));
522 octstr_destroy(os);
523 }
524
525 if ((os = cfg_get(grp, octstr_imm("allowed-prefix-regex"))) != NULL) {
526 if ((u->allowed_prefix_regex = gw_regex_comp(os, REG_EXTENDED)) == NULL)
527 panic(0, "Could not compile pattern '%s'", octstr_get_cstr(os));
528 octstr_destroy(os);
529 };
530 if ((os = cfg_get(grp, octstr_imm("denied-prefix-regex"))) != NULL) {
531 if ((u->denied_prefix_regex = gw_regex_comp(os, REG_EXTENDED)) == NULL)
532 panic(0, "Could not compile pattern '%s'", octstr_get_cstr(os));
533 octstr_destroy(os);
534 };
535 if ((os = cfg_get(grp, octstr_imm("white-list-regex"))) != NULL) {
536 if ((u->white_list_regex = gw_regex_comp(os, REG_EXTENDED)) == NULL)
537 panic(0, "Could not compile pattern '%s'", octstr_get_cstr(os));
538 octstr_destroy(os);
539 };
540 if ((os = cfg_get(grp, octstr_imm("black-list-regex"))) != NULL) {
541 if ((u->black_list_regex = gw_regex_comp(os, REG_EXTENDED)) == NULL)
542 panic(0, "Could not compile pattern '%s'", octstr_get_cstr(os));
543 octstr_destroy(os);
544 };
545
546 octstr_destroy(grpname);
547 return u;
548
549 no_grpname:
550 octstr_destroy(grpname);
551 return NULL;
552
553 error:
554 octstr_destroy(grpname);
555 destroy_oneuser(u);
556 return NULL;
557 }
558
destroy_oneuser(void * p)559 static void destroy_oneuser(void *p)
560 {
561 WAPPushUser *u;
562
563 u = p;
564 if (u == NULL)
565 return;
566
567 octstr_destroy(u->name);
568 octstr_destroy(u->username);
569 octstr_destroy(u->password);
570 octstr_destroy(u->country_prefix);
571 octstr_destroy(u->allowed_prefix);
572 octstr_destroy(u->denied_prefix);
573 numhash_destroy(u->white_list);
574 numhash_destroy(u->black_list);
575 octstr_destroy(u->user_deny_ip);
576 octstr_destroy(u->user_allow_ip);
577 octstr_destroy(u->smsc_id);
578 octstr_destroy(u->default_smsc_id);
579
580 if (u->black_list_regex != NULL) gw_regex_destroy(u->black_list_regex);
581 if (u->white_list_regex != NULL) gw_regex_destroy(u->white_list_regex);
582 if (u->denied_prefix_regex != NULL) gw_regex_destroy(u->denied_prefix_regex);
583 if (u->allowed_prefix_regex != NULL) gw_regex_destroy(u->allowed_prefix_regex);
584 gw_free(u);
585 }
586
oneuser_dump(WAPPushUser * u)587 static void oneuser_dump(WAPPushUser *u)
588 {
589 if (u == NULL) {
590 debug("wap.push.ppg.pushuser", 0, "no user found");
591 return;
592 }
593
594 debug("wap.push.ppg.pushuser", 0, "Dumping user data: Name of the user:");
595 octstr_dump(u->name, 0);
596 debug("wap.push.ppg.pushuser", 0, "username:");
597 octstr_dump(u->username, 0);
598 debug("wap.push.ppg.pushuser", 0, "omitting password");
599 debug("wap-push.ppg.pushuser", 0, "country prefix");
600 octstr_dump(u->country_prefix, 0);
601 debug("wap.push.ppg.pushuser", 0, "allowed prefix list:");
602 octstr_dump(u->allowed_prefix, 0);
603 debug("wap.push.ppg.pushuser", 0, "denied prefix list:");
604 octstr_dump(u->denied_prefix, 0);
605 debug("wap.push.ppg.pushuser", 0, "denied ip list:");
606 octstr_dump(u->user_deny_ip, 0);
607 debug("wap.push.ppg.pushuser", 0, "allowed ip list:");
608 octstr_dump(u->user_allow_ip, 0);
609 debug("wap.push.ppg.pushuser", 0, "send via smsc-id:");
610 octstr_dump(u->smsc_id, 0);
611 debug("wap.push.ppg.pushuser", 0, "use default smsc:");
612 octstr_dump(u->default_smsc_id, 0);
613 debug("wap.push.ppg.pushuser", 0, "end of the dump");
614 }
615
616 /*
617 * Add an user to the push users list
618 */
oneuser_add(CfgGroup * grp)619 static int oneuser_add(CfgGroup *grp)
620 {
621 WAPPushUser *u;
622 List *list;
623
624 u = create_oneuser(grp);
625 if (u == NULL)
626 return -1;
627
628 gwlist_append(users->list, u);
629
630 list = dict_get(users->names, u->username);
631 if (list == NULL) {
632 list = gwlist_create();
633 dict_put(users->names, u->username, list);
634 }
635
636 return 0;
637 }
638
user_find_by_username(Octstr * username)639 static WAPPushUser *user_find_by_username(Octstr *username)
640 {
641 WAPPushUser *u;
642 long i;
643 List *list;
644
645 if (username == NULL)
646 return NULL;
647
648 if ((list = dict_get(users->names, username)) == NULL)
649 return NULL;
650
651 for (i = 0; i < gwlist_len(users->list); ++i) {
652 u = gwlist_get(users->list, i);
653 if (octstr_compare(u->username, username) == 0)
654 return u;
655 }
656
657 return NULL;
658 }
659
password_matches(WAPPushUser * u,Octstr * password)660 static int password_matches(WAPPushUser *u, Octstr *password)
661 {
662 if (password == NULL)
663 return 0;
664
665 return octstr_compare(u->password, password) == 0;
666 }
667
wildcarded_ip_found(Octstr * ip,Octstr * needle,Octstr * ip_sep)668 static int wildcarded_ip_found(Octstr *ip, Octstr *needle, Octstr *ip_sep)
669 {
670 List *ip_fragments,
671 *needle_fragments;
672 long i;
673 Octstr *ip_fragment,
674 *needle_fragment;
675
676 ip_fragments = octstr_split(ip, ip_sep);
677 needle_fragments = octstr_split(needle, ip_sep);
678
679 gw_assert(gwlist_len(ip_fragments) == gwlist_len(needle_fragments));
680 for (i = 0; i < gwlist_len(ip_fragments); ++i) {
681 ip_fragment = gwlist_get(ip_fragments, i);
682 needle_fragment = gwlist_get(needle_fragments, i);
683 if (octstr_compare(ip_fragment, needle_fragment) != 0 &&
684 octstr_compare(ip_fragment, octstr_imm("*")) != 0)
685 goto not_found;
686 }
687
688 gwlist_destroy(ip_fragments, octstr_destroy_item);
689 gwlist_destroy(needle_fragments, octstr_destroy_item);
690 return 1;
691
692 not_found:
693 gwlist_destroy(ip_fragments, octstr_destroy_item);
694 gwlist_destroy(needle_fragments, octstr_destroy_item);
695 return 0;
696 }
697
698 /*
699 * Deny_ip = '*.*.*.*' is here taken literally: no ips allowed by this user
700 * (definitely strange, but not a fatal error).
701 */
ip_allowed_by_user(WAPPushUser * u,Octstr * ip)702 static int ip_allowed_by_user(WAPPushUser *u, Octstr *ip)
703 {
704 Octstr *copy,
705 *ip_copy;
706
707 if (u == NULL) {
708 warning(0, "user not found from the users list");
709 goto no_user;
710 }
711
712 copy = octstr_duplicate(u->username);
713
714 if (u->user_deny_ip == NULL && u->user_allow_ip == NULL)
715 goto allowed;
716
717 if (u->user_deny_ip) {
718 if (octstr_compare(u->user_deny_ip, octstr_imm("*.*.*.*")) == 0) {
719 warning(0, "no ips allowed for %s", octstr_get_cstr(copy));
720 goto denied;
721 }
722 }
723
724 if (u->user_allow_ip)
725 if (octstr_compare(u->user_allow_ip, octstr_imm("*.*.*.*")) == 0)
726 goto allowed;
727
728 if (u->user_deny_ip) {
729 if (wap_push_ppg_pushuser_search_ip_from_wildcarded_list(u->user_deny_ip,
730 ip, octstr_imm(";"), octstr_imm("."))) {
731 goto denied;
732 }
733 }
734
735 if (u->user_allow_ip) {
736 if (wap_push_ppg_pushuser_search_ip_from_wildcarded_list(u->user_allow_ip,
737 ip, octstr_imm(";"), octstr_imm("."))) {
738 goto allowed;
739 }
740 }
741
742 octstr_destroy(copy);
743 warning(0, "ip not found from either ip list, deny it");
744 return 0;
745
746 allowed:
747 octstr_destroy(copy);
748 return 1;
749
750 denied:
751 ip_copy = octstr_duplicate(ip);
752 warning(0, "%s denied by user %s", octstr_get_cstr(ip_copy),
753 octstr_get_cstr(copy));
754 octstr_destroy(copy);
755 octstr_destroy(ip_copy);
756 return 0;
757
758 no_user:
759 return 0;
760 }
761
762 /*
763 * HTTP basic authentication server response is defined in rfc 2617, chapter 2.
764 * Return 1, when we found username and password from headers, 0, when there were
765 * no password and -1 when there were no username (or no Authorization header at
766 * all, or an unparsable one). Username and password value 'NULL' means no user-
767 * name or password supplied.
768 */
response(List * push_headers,Octstr ** username,Octstr ** password)769 static int response(List *push_headers, Octstr **username, Octstr **password)
770 {
771 Octstr *header_value,
772 *basic;
773 size_t basic_len;
774 List *auth_list;
775
776 *username = NULL;
777 *password = NULL;
778
779 if ((header_value = http_header_find_first(push_headers,
780 "Authorization")) == NULL)
781 goto no_response3;
782
783 octstr_strip_blanks(header_value);
784 basic = octstr_imm("Basic");
785 basic_len = octstr_len(basic);
786
787 if (octstr_ncompare(header_value, basic, basic_len) != 0)
788 goto no_response1;
789
790 octstr_delete(header_value, 0, basic_len);
791 octstr_strip_blanks(header_value);
792 octstr_base64_to_binary(header_value);
793 auth_list = octstr_split(header_value, octstr_imm(":"));
794
795 if (gwlist_len(auth_list) != 2)
796 goto no_response2;
797
798 *username = octstr_duplicate(gwlist_get(auth_list, 0));
799 *password = octstr_duplicate(gwlist_get(auth_list, 1));
800
801 if (username == NULL) {
802 goto no_response2;
803 }
804
805 if (password == NULL) {
806 goto no_response4;
807 }
808
809 debug("wap.push.ppg.pushuser", 0, "we have an username and a password in"
810 " authorization header");
811 gwlist_destroy(auth_list, octstr_destroy_item);
812 octstr_destroy(header_value);
813 http_header_remove_all(push_headers, "Authorization");
814 return HEADER_AUTHENTICATION;
815
816 no_response1:
817 octstr_destroy(header_value);
818 return NO_USERNAME;
819
820 no_response2:
821 gwlist_destroy(auth_list, octstr_destroy_item);
822 octstr_destroy(header_value);
823 return NO_USERNAME;
824
825 no_response3:
826 return NO_USERNAME;
827
828 no_response4:
829 gwlist_destroy(auth_list, octstr_destroy_item);
830 octstr_destroy(header_value);
831 return NO_PASSWORD;
832 }
833
834 /*
835 * HTTP basic authentication server challenge is defined in rfc 2617, chapter 2.
836 * Only WWW-Authenticate header is required here by specs. This function does not
837 * release memory used by push headers, the caller must do this.
838 */
challenge(HTTPClient * c,List * push_headers)839 static void challenge(HTTPClient *c, List *push_headers)
840 {
841 Octstr *challenge,
842 *realm;
843 int http_status;
844 List *reply_headers;
845
846 realm = octstr_format("%s", "Basic realm=");
847 octstr_append(realm, get_official_name());
848 octstr_format_append(realm, "%s", "\"wappush\"");
849 reply_headers = http_create_empty_headers();
850 http_header_add(reply_headers, "WWW-Authenticate", octstr_get_cstr(realm));
851 http_status = HTTP_UNAUTHORIZED;
852 challenge = octstr_imm("You must show your credentials.\n");
853
854 http_send_reply(c, http_status, reply_headers, challenge);
855
856 octstr_destroy(realm);
857 http_destroy_headers(reply_headers);
858 }
859
860 /*
861 * This function does not release memory used by push headers, the caller must do this.
862 */
reply(HTTPClient * c,List * push_headers)863 static void reply(HTTPClient *c, List *push_headers)
864 {
865 int http_status;
866 Octstr *denied;
867 List *reply_headers;
868
869 reply_headers = http_create_empty_headers();
870 http_status = HTTP_FORBIDDEN;
871 denied = octstr_imm("You are not allowed to use this service. Do not retry.\n");
872
873 http_send_reply(c, http_status, push_headers, denied);
874
875 http_destroy_headers(reply_headers);
876 }
877
878 /*
879 * Note that the phone number necessarily follows the international format (a requi-
880 * rement by our pap compiler). So we add country prefix to listed prefixes, if one
881 * is configured.
882 */
prefix_allowed(WAPPushUser * u,Octstr * number)883 static int prefix_allowed(WAPPushUser *u, Octstr *number)
884 {
885 List *allowed,
886 *denied;
887 long i;
888 Octstr *listed_prefix;
889
890 allowed = NULL;
891 denied = NULL;
892
893 if (u == NULL)
894 goto no_user;
895
896 if ( u->allowed_prefix == NULL && u->denied_prefix == NULL
897 && u->allowed_prefix_regex == NULL && u->denied_prefix_regex == NULL)
898 goto no_configuration;
899
900 if (u->denied_prefix != NULL) {
901 denied = octstr_split(u->denied_prefix, octstr_imm(";"));
902 for (i = 0; i < gwlist_len(denied); ++i) {
903 listed_prefix = gwlist_get(denied, i);
904 if (u->country_prefix != NULL)
905 octstr_insert(listed_prefix, u->country_prefix, 0);
906 if (compare_octstr_sequence(number, listed_prefix,
907 0) == 0) {
908 goto denied;
909 }
910 }
911 }
912
913 /* note: country-prefix _must_be included in the pattern */
914 if (u->denied_prefix_regex != NULL)
915 if (gw_regex_match_pre(u->denied_prefix_regex, number) == 1)
916 goto denied;
917
918 if (u->allowed_prefix_regex == NULL && u->allowed_prefix == NULL)
919 goto no_allowed_config;
920
921 if (u->allowed_prefix != NULL) {
922 allowed = octstr_split(u->allowed_prefix, octstr_imm(";"));
923 for (i = 0; i < gwlist_len(allowed); ++i) {
924 listed_prefix = gwlist_get(allowed, i);
925 if (u->country_prefix != NULL)
926 octstr_insert(listed_prefix, u->country_prefix, 0);
927 if (compare_octstr_sequence(number, listed_prefix,
928 0) == 0) {
929 goto allowed;
930 }
931 }
932 }
933
934 /* note: country-prefix _must_ be included in the pattern */
935 if (u->allowed_prefix_regex != NULL)
936 if (gw_regex_match_pre(u->allowed_prefix_regex, number) == 1)
937 goto allowed;
938
939 /*
940 * Here we have an intentional fall-through. It will removed when memory cleaning
941 * functions are implemented.
942 */
943 denied:
944 gwlist_destroy(allowed, octstr_destroy_item);
945 gwlist_destroy(denied, octstr_destroy_item);
946 return 0;
947
948 allowed:
949 gwlist_destroy(allowed, octstr_destroy_item);
950 gwlist_destroy(denied, octstr_destroy_item);
951 return 1;
952
953 no_configuration:
954 return 1;
955
956 no_user:
957 return 0;
958
959 no_allowed_config:
960 gwlist_destroy(denied, octstr_destroy_item);
961 return 1;
962 }
963
whitelisted(WAPPushUser * u,Octstr * number)964 static int whitelisted(WAPPushUser *u, Octstr *number)
965 {
966 int result = 1;
967
968 if (u->white_list != NULL)
969 result = numhash_find_number(u->white_list, number);
970
971 if ((result == 0) && (u->white_list_regex != NULL))
972 result = gw_regex_match_pre(u->white_list_regex, number);
973
974 return result;
975 }
976
blacklisted(WAPPushUser * u,Octstr * number)977 static int blacklisted(WAPPushUser *u, Octstr *number)
978 {
979 int result = 0;
980
981 if (u->black_list != NULL)
982 result = numhash_find_number(u->black_list, number);
983
984 if ((result == 0) && (u->black_list_regex != NULL))
985 result = gw_regex_match_pre(u->black_list_regex, number);
986
987 return result;
988 }
989
990 /*
991 * 'NULL' means here 'no value found'.
992 * Return 1 when we found username, 0 when we did not.
993 */
parse_cgivars_for_username(List * cgivars,Octstr ** username)994 static int parse_cgivars_for_username(List *cgivars, Octstr **username)
995 {
996 *username = NULL;
997 *username = octstr_duplicate(http_cgi_variable(cgivars, "username"));
998
999 if (*username == NULL) {
1000 return 0;
1001 }
1002
1003 return 1;
1004 }
1005
parse_cgivars_for_password(List * cgivars,Octstr ** password)1006 static int parse_cgivars_for_password(List *cgivars, Octstr **password)
1007 {
1008 *password = NULL;
1009 *password = octstr_duplicate(http_cgi_variable(cgivars, "password"));
1010
1011 if (*password == NULL) {
1012 return 0;
1013 }
1014
1015 return 1;
1016 }
1017
1018 /*
1019 * Compare an octet string os2 with a sequence of an octet string os1. The sequence
1020 * starts with a position start.
1021 */
compare_octstr_sequence(Octstr * os1,Octstr * os2,long start)1022 static int compare_octstr_sequence(Octstr *os1, Octstr *os2, long start)
1023 {
1024 int ret;
1025 unsigned char *prefix;
1026 long end;
1027
1028 if (octstr_len(os2) == 0)
1029 return 1;
1030
1031 if (octstr_len(os1) == 0)
1032 return -1;
1033
1034 prefix = NULL;
1035 if (start != 0) {
1036 prefix = gw_malloc(start);
1037 octstr_get_many_chars((char *)prefix, os1, 0, start);
1038 octstr_delete(os1, 0, start);
1039 }
1040
1041 end = start + octstr_len(os2);
1042 ret = octstr_ncompare(os1, os2, end - start);
1043
1044 if (start != 0) {
1045 octstr_insert_data(os1, 0, (char *)prefix, start);
1046 gw_free(prefix);
1047 }
1048
1049 return ret;
1050 }
1051
forced_smsc(WAPPushUser * u)1052 static Octstr *forced_smsc(WAPPushUser *u)
1053 {
1054 return u->smsc_id;
1055 }
1056
default_smsc(WAPPushUser * u)1057 static Octstr *default_smsc(WAPPushUser *u)
1058 {
1059 return u->default_smsc_id;
1060 }
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073