Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

wap_push_ppg_pushuser.c

Go to the documentation of this file.
00001 /* ==================================================================== 
00002  * The Kannel Software License, Version 1.0 
00003  * 
00004  * Copyright (c) 2001-2008 Kannel Group  
00005  * Copyright (c) 1998-2001 WapIT Ltd.   
00006  * All rights reserved. 
00007  * 
00008  * Redistribution and use in source and binary forms, with or without 
00009  * modification, are permitted provided that the following conditions 
00010  * are met: 
00011  * 
00012  * 1. Redistributions of source code must retain the above copyright 
00013  *    notice, this list of conditions and the following disclaimer. 
00014  * 
00015  * 2. Redistributions in binary form must reproduce the above copyright 
00016  *    notice, this list of conditions and the following disclaimer in 
00017  *    the documentation and/or other materials provided with the 
00018  *    distribution. 
00019  * 
00020  * 3. The end-user documentation included with the redistribution, 
00021  *    if any, must include the following acknowledgment: 
00022  *       "This product includes software developed by the 
00023  *        Kannel Group (http://www.kannel.org/)." 
00024  *    Alternately, this acknowledgment may appear in the software itself, 
00025  *    if and wherever such third-party acknowledgments normally appear. 
00026  * 
00027  * 4. The names "Kannel" and "Kannel Group" must not be used to 
00028  *    endorse or promote products derived from this software without 
00029  *    prior written permission. For written permission, please  
00030  *    contact org@kannel.org. 
00031  * 
00032  * 5. Products derived from this software may not be called "Kannel", 
00033  *    nor may "Kannel" appear in their name, without prior written 
00034  *    permission of the Kannel Group. 
00035  * 
00036  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
00037  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
00038  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00039  * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
00040  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
00041  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
00042  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
00043  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
00044  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
00045  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
00046  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00047  * ==================================================================== 
00048  * 
00049  * This software consists of voluntary contributions made by many 
00050  * individuals on behalf of the Kannel Group.  For more information on  
00051  * the Kannel Group, please see <http://www.kannel.org/>. 
00052  * 
00053  * Portions of this software are based upon software originally written at  
00054  * WapIT Ltd., Helsinki, Finland for the Kannel project.  
00055  */ 
00056 
00057 /*
00058  * wap_push_ppg_pushuser.c: Implementation of wap_push_ppg_pushuser.h header.
00059  *
00060  * By Aarno Syvänen for Wiral Ltd and Global Networks Inc.
00061  */
00062 
00063 #include "wap_push_ppg_pushuser.h"
00064 #include "numhash.h"
00065 #include "gwlib/regex.h"
00066 
00067 /***************************************************************************
00068  *
00069  * Global data structures
00070  *
00071  * Hold user specific  data for one ppg user
00072  */
00073 
00074 struct WAPPushUser {
00075     Octstr *name;                      /* the name of the user */
00076     Octstr *username;                  /* the username of this ppg user */
00077     Octstr *password;                  /* and password */
00078     Octstr *country_prefix;
00079     Octstr *allowed_prefix;            /* phone number prefixes allowed by 
00080                                           this user when pushing*/
00081     regex_t *allowed_prefix_regex;
00082     
00083     Octstr *denied_prefix;             /* and denied ones */
00084     regex_t *denied_prefix_regex;
00085 
00086     Numhash *white_list;               /* phone numbers of this user, used for 
00087                                           push*/
00088     regex_t *white_list_regex;
00089     Numhash *black_list;               /* numbers should not be used for push*/
00090     regex_t *black_list_regex;
00091 
00092     Octstr *user_deny_ip;              /* this user allows pushes from these 
00093                                           IPs*/
00094     Octstr *user_allow_ip;             /* and denies them from these*/
00095     Octstr *smsc_id;                   /* force push SMs to this smsc */
00096     Octstr *default_smsc_id;           /* use this smsc as a default for push SMs */
00097     Octstr *dlr_url;                   /* default dlr url from this user */
00098     Octstr *smsbox_id;                 /* use this smsbox for sending dlrs back*/
00099 };
00100 
00101 typedef struct WAPPushUser WAPPushUser;
00102 
00103 /*
00104  * Hold user specific  data of all ppg users
00105  */
00106 
00107 struct WAPPushUserList {
00108     List *list;
00109     Dict *names;
00110 }; 
00111 
00112 typedef struct WAPPushUserList WAPPushUserList; 
00113 
00114 static WAPPushUserList *users = NULL;
00115 
00116 /*
00117  * This hash table stores time when a specific ip is allowed to try next time.
00118  */
00119 static Dict *next_try = NULL;
00120 
00121 /***********************************************************************************
00122  *
00123  * Prototypes of internal functions
00124  */
00125 
00126 static void destroy_users_list(void *l);
00127 static WAPPushUserList *pushusers_create(long number_of_users);
00128 static WAPPushUser *create_oneuser(CfgGroup *grp);
00129 static void destroy_oneuser(void *p);
00130 static int oneuser_add(CfgGroup *cfg);
00131 static void oneuser_dump(WAPPushUser *u);
00132 static WAPPushUser *user_find_by_username(Octstr *username);
00133 static int password_matches(WAPPushUser *u, Octstr *password);
00134 static int ip_allowed_by_user(WAPPushUser *u, Octstr *ip);
00135 static int prefix_allowed(WAPPushUser *u, Octstr *number);
00136 static int whitelisted(WAPPushUser *u, Octstr *number);
00137 static int blacklisted(WAPPushUser *u, Octstr *number);
00138 static int wildcarded_ip_found(Octstr *ip, Octstr *needle, Octstr *ip_sep);
00139 static int response(List *push_headers, Octstr **username, Octstr **password);
00140 static void challenge(HTTPClient *c, List *push_headers);
00141 static void reply(HTTPClient *c, List *push_headers);
00142 static int parse_cgivars_for_username(List *cgivars, Octstr **username);
00143 static int parse_cgivars_for_password(List *cgivars, Octstr **password);
00144 static int compare_octstr_sequence(Octstr *os1, Octstr *os2, long start);
00145 static Octstr *forced_smsc(WAPPushUser *u);
00146 static Octstr *default_smsc(WAPPushUser *u);
00147 
00148 /****************************************************************************
00149  *
00150  * Implementation of external functions
00151  */
00152 
00153 /*
00154  * Initialize the whole module and fill the push users list.
00155  */
00156 int wap_push_ppg_pushuser_list_add(List *list, long number_of_pushes, 
00157                                    long number_of_users)
00158 {
00159     CfgGroup *grp;
00160 
00161     next_try = dict_create(number_of_pushes, octstr_destroy_item);
00162     users = pushusers_create(number_of_users);
00163     gw_assert(list);
00164     while (list && (grp = gwlist_extract_first(list))) {
00165         if (oneuser_add(grp) == -1) {
00166             gwlist_destroy(list, NULL);
00167             return 0;
00168         }
00169     }
00170     gwlist_destroy(list, NULL);
00171 
00172     return 1;
00173 }
00174 
00175 void wap_push_ppg_pushuser_list_destroy(void)
00176 {
00177     dict_destroy(next_try);
00178     if (users == NULL)
00179         return;
00180 
00181     gwlist_destroy(users->list, destroy_oneuser);
00182     dict_destroy(users->names);
00183     gw_free(users);
00184 }
00185 
00186 enum {
00187     NO_USERNAME = -1,
00188     NO_PASSWORD = 0,
00189     HEADER_AUTHENTICATION = 1
00190 };
00191 
00192 #define ADDITION  0.1
00193 
00194 /*
00195  * This function does authentication possible before compiling the control 
00196  * document. This means:
00197  *           a) password authentication by url or by headers (it is, by basic
00198  *              authentication response, see rfc 2617, chapter 2) 
00199  *           b) if this does not work, basic authentication by challenge - 
00200  *              response 
00201  *           c) enforcing various ip lists
00202  *
00203  * Check does ppg allows a connection from this at all, then try to find username 
00204  * and password from headers, then from url. If both fails, try basic authentica-
00205  * tion. Then check does this user allow a push from this ip, then check the pass-
00206  * word.
00207  *
00208  * For protection against brute force and partial protection for denial of serv-
00209  * ice attacks, an exponential backup algorithm is used. Time when a specific ip  
00210  * is allowed to reconnect, is stored in Dict next_try. If an ip tries to recon-
00211  * nect before this (three attemps are allowed, then exponential seconds are add-
00212  * ed to the limit) we make a new challenge. We do the corresponding check before
00213  * testing passwords; after all, it is an authorization failure that causes a new
00214  * challenge. 
00215  *
00216  * Rfc 2617, chapter 1 states that if we do not accept credentials of an user's, 
00217  * we must send a new challenge to the user.
00218  *
00219  * Output an authenticated username.
00220  * This function should be called only when there are a push users list; the 
00221  * caller is responsible for this.
00222  */
00223 int wap_push_ppg_pushuser_authenticate(HTTPClient *c, List *cgivars, Octstr *ip, 
00224                                        List *push_headers, Octstr **username) {
00225         time_t now;
00226         static long next = 0L;            /* used only in this thread (and this 
00227                                              function) */
00228         long next_time;
00229         Octstr *next_time_os;
00230         static long multiplier = 1L;      /* ditto */
00231         WAPPushUser *u;
00232         Octstr *copy,
00233                *password;
00234         int ret;
00235         
00236         copy = octstr_duplicate(ip);
00237         time(&now);
00238         next_time_os = NULL;
00239 
00240         if ((ret = response(push_headers, username, &password)) == NO_USERNAME) { 
00241             if (!parse_cgivars_for_username(cgivars, username)) {
00242                 error(0, "no user specified, challenging regardless");
00243                 goto listed;
00244             }
00245         }
00246 
00247         if (password == NULL)
00248             parse_cgivars_for_password(cgivars, &password);
00249 
00250         u = user_find_by_username(*username);
00251         if (!ip_allowed_by_user(u, ip)) {
00252             goto not_listed;
00253         }
00254 
00255         next = 0;       
00256 
00257         if ((next_time_os = dict_get(next_try, ip)) != NULL) {
00258             octstr_parse_long(&next_time, next_time_os, 0, 10);
00259             if (difftime(now, (time_t) next_time) < 0) {
00260                 error(0, "another try from %s, not much time used", 
00261                       octstr_get_cstr(copy));
00262                 goto listed;
00263             }
00264         }
00265 
00266         if (u == NULL) {
00267             error(0, "user %s is not allowed by users list, challenging",
00268                   octstr_get_cstr(*username));
00269             goto listed;
00270         }
00271 
00272         if (!password_matches(u, password)) {
00273             error(0, "wrong or missing password in request from %s, challenging" , 
00274                   octstr_get_cstr(copy));
00275             goto listed;
00276         }
00277 
00278         dict_remove(next_try, ip);       /* no restrictions after authentica-
00279                                             tion */
00280         octstr_destroy(password);
00281         octstr_destroy(copy);
00282         octstr_destroy(next_time_os);
00283         return 1;
00284 
00285 not_listed:
00286         octstr_destroy(password);
00287         octstr_destroy(copy); 
00288         reply(c, push_headers);
00289         octstr_destroy(next_time_os);
00290         return 0;
00291 
00292 listed:
00293         challenge(c, push_headers);
00294 
00295         multiplier <<= 1;
00296         next = next + multiplier * ADDITION;
00297         next += now;
00298         next_time_os = octstr_format("%ld", next);
00299         dict_put(next_try, ip, next_time_os);
00300         
00301         octstr_destroy(copy);
00302         octstr_destroy(password);
00303         
00304         return 0;
00305 }
00306 
00307 /*
00308  * This function checks phone number for allowed prefixes, black lists and white
00309  * lists. Note that the phone number necessarily follows the international format 
00310  * (a requirement by our pap compiler).
00311  */
00312 int wap_push_ppg_pushuser_client_phone_number_acceptable(Octstr *username, 
00313         Octstr *number)
00314 {
00315     WAPPushUser *u;
00316 
00317     u = user_find_by_username(username);
00318     if (!prefix_allowed(u, number)) {
00319         error(0, "Number %s not allowed by user %s (wrong prefix)", 
00320               octstr_get_cstr(number), octstr_get_cstr(username));
00321         return 0;
00322     }
00323 
00324     if (blacklisted(u, number)) {
00325         error(0, "Number %s not allowed by user %s (blacklisted)", 
00326               octstr_get_cstr(number), octstr_get_cstr(username) );
00327         return 0;
00328     }
00329 
00330     if (!whitelisted(u, number)) {
00331         error(0, "Number %s not allowed by user %s (not whitelisted)", 
00332               octstr_get_cstr(number), octstr_get_cstr(username) );
00333         return 0;
00334     }
00335 
00336     return 1;
00337 }
00338 
00339 int wap_push_ppg_pushuser_search_ip_from_wildcarded_list(Octstr *haystack, 
00340         Octstr *needle, Octstr *gwlist_sep, Octstr *ip_sep)
00341 {
00342     List *ips;
00343     long i;
00344     Octstr *configured_ip;
00345 
00346     gw_assert(haystack);
00347     gw_assert(gwlist_sep);
00348     gw_assert(ip_sep);
00349 
00350     /*There are no wildcards in the list*/    
00351     if (octstr_search_char(haystack, '*', 0) < 0) {
00352         if (octstr_search(haystack, needle, 0) >= 0) {
00353             return 1;
00354         } else { 
00355             return 0;
00356         }
00357     }
00358     
00359     /*There are wildcards in the list*/
00360     configured_ip = NULL;
00361     ips = octstr_split(haystack, gwlist_sep);
00362     for (i = 0; i < gwlist_len(ips); ++i) {
00363         configured_ip = gwlist_get(ips, i);
00364         if (wildcarded_ip_found(configured_ip, needle, ip_sep))
00365             goto found;
00366     }
00367 
00368     gwlist_destroy(ips, octstr_destroy_item);
00369     return 0;
00370 
00371 found:
00372     gwlist_destroy(ips, octstr_destroy_item);
00373     return 1;
00374 }
00375 
00376 /*
00377  * Returns smsc-id that pushes by this user must use, 
00378  * NULL when there was an error.
00379  */
00380 Octstr *wap_push_ppg_pushuser_smsc_id_get(Octstr *username)
00381 {
00382     WAPPushUser *u;
00383     Octstr *smsc_id;
00384 
00385     if ((u = user_find_by_username(username)) == NULL) {
00386         /* no user found with this username */
00387         return NULL;
00388     }
00389 
00390     if ((smsc_id = forced_smsc(u)) != NULL)
00391         return octstr_duplicate(smsc_id);
00392 
00393     smsc_id = default_smsc(u);
00394     return octstr_duplicate(smsc_id);
00395 }
00396 
00397 /*
00398  * Returns default dlr url for this user.
00399  */
00400 Octstr *wap_push_ppg_pushuser_dlr_url_get(Octstr *username)
00401 {
00402     WAPPushUser *u;
00403     Octstr *dlr_url;
00404 
00405     u = user_find_by_username(username);
00406     dlr_url = u->dlr_url;     
00407 
00408     return octstr_duplicate(dlr_url);
00409 }
00410 
00411 /*
00412  * Returns default dlr smsbox id for this user.
00413  */
00414 Octstr *wap_push_ppg_pushuser_smsbox_id_get(Octstr *username)
00415 {
00416     WAPPushUser *u;
00417     Octstr *smsbox_id;
00418 
00419     u = user_find_by_username(username);
00420     smsbox_id = u->smsbox_id;
00421 
00422     return octstr_duplicate(smsbox_id);
00423 }
00424 
00425 
00426 /***************************************************************************
00427  *
00428  * Implementation of internal functions
00429  */
00430 
00431 static void destroy_users_list(void *l)
00432 {
00433     gwlist_destroy(l, NULL);
00434 }
00435 
00436 static WAPPushUserList *pushusers_create(long number_of_users) 
00437 {
00438     users = gw_malloc(sizeof(WAPPushUserList));
00439     users->list = gwlist_create();
00440     users->names = dict_create(number_of_users, destroy_users_list);
00441 
00442     return users;
00443 }
00444 
00445 /*
00446  * Allocate memory for one push user and read configuration data to it. We initial-
00447  * ize all fields to NULL, because the value NULL means that the configuration did
00448  * not have this variable. 
00449  * Return NULL when failure, a pointer to the data structure otherwise.
00450  */
00451 static WAPPushUser *create_oneuser(CfgGroup *grp)
00452 {
00453     WAPPushUser *u;
00454     Octstr *grpname,
00455            *os;
00456 
00457     grpname = cfg_get(grp, octstr_imm("wap-push-user"));
00458     if (grpname == NULL) {
00459         error(0, "all users group (wap-push-user) are missing");
00460         goto no_grpname;
00461     }
00462    
00463     u = gw_malloc(sizeof(WAPPushUser));
00464     u->name = NULL;
00465     u->username = NULL;                  
00466     u->allowed_prefix = NULL;           
00467     u->allowed_prefix_regex = NULL;           
00468     u->denied_prefix = NULL;             
00469     u->denied_prefix_regex = NULL;             
00470     u->white_list = NULL;               
00471     u->white_list_regex = NULL;               
00472     u->black_list = NULL;              
00473     u->black_list_regex = NULL;              
00474     u->user_deny_ip = NULL;              
00475     u->user_allow_ip = NULL;
00476     u->smsc_id = NULL;
00477     u->default_smsc_id = NULL;
00478 
00479     u->name = cfg_get(grp, octstr_imm("wap-push-user"));
00480 
00481     if (u->name == NULL) {
00482         warning(0, "user name missing, dump follows");
00483         oneuser_dump(u);
00484         goto error;
00485     }
00486 
00487     u->username = cfg_get(grp, octstr_imm("ppg-username"));
00488     u->password = cfg_get(grp, octstr_imm("ppg-password"));
00489 
00490     if (u->username == NULL) {
00491         warning(0, "login name for user %s missing, dump follows", 
00492               octstr_get_cstr(u->name));
00493         oneuser_dump(u);
00494         goto error;
00495     }
00496 
00497     if (u->password == NULL) {
00498         warning(0, "password for user %s missing, dump follows", 
00499               octstr_get_cstr(u->name));
00500         oneuser_dump(u);
00501         goto error;
00502     }
00503 
00504     u->user_deny_ip = cfg_get(grp, octstr_imm("deny-ip"));
00505     u->user_allow_ip = cfg_get(grp, octstr_imm("allow-ip"));
00506     u->country_prefix = cfg_get(grp, octstr_imm("country-prefix"));
00507     u->allowed_prefix = cfg_get(grp, octstr_imm("allowed-prefix"));
00508     u->denied_prefix = cfg_get(grp, octstr_imm("denied-prefix"));
00509     u->smsc_id = cfg_get(grp, octstr_imm("forced-smsc"));
00510     u->default_smsc_id = cfg_get(grp, octstr_imm("default-smsc"));
00511     u->dlr_url = cfg_get(grp, octstr_imm("dlr-url"));
00512     u->smsbox_id = cfg_get(grp, octstr_imm("smsbox-id"));
00513 
00514     os = cfg_get(grp, octstr_imm("white-list"));
00515     if (os != NULL) {
00516         u->white_list = numhash_create(octstr_get_cstr(os));
00517         octstr_destroy(os);
00518     }
00519     os = cfg_get(grp, octstr_imm("black-list"));
00520     if (os != NULL) {
00521         u->black_list = numhash_create(octstr_get_cstr(os));
00522         octstr_destroy(os);
00523     }
00524 
00525     if ((os = cfg_get(grp, octstr_imm("allowed-prefix-regex"))) != NULL) {
00526         if ((u->allowed_prefix_regex = gw_regex_comp(os, REG_EXTENDED)) == NULL)
00527             panic(0, "Could not compile pattern '%s'", octstr_get_cstr(os));
00528         octstr_destroy(os);
00529     };
00530     if ((os = cfg_get(grp, octstr_imm("denied-prefix-regex"))) != NULL) {
00531         if ((u->denied_prefix_regex = gw_regex_comp(os, REG_EXTENDED)) == NULL)
00532             panic(0, "Could not compile pattern '%s'", octstr_get_cstr(os));
00533         octstr_destroy(os);
00534     };
00535     if ((os = cfg_get(grp, octstr_imm("white-list-regex"))) != NULL) {
00536         if ((u->white_list_regex = gw_regex_comp(os, REG_EXTENDED)) == NULL)
00537             panic(0, "Could not compile pattern '%s'", octstr_get_cstr(os));
00538         octstr_destroy(os);
00539     };
00540     if ((os = cfg_get(grp, octstr_imm("black-list-regex"))) != NULL) {
00541         if ((u->black_list_regex = gw_regex_comp(os, REG_EXTENDED)) == NULL)
00542             panic(0, "Could not compile pattern '%s'", octstr_get_cstr(os));
00543         octstr_destroy(os);
00544     };
00545 
00546     octstr_destroy(grpname);
00547     return u;
00548 
00549 no_grpname:
00550     octstr_destroy(grpname);
00551     return NULL;
00552 
00553 error:
00554     octstr_destroy(grpname);
00555     destroy_oneuser(u);
00556     return NULL;
00557 }
00558 
00559 static void destroy_oneuser(void *p) 
00560 {
00561      WAPPushUser *u;
00562 
00563      u = p;
00564      if (u == NULL)
00565          return;
00566 
00567      octstr_destroy(u->name);
00568      octstr_destroy(u->username);  
00569      octstr_destroy(u->password);  
00570      octstr_destroy(u->country_prefix);              
00571      octstr_destroy(u->allowed_prefix);           
00572      octstr_destroy(u->denied_prefix);             
00573      numhash_destroy(u->white_list);               
00574      numhash_destroy(u->black_list);              
00575      octstr_destroy(u->user_deny_ip);              
00576      octstr_destroy(u->user_allow_ip);
00577      octstr_destroy(u->smsc_id);
00578      octstr_destroy(u->default_smsc_id);
00579 
00580      if (u->black_list_regex != NULL) gw_regex_destroy(u->black_list_regex);
00581      if (u->white_list_regex != NULL) gw_regex_destroy(u->white_list_regex);
00582      if (u->denied_prefix_regex != NULL) gw_regex_destroy(u->denied_prefix_regex);
00583      if (u->allowed_prefix_regex != NULL) gw_regex_destroy(u->allowed_prefix_regex);
00584      gw_free(u);             
00585 }
00586 
00587 static void oneuser_dump(WAPPushUser *u)
00588 {
00589     if (u == NULL) {
00590         debug("wap.push.ppg.pushuser", 0, "no user found");
00591         return;
00592     }
00593 
00594     debug("wap.push.ppg.pushuser", 0, "Dumping user data: Name of the user:");
00595     octstr_dump(u->name, 0);
00596     debug("wap.push.ppg.pushuser", 0, "username:");
00597     octstr_dump(u->username, 0);  
00598     debug("wap.push.ppg.pushuser", 0, "omitting password");
00599     debug("wap-push.ppg.pushuser", 0, "country prefix");
00600     octstr_dump(u->country_prefix, 0);   
00601     debug("wap.push.ppg.pushuser", 0, "allowed prefix list:");            
00602     octstr_dump(u->allowed_prefix, 0);  
00603     debug("wap.push.ppg.pushuser", 0, "denied prefix list:");         
00604     octstr_dump(u->denied_prefix, 0);   
00605     debug("wap.push.ppg.pushuser", 0, "denied ip list:");                         
00606     octstr_dump(u->user_deny_ip, 0);    
00607     debug("wap.push.ppg.pushuser", 0, "allowed ip list:");                   
00608     octstr_dump(u->user_allow_ip, 0);
00609     debug("wap.push.ppg.pushuser", 0, "send via smsc-id:");                   
00610     octstr_dump(u->smsc_id, 0);
00611     debug("wap.push.ppg.pushuser", 0, "use default smsc:");
00612     octstr_dump(u->default_smsc_id, 0);
00613     debug("wap.push.ppg.pushuser", 0, "end of the dump");
00614 }
00615 
00616 /*
00617  * Add an user to the push users list
00618  */
00619 static int oneuser_add(CfgGroup *grp)
00620 {
00621     WAPPushUser *u;
00622     List *list;
00623 
00624     u = create_oneuser(grp);
00625     if (u == NULL)
00626         return -1;
00627 
00628     gwlist_append(users->list, u);
00629 
00630     list = dict_get(users->names, u->username);
00631     if (list == NULL) {
00632         list = gwlist_create();
00633         dict_put(users->names, u->username, list);
00634     }
00635 
00636     return 0;
00637 }
00638 
00639 static WAPPushUser *user_find_by_username(Octstr *username)
00640 {
00641     WAPPushUser *u;
00642     long i;
00643     List *list;
00644 
00645     if (username == NULL)
00646         return NULL;
00647 
00648     if ((list = dict_get(users->names, username)) == NULL)
00649          return NULL;
00650 
00651     for (i = 0; i < gwlist_len(users->list); ++i) {
00652          u = gwlist_get(users->list, i);
00653          if (octstr_compare(u->username, username) == 0)
00654              return u;
00655     }
00656 
00657     return NULL;
00658 }
00659 
00660 static int password_matches(WAPPushUser *u, Octstr *password)
00661 {
00662     if (password == NULL)
00663         return 0;    
00664 
00665     return octstr_compare(u->password, password) == 0;
00666 }
00667 
00668 static int wildcarded_ip_found(Octstr *ip, Octstr *needle, Octstr *ip_sep)
00669 {
00670     List *ip_fragments,
00671          *needle_fragments;
00672     long i;
00673     Octstr *ip_fragment,
00674            *needle_fragment;
00675 
00676     ip_fragments = octstr_split(ip, ip_sep);
00677     needle_fragments = octstr_split(needle, ip_sep);
00678 
00679     gw_assert(gwlist_len(ip_fragments) == gwlist_len(needle_fragments));
00680     for (i = 0; i < gwlist_len(ip_fragments); ++i) {
00681         ip_fragment = gwlist_get(ip_fragments, i);
00682         needle_fragment = gwlist_get(needle_fragments, i);
00683         if (octstr_compare(ip_fragment, needle_fragment) != 0 && 
00684                 octstr_compare(ip_fragment, octstr_imm("*")) != 0)
00685             goto not_found;
00686     }
00687 
00688     gwlist_destroy(ip_fragments, octstr_destroy_item);
00689     gwlist_destroy(needle_fragments, octstr_destroy_item);   
00690     return 1;
00691 
00692 not_found:
00693     gwlist_destroy(ip_fragments, octstr_destroy_item);
00694     gwlist_destroy(needle_fragments, octstr_destroy_item);
00695     return 0;
00696 }
00697 
00698 /*
00699  * Deny_ip = '*.*.*.*' is here taken literally: no ips allowed by this user 
00700  * (definitely strange, but not a fatal error). 
00701  */
00702 static int ip_allowed_by_user(WAPPushUser *u, Octstr *ip)
00703 {
00704     Octstr *copy,
00705            *ip_copy;
00706     
00707     if (u == NULL) {
00708         warning(0, "user not found from the users list");
00709         goto no_user;
00710     }
00711 
00712     copy = octstr_duplicate(u->username);
00713 
00714     if (u->user_deny_ip == NULL && u->user_allow_ip == NULL)
00715         goto allowed;
00716 
00717     if (u->user_deny_ip) {
00718         if (octstr_compare(u->user_deny_ip, octstr_imm("*.*.*.*")) == 0) {
00719             warning(0, "no ips allowed for %s", octstr_get_cstr(copy));
00720             goto denied;
00721         }
00722     }
00723 
00724     if (u->user_allow_ip)
00725         if (octstr_compare(u->user_allow_ip, octstr_imm("*.*.*.*")) == 0)
00726             goto allowed;
00727 
00728     if (u->user_deny_ip) {
00729         if (wap_push_ppg_pushuser_search_ip_from_wildcarded_list(u->user_deny_ip, 
00730                 ip, octstr_imm(";"), octstr_imm("."))) {
00731             goto denied;
00732         }
00733     }
00734 
00735     if (u->user_allow_ip) {
00736         if (wap_push_ppg_pushuser_search_ip_from_wildcarded_list(u->user_allow_ip, 
00737                 ip, octstr_imm(";"), octstr_imm("."))) {
00738             goto allowed;
00739         }
00740     }
00741 
00742     octstr_destroy(copy);
00743     warning(0, "ip not found from either ip list, deny it");
00744     return 0;
00745 
00746 allowed:
00747     octstr_destroy(copy);
00748     return 1;
00749 
00750 denied:
00751     ip_copy = octstr_duplicate(ip);
00752     warning(0, "%s denied by user %s", octstr_get_cstr(ip_copy), 
00753             octstr_get_cstr(copy));
00754     octstr_destroy(copy);
00755     octstr_destroy(ip_copy);
00756     return 0;
00757 
00758 no_user:
00759     return 0;
00760 }
00761 
00762 /*
00763  * HTTP basic authentication server response is defined in rfc 2617, chapter 2.
00764  * Return 1, when we found username and password from headers, 0, when there were 
00765  * no password and -1 when there were no username (or no Authorization header at 
00766  * all, or an unparsable one). Username and password value 'NULL' means no user-
00767  * name or password supplied.
00768  */
00769 static int response(List *push_headers, Octstr **username, Octstr **password)
00770 {
00771     Octstr *header_value,
00772            *basic;
00773     size_t basic_len;
00774     List *auth_list;
00775 
00776     *username = NULL;
00777     *password = NULL;
00778 
00779     if ((header_value = http_header_find_first(push_headers, 
00780             "Authorization")) == NULL)
00781         goto no_response3; 
00782 
00783     octstr_strip_blanks(header_value);
00784     basic = octstr_imm("Basic");
00785     basic_len = octstr_len(basic);
00786 
00787     if (octstr_ncompare(header_value, basic, basic_len) != 0)
00788         goto no_response1;
00789 
00790     octstr_delete(header_value, 0, basic_len);
00791     octstr_strip_blanks(header_value);
00792     octstr_base64_to_binary(header_value);
00793     auth_list = octstr_split(header_value, octstr_imm(":"));
00794 
00795     if (gwlist_len(auth_list) != 2)
00796         goto no_response2;
00797     
00798     *username = octstr_duplicate(gwlist_get(auth_list, 0));
00799     *password = octstr_duplicate(gwlist_get(auth_list, 1));
00800 
00801     if (username == NULL) {
00802         goto no_response2;
00803     }
00804 
00805     if (password == NULL) {
00806         goto no_response4;
00807     }
00808 
00809     debug("wap.push.ppg.pushuser", 0, "we have an username and a password in" 
00810           " authorization header");
00811     gwlist_destroy(auth_list, octstr_destroy_item);
00812     octstr_destroy(header_value);
00813     http_header_remove_all(push_headers, "Authorization");
00814     return HEADER_AUTHENTICATION;
00815 
00816 no_response1:
00817     octstr_destroy(header_value);
00818     return NO_USERNAME;
00819 
00820 no_response2:   
00821     gwlist_destroy(auth_list, octstr_destroy_item);
00822     octstr_destroy(header_value);
00823     return NO_USERNAME;
00824 
00825 no_response3:
00826     return NO_USERNAME;
00827 
00828 no_response4:   
00829     gwlist_destroy(auth_list, octstr_destroy_item);
00830     octstr_destroy(header_value);
00831     return NO_PASSWORD;
00832 }
00833 
00834 /*
00835  * HTTP basic authentication server challenge is defined in rfc 2617, chapter 2. 
00836  * Only WWW-Authenticate header is required here by specs. This function does not
00837  * release memory used by push headers, the caller must do this.
00838  */
00839 static void challenge(HTTPClient *c, List *push_headers)
00840 {
00841     Octstr *challenge,
00842            *realm;
00843     int http_status;
00844     List *reply_headers;
00845 
00846     realm = octstr_format("%s", "Basic realm=");
00847     octstr_append(realm, get_official_name());
00848     octstr_format_append(realm, "%s", "\"wappush\"");
00849     reply_headers = http_create_empty_headers();
00850     http_header_add(reply_headers, "WWW-Authenticate", octstr_get_cstr(realm));
00851     http_status = HTTP_UNAUTHORIZED;
00852     challenge = octstr_imm("You must show your credentials.\n");
00853     
00854     http_send_reply(c, http_status, reply_headers, challenge);
00855 
00856     octstr_destroy(realm);
00857     http_destroy_headers(reply_headers);
00858 }
00859 
00860 /*
00861  * This function does not release memory used by push headers, the caller must do this.
00862  */
00863 static void reply(HTTPClient *c, List *push_headers)
00864 {
00865     int http_status;
00866     Octstr *denied;
00867     List *reply_headers;
00868 
00869     reply_headers = http_create_empty_headers();
00870     http_status = HTTP_FORBIDDEN;
00871     denied = octstr_imm("You are not allowed to use this service. Do not retry.\n");
00872  
00873     http_send_reply(c, http_status, push_headers, denied);
00874 
00875     http_destroy_headers(reply_headers);
00876 }
00877 
00878 /*
00879  * Note that the phone number necessarily follows the international format (a requi-
00880  * rement by our pap compiler). So we add country prefix to listed prefixes, if one
00881  * is configured.
00882  */
00883 static int prefix_allowed(WAPPushUser *u, Octstr *number)
00884 {
00885     List *allowed,
00886          *denied;
00887     long i;
00888     Octstr *listed_prefix;
00889 
00890     allowed = NULL;
00891     denied = NULL;
00892 
00893     if (u == NULL)
00894         goto no_user;
00895 
00896     if (        u->allowed_prefix == NULL && u->denied_prefix == NULL 
00897         && u->allowed_prefix_regex == NULL && u->denied_prefix_regex == NULL)
00898         goto no_configuration;
00899 
00900     if (u->denied_prefix != NULL) {
00901         denied = octstr_split(u->denied_prefix, octstr_imm(";"));
00902         for (i = 0; i < gwlist_len(denied); ++i) {
00903              listed_prefix = gwlist_get(denied, i);
00904              if (u->country_prefix != NULL)
00905                  octstr_insert(listed_prefix, u->country_prefix, 0);
00906              if (compare_octstr_sequence(number, listed_prefix, 
00907                      0) == 0) {
00908                  goto denied;
00909              }
00910         }
00911     }
00912 
00913     /* note: country-prefix _must_be included in the pattern */
00914     if (u->denied_prefix_regex != NULL) 
00915         if (gw_regex_match_pre(u->denied_prefix_regex, number) == 1)
00916             goto denied;
00917 
00918     if (u->allowed_prefix_regex == NULL && u->allowed_prefix == NULL) 
00919         goto no_allowed_config;
00920 
00921     if (u->allowed_prefix != NULL) {
00922     allowed = octstr_split(u->allowed_prefix, octstr_imm(";"));
00923     for (i = 0; i < gwlist_len(allowed); ++i) {
00924          listed_prefix = gwlist_get(allowed, i);
00925          if (u->country_prefix != NULL)
00926              octstr_insert(listed_prefix, u->country_prefix, 0);
00927          if (compare_octstr_sequence(number, listed_prefix, 
00928                  0) == 0) {
00929              goto allowed;
00930          }
00931     }
00932     }
00933 
00934     /* note: country-prefix _must_ be included in the pattern */
00935     if (u->allowed_prefix_regex != NULL) 
00936         if (gw_regex_match_pre(u->allowed_prefix_regex, number) == 1)
00937             goto allowed;
00938 
00939 /*
00940  * Here we have an intentional fall-through. It will removed when memory cleaning
00941  * functions are implemented.
00942  */
00943 denied:         
00944     gwlist_destroy(allowed, octstr_destroy_item);
00945     gwlist_destroy(denied, octstr_destroy_item);
00946     return 0;
00947 
00948 allowed:      
00949     gwlist_destroy(allowed, octstr_destroy_item);
00950     gwlist_destroy(denied, octstr_destroy_item);
00951     return 1;
00952 
00953 no_configuration:
00954     return 1;
00955 
00956 no_user:
00957     return 0;
00958 
00959 no_allowed_config:
00960     gwlist_destroy(denied, octstr_destroy_item);
00961     return 1;
00962 }
00963 
00964 static int whitelisted(WAPPushUser *u, Octstr *number)
00965 {
00966     int result = 1;
00967 
00968     if (u->white_list != NULL)
00969         result = numhash_find_number(u->white_list, number);
00970 
00971     if ((result == 0) && (u->white_list_regex != NULL))
00972         result = gw_regex_match_pre(u->white_list_regex, number);
00973 
00974     return result;
00975 }
00976 
00977 static int blacklisted(WAPPushUser *u, Octstr *number)
00978 {
00979     int result = 0;
00980     
00981     if (u->black_list != NULL)
00982         result = numhash_find_number(u->black_list, number);
00983 
00984     if ((result == 0) && (u->black_list_regex != NULL))
00985         result = gw_regex_match_pre(u->black_list_regex, number);
00986 
00987     return result;
00988 }
00989 
00990 /* 
00991  * 'NULL' means here 'no value found'.
00992  * Return 1 when we found username, 0 when we did not.
00993  */
00994 static int parse_cgivars_for_username(List *cgivars, Octstr **username)
00995 {
00996     *username = NULL;
00997     *username = octstr_duplicate(http_cgi_variable(cgivars, "username"));
00998 
00999     if (*username == NULL) {
01000         return 0;
01001     }
01002 
01003     return 1;
01004 }
01005 
01006 static int parse_cgivars_for_password(List *cgivars, Octstr **password)
01007 {
01008     *password = NULL;
01009     *password = octstr_duplicate(http_cgi_variable(cgivars, "password"));
01010 
01011     if (*password == NULL) {
01012         return 0;
01013     }
01014 
01015     return 1;
01016 }
01017 
01018 /*
01019  * Compare an octet string os2 with a sequence of an octet string os1. The sequence
01020  * starts with a position start. 
01021  */
01022 static int compare_octstr_sequence(Octstr *os1, Octstr *os2, long start)
01023 {
01024     int ret;
01025     unsigned char *prefix;
01026     long end;
01027 
01028     if (octstr_len(os2) == 0)
01029         return 1;
01030 
01031     if (octstr_len(os1) == 0)
01032         return -1;
01033 
01034     prefix = NULL;
01035     if (start != 0) {
01036         prefix = gw_malloc(start);
01037         octstr_get_many_chars((char *)prefix, os1, 0, start);
01038         octstr_delete(os1, 0, start);
01039     }
01040     
01041     end = start + octstr_len(os2);
01042     ret = octstr_ncompare(os1, os2, end - start);
01043     
01044     if (start != 0) {
01045         octstr_insert_data(os1, 0, (char *)prefix, start);
01046         gw_free(prefix);
01047     }
01048 
01049     return ret;
01050 }
01051 
01052 static Octstr *forced_smsc(WAPPushUser *u)
01053 {
01054     return u->smsc_id;
01055 }
01056 
01057 static Octstr *default_smsc(WAPPushUser *u)
01058 {
01059     return u->default_smsc_id;
01060 }
01061 
01062 
01063 
01064 
01065 
01066 
01067 
01068 
01069 
01070 
01071 
01072 
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.