📄 wap_push_ppg_pushuser.c
字号:
/* ==================================================================== * The Kannel Software License, Version 1.0 * * Copyright (c) 2001-2004 Kannel Group * Copyright (c) 1998-2001 WapIT Ltd. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Kannel Group (http://www.kannel.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Kannel" and "Kannel Group" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please * contact org@kannel.org. * * 5. Products derived from this software may not be called "Kannel", * nor may "Kannel" appear in their name, without prior written * permission of the Kannel Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Kannel Group. For more information on * the Kannel Group, please see <http://www.kannel.org/>. * * Portions of this software are based upon software originally written at * WapIT Ltd., Helsinki, Finland for the Kannel project. */ /* * wap_push_ppg_pushuser.c: Implementation of wap_push_ppg_pushuser.h header. * * By Aarno Syv鋘en for Wiral Ltd and Global Networks Inc. */#include "wap_push_ppg_pushuser.h"#include "numhash.h"#include "gwlib/regex.h"/*************************************************************************** * * Global data structures * * Hold user specific data for one ppg user */struct WAPPushUser { Octstr *name; /* the name of the user */ Octstr *username; /* the username of this ppg user */ Octstr *password; /* and password */ Octstr *country_prefix; Octstr *allowed_prefix; /* phone number prefixes allowed by this user when pushing*/ regex_t *allowed_prefix_regex; Octstr *denied_prefix; /* and denied ones */ regex_t *denied_prefix_regex; Numhash *white_list; /* phone numbers of this user, used for push*/ regex_t *white_list_regex; Numhash *black_list; /* numbers should not be used for push*/ regex_t *black_list_regex; Octstr *user_deny_ip; /* this user allows pushes from these IPs*/ Octstr *user_allow_ip; /* and denies them from these*/ Octstr *smsc_id; /* force push SMs to this smsc */ Octstr *default_smsc_id; /* use this smsc as a default for push SMs */ Octstr *dlr_url; /* default dlr url from this user */ Octstr *smsbox_id; /* use this smsbox for sending dlrs back*/};typedef struct WAPPushUser WAPPushUser;/* * Hold user specific data of all ppg users */struct WAPPushUserList { List *list; Dict *names;}; typedef struct WAPPushUserList WAPPushUserList; static WAPPushUserList *users = NULL;/* * This hash table stores time when a specific ip is allowed to try next time. */static Dict *next_try = NULL;/*********************************************************************************** * * Prototypes of internal functions */static void destroy_users_list(void *l);static WAPPushUserList *pushusers_create(long number_of_users);static WAPPushUser *create_oneuser(CfgGroup *grp);static void destroy_oneuser(void *p);static int oneuser_add(CfgGroup *cfg);static void oneuser_dump(WAPPushUser *u);static WAPPushUser *user_find_by_username(Octstr *username);static int password_matches(WAPPushUser *u, Octstr *password);static int ip_allowed_by_user(WAPPushUser *u, Octstr *ip);static int prefix_allowed(WAPPushUser *u, Octstr *number);static int whitelisted(WAPPushUser *u, Octstr *number);static int blacklisted(WAPPushUser *u, Octstr *number);static int wildcarded_ip_found(Octstr *ip, Octstr *needle, Octstr *ip_sep);static int response(List *push_headers, Octstr **username, Octstr **password);static void challenge(HTTPClient *c, List *push_headers);static void reply(HTTPClient *c, List *push_headers);static int parse_cgivars_for_username(List *cgivars, Octstr **username);static int parse_cgivars_for_password(List *cgivars, Octstr **password);static int compare_octstr_sequence(Octstr *os1, Octstr *os2, long start);static Octstr *forced_smsc(WAPPushUser *u);static Octstr *default_smsc(WAPPushUser *u);/**************************************************************************** * * Implementation of external functions *//* * Initialize the whole module and fill the push users list. */int wap_push_ppg_pushuser_list_add(List *list, long number_of_pushes, long number_of_users){ CfgGroup *grp; next_try = dict_create(number_of_pushes, octstr_destroy_item); users = pushusers_create(number_of_users); gw_assert(list); while (list && (grp = list_extract_first(list))) { if (oneuser_add(grp) == -1) { list_destroy(list, NULL); return 0; } } list_destroy(list, NULL); return 1;}void wap_push_ppg_pushuser_list_destroy(void){ dict_destroy(next_try); if (users == NULL) return; list_destroy(users->list, destroy_oneuser); dict_destroy(users->names); gw_free(users);}enum { NO_USERNAME = -1, NO_PASSWORD = 0, HEADER_AUTHENTICATION = 1};#define ADDITION 0.1/* * This function does authentication possible before compiling the control * document. This means: * a) password authentication by url or by headers (it is, by basic * authentication response, see rfc 2617, chapter 2) * b) if this does not work, basic authentication by challenge - * response * c) enforcing various ip lists * * Check does ppg allows a connection from this at all, then try to find username * and password from headers, then from url. If both fails, try basic authentica- * tion. Then check does this user allow a push from this ip, then check the pass- * word. * * For protection against brute force and partial protection for denial of serv- * ice attacks, an exponential backup algorithm is used. Time when a specific ip * is allowed to reconnect, is stored in Dict next_try. If an ip tries to recon- * nect before this (three attemps are allowed, then exponential seconds are add- * ed to the limit) we make a new challenge. We do the corresponding check before * testing passwords; after all, it is an authorization failure that causes a new * challenge. * * Rfc 2617, chapter 1 states that if we do not accept credentials of an user's, * we must send a new challenge to the user. * * Output an authenticated username. * This function should be called only when there are a push users list; the * caller is responsible for this. */int wap_push_ppg_pushuser_authenticate(HTTPClient *c, List *cgivars, Octstr *ip, List *push_headers, Octstr **username) { time_t now; static long next = 0L; /* used only in this thread (and this function) */ long next_time; Octstr *next_time_os; static long multiplier = 1L; /* ditto */ WAPPushUser *u; Octstr *copy, *password; int ret; copy = octstr_duplicate(ip); time(&now); next_time_os = NULL; if ((ret = response(push_headers, username, &password)) == NO_USERNAME) { if (!parse_cgivars_for_username(cgivars, username)) { error(0, "no user specified, challenging regardless"); goto listed; } } if (password == NULL) parse_cgivars_for_password(cgivars, &password); u = user_find_by_username(*username); if (!ip_allowed_by_user(u, ip)) { goto not_listed; } next = 0; if ((next_time_os = dict_get(next_try, ip)) != NULL) { octstr_parse_long(&next_time, next_time_os, 0, 10); if (difftime(now, (time_t) next_time) < 0) { error(0, "another try from %s, not much time used", octstr_get_cstr(copy)); goto listed; } } if (u == NULL) { error(0, "user %s is not allowed by users list, challenging", octstr_get_cstr(*username)); goto listed; } if (!password_matches(u, password)) { error(0, "wrong or missing password in request from %s, challenging" , octstr_get_cstr(copy)); goto listed; } dict_remove(next_try, ip); /* no restrictions after authentica- tion */ octstr_destroy(password); octstr_destroy(copy); octstr_destroy(next_time_os); return 1;not_listed: octstr_destroy(password); octstr_destroy(copy); reply(c, push_headers); octstr_destroy(next_time_os); return 0;listed: challenge(c, push_headers); multiplier <<= 1; next = next + multiplier * ADDITION; next += now; next_time_os = octstr_format("%ld", next); dict_put(next_try, ip, next_time_os); octstr_destroy(copy); octstr_destroy(password); return 0;}/* * This function checks phone number for allowed prefixes, black lists and white * lists. Note that the phone number necessarily follows the international format * (a requirement by our pap compiler). */int wap_push_ppg_pushuser_client_phone_number_acceptable(Octstr *username, Octstr *number){ WAPPushUser *u; u = user_find_by_username(username); if (!prefix_allowed(u, number)) { error(0, "Number %s not allowed by user %s (wrong prefix)", octstr_get_cstr(number), octstr_get_cstr(username)); return 0; } if (blacklisted(u, number)) { error(0, "Number %s not allowed by user %s (blacklisted)", octstr_get_cstr(number), octstr_get_cstr(username) ); return 0; } if (!whitelisted(u, number)) { error(0, "Number %s not allowed by user %s (not whitelisted)", octstr_get_cstr(number), octstr_get_cstr(username) ); return 0; } return 1;}int wap_push_ppg_pushuser_search_ip_from_wildcarded_list(Octstr *haystack, Octstr *needle, Octstr *list_sep, Octstr *ip_sep){ List *ips; long i; Octstr *configured_ip; gw_assert(haystack); gw_assert(list_sep); gw_assert(ip_sep); /*There are no wildcards in the list*/ if (octstr_search_char(haystack, '*', 0) < 0) { if (octstr_search(haystack, needle, 0) >= 0) { return 1; } else { return 0; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -