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