Kannel: Open Source WAP and SMS gateway  $Revision: 5037 $
wap_push_ppg_pushuser.c
Go to the documentation of this file.
1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2016 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 */
79  Octstr *allowed_prefix; /* phone number prefixes allowed by
80  this user when pushing*/
82 
83  Octstr *denied_prefix; /* and denied ones */
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 
110 };
111 
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);
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);
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  */
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 
176 {
177  dict_destroy(next_try);
178  if (users == NULL)
179  return;
180 
182  dict_destroy(users->names);
183  gw_free(users);
184 }
185 
186 enum {
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  */
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  */
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 
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 
369  return 0;
370 
371 found:
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  */
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  */
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  */
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 
431 static void destroy_users_list(void *l)
432 {
433  gwlist_destroy(l, NULL);
434 }
435 
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  */
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) {
517  octstr_destroy(os);
518  }
519  os = cfg_get(grp, octstr_imm("black-list"));
520  if (os != NULL) {
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 
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);
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 
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:");
613  debug("wap.push.ppg.pushuser", 0, "end of the dump");
614 }
615 
616 /*
617  * Add an user to the push users list
618  */
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 
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 
661 {
662  if (password == NULL)
663  return 0;
664 
665  return octstr_compare(u->password, password) == 0;
666 }
667 
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  */
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) {
730  ip, octstr_imm(";"), octstr_imm("."))) {
731  goto denied;
732  }
733  }
734 
735  if (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  */
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");
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:
822  octstr_destroy(header_value);
823  return NO_USERNAME;
824 
825 no_response3:
826  return NO_USERNAME;
827 
828 no_response4:
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  */
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=");
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  */
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  */
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:
946  return 0;
947 
948 allowed:
951  return 1;
952 
953 no_configuration:
954  return 1;
955 
956 no_user:
957  return 0;
958 
959 no_allowed_config:
961  return 1;
962 }
963 
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 
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  */
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 
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  */
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 
1053 {
1054  return u->smsc_id;
1055 }
1056 
1058 {
1059  return u->default_smsc_id;
1060 }
1061 
1062 
1063 
1064 
1065 
1066 
1067 
1068 
1069 
1070 
1071 
1072 
Dict * dict_create(long size_hint, void(*destroy_value)(void *))
Definition: dict.c:192
regex_t * allowed_prefix_regex
void error(int err, const char *fmt,...)
Definition: log.c:612
int number
Definition: smsc_cimd2.c:213
Octstr * wap_push_ppg_pushuser_dlr_url_get(Octstr *username)
static Dict * next_try
void http_header_add(List *headers, char *name, char *contents)
Definition: http.c:2863
static int whitelisted(WAPPushUser *u, Octstr *number)
regex_t * black_list_regex
void dict_put(Dict *dict, Octstr *key, void *value)
Definition: dict.c:240
void gwlist_append(List *list, void *item)
Definition: list.c:179
Octstr * wap_push_ppg_pushuser_smsc_id_get(Octstr *username)
void octstr_append(Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:1502
Octstr * wap_push_ppg_pushuser_smsbox_id_get(Octstr *username)
static void oneuser_dump(WAPPushUser *u)
long gwlist_len(List *list)
Definition: list.c:166
void * gwlist_get(List *list, long pos)
Definition: list.c:292
static int password_matches(WAPPushUser *u, Octstr *password)
Octstr * default_smsc_id
long octstr_search(const Octstr *haystack, const Octstr *needle, long pos)
Definition: octstr.c:1068
static void destroy_users_list(void *l)
#define cfg_get(grp, varname)
Definition: cfg.h:86
regex_t * white_list_regex
static Octstr * default_smsc(WAPPushUser *u)
static int parse_cgivars_for_password(List *cgivars, Octstr **password)
int wap_push_ppg_pushuser_list_add(List *list, long number_of_pushes, long number_of_users)
void numhash_destroy(Numhash *table)
Definition: numhash.c:275
void octstr_insert_data(Octstr *ostr, long pos, const char *data, long len)
Definition: octstr.c:1459
void octstr_strip_blanks(Octstr *text)
Definition: octstr.c:1344
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
long octstr_search_char(const Octstr *ostr, int ch, long pos)
Definition: octstr.c:1010
static Octstr * smsbox_id
Definition: smsbox.c:120
static struct pid_list * found
static int blacklisted(WAPPushUser *u, Octstr *number)
Numhash * numhash_create(const char *seek_url)
Definition: numhash.c:313
unsigned char * username
Definition: test_cimd2.c:99
Octstr * http_cgi_variable(List *list, char *name)
Definition: http.c:2813
static int compare_octstr_sequence(Octstr *os1, Octstr *os2, long start)
void http_destroy_headers(List *headers)
Definition: http.c:2856
static int oneuser_add(CfgGroup *cfg)
static long number_of_users
Definition: wap_push_ppg.c:193
unsigned char * password
Definition: test_cimd2.c:100
void http_send_reply(HTTPClient *client, int status, List *headers, Octstr *body)
Definition: http.c:2671
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:281
void octstr_insert(Octstr *ostr1, const Octstr *ostr2, long pos)
Definition: octstr.c:1301
void * dict_remove(Dict *dict, Octstr *key)
Definition: dict.c:307
int numhash_find_number(Numhash *table, Octstr *nro)
Definition: numhash.c:218
void * gwlist_extract_first(List *list)
Definition: list.c:305
static Octstr * dlr_url
Definition: test_ppg.c:107
void * dict_get(Dict *dict, Octstr *key)
Definition: dict.c:286
void octstr_delete(Octstr *ostr1, long pos, long len)
Definition: octstr.c:1525
static int wildcarded_ip_found(Octstr *ip, Octstr *needle, Octstr *ip_sep)
static WAPPushUserList * pushusers_create(long number_of_users)
List * http_create_empty_headers(void)
Definition: http.c:2849
int wap_push_ppg_pushuser_search_ip_from_wildcarded_list(Octstr *haystack, Octstr *needle, Octstr *gwlist_sep, Octstr *ip_sep)
int octstr_ncompare(const Octstr *ostr1, const Octstr *ostr2, long n)
Definition: octstr.c:950
static void destroy_oneuser(void *p)
Definition: dict.c:116
#define octstr_duplicate(ostr)
Definition: octstr.h:187
#define octstr_dump(ostr, level,...)
Definition: octstr.h:564
static Octstr * smsc_id
Definition: mtbatch.c:98
int wap_push_ppg_pushuser_client_phone_number_acceptable(Octstr *username, Octstr *number)
#define http_header_find_first(headers, name)
Definition: http.h:592
static int ip_allowed_by_user(WAPPushUser *u, Octstr *ip)
void warning(int err, const char *fmt,...)
Definition: log.c:624
static WAPPushUserList * users
#define ADDITION
void wap_push_ppg_pushuser_list_destroy(void)
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2462
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
void octstr_destroy_item(void *os)
Definition: octstr.c:334
gw_assert(wtls_machine->packet_to_send!=NULL)
Octstr * get_official_name(void)
Definition: socket.c:627
int wap_push_ppg_pushuser_authenticate(HTTPClient *c, List *cgivars, Octstr *ip, List *push_headers, Octstr **username)
void octstr_base64_to_binary(Octstr *ostr)
Definition: octstr.c:661
static Cfg * cfg
Definition: smsbox.c:115
static long number_of_pushes
Definition: wap_push_ppg.c:191
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
static WAPPushUser * create_oneuser(CfgGroup *grp)
void dict_destroy(Dict *dict)
Definition: dict.c:215
regex_t * denied_prefix_regex
Definition: octstr.c:118
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
#define panic
Definition: log.h:87
Definition: cfg.c:73
long http_header_remove_all(List *headers, char *name)
Definition: http.c:3112
static int prefix_allowed(WAPPushUser *u, Octstr *number)
long octstr_parse_long(long *nump, Octstr *ostr, long pos, int base)
Definition: octstr.c:747
void octstr_format_append(Octstr *os, const char *fmt,...)
Definition: octstr.c:2505
#define gwlist_create()
Definition: list.h:136
static int parse_cgivars_for_username(List *cgivars, Octstr **username)
static int response(List *push_headers, Octstr **username, Octstr **password)
static void challenge(HTTPClient *c, List *push_headers)
void octstr_get_many_chars(char *buf, Octstr *ostr, long pos, long len)
Definition: octstr.c:423
static Octstr * forced_smsc(WAPPushUser *u)
List * octstr_split(const Octstr *os, const Octstr *sep)
Definition: octstr.c:1638
Definition: list.c:102
static int start
static void reply(HTTPClient *c, List *push_headers)
static WAPPushUser * user_find_by_username(Octstr *username)
int octstr_compare(const Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:869
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.