Completely remove XMLRPC

This commit is contained in:
Timothée Jaussoin 2023-07-12 14:48:11 +00:00
parent 86983f3f9b
commit 16a26d1576
72 changed files with 136 additions and 7067 deletions

1
.gitignore vendored
View file

@ -3,7 +3,6 @@ rpmbuild/
.env.*
xmlrpc/src/vendor
flexiapi/node_modules
flexiapi/public/hot
flexiapi/public/storage

View file

@ -17,7 +17,6 @@ remi-phpredis-package:
needs:
- remi-igbinary-package
- remi-msgpack-package
- remi-xmlrpc-package
variables:
PACKAGE: $PHP_REDIS_REMI_VERSION
@ -31,11 +30,6 @@ remi-msgpack-package:
variables:
PACKAGE: $PHP_MSGPACK_REMI_VERSION
remi-xmlrpc-package:
extends: .remi-package
variables:
PACKAGE: $PHP_XMLRPC_REMI_VERSION
.remi-package:
extends: .package
image: gitlab.linphone.org:4567/bc/public/docker/rocky8-php:$ROCKY_8_IMAGE_VERSION

View file

@ -3,7 +3,6 @@ rocky8-test:
image: gitlab.linphone.org:4567/bc/public/docker/rocky8-php:$ROCKY_8_IMAGE_VERSION
needs:
- rocky8-package
- remi-xmlrpc-package
script:
- yum -y localinstall build/*.rpm
- cd /opt/belledonne-communications/share/flexisip-account-manager/flexiapi

View file

@ -4,7 +4,6 @@ variables:
PHP_REDIS_REMI_VERSION: php-pecl-redis5-5.3.6-1
PHP_IGBINARY_REMI_VERSION: php-pecl-igbinary-3.2.14-1
PHP_MSGPACK_REMI_VERSION: php-pecl-msgpack-2.2.0-1
PHP_XMLRPC_REMI_VERSION: php-pecl-xmlrpc-1.0.0~rc3-2
include:
- '.gitlab-ci-files/package.yml'

View file

@ -24,11 +24,9 @@ cleanup-package-semvers:
prepare:
cd flexiapi && php composer.phar install --ignore-platform-req=ext-redis --no-dev
cd xmlrpc/src && cp ../../flexiapi/composer.phar . && php composer.phar install --ignore-platform-req=ext-redis --no-dev
prepare-dev:
cd flexiapi && php composer.phar install --ignore-platform-req=ext-redis
cd xmlrpc/src && cp ../../flexiapi/composer.phar . && php composer.phar install --ignore-platform-req=ext-redis
package-common:
rm -rf $(OUTPUT_DIR)/flexisip-account-manager
@ -36,16 +34,10 @@ package-common:
mkdir -p $(OUTPUT_DIR)/rpmbuild/SPECS
mkdir -p $(OUTPUT_DIR)/rpmbuild/SOURCES
# XMLRPC
cp -R --parents xmlrpc/src/**/*.php $(OUTPUT_DIR)/flexisip-account-manager/
cp -R --parents xmlrpc/src/vendor/**/* $(OUTPUT_DIR)/flexisip-account-manager/
cp -R --parents xmlrpc/src/api/**/*.php $(OUTPUT_DIR)/flexisip-account-manager/
cp -R --parents conf/*.conf $(OUTPUT_DIR)/flexisip-account-manager/
# FlexiAPI
cp -R --parents flexiapi/**/* $(OUTPUT_DIR)/flexisip-account-manager/
cp flexiapi/composer* $(OUTPUT_DIR)/flexisip-account-manager/flexiapi/
cp README.md $(OUTPUT_DIR)/flexisip-account-manager/flexiapi/
cp README.md $(OUTPUT_DIR)/flexisip-account-manager/
cp flexiapi/.env.example $(OUTPUT_DIR)/flexisip-account-manager/flexiapi/.env.example
cp flexiapi/artisan $(OUTPUT_DIR)/flexisip-account-manager/flexiapi/
cp flexiapi/phpunit.xml $(OUTPUT_DIR)/flexisip-account-manager/flexiapi/
@ -53,7 +45,6 @@ package-common:
cp flexiapi/phpmd.xml $(OUTPUT_DIR)/flexisip-account-manager/flexiapi/
# General
cp xmlrpc/README.md $(OUTPUT_DIR)/flexisip-account-manager/
cp -R httpd/ $(OUTPUT_DIR)/flexisip-account-manager/
cp -R cron/ $(OUTPUT_DIR)/flexisip-account-manager/
cp flexisip-account-manager.spec.run $(OUTPUT_DIR)/rpmbuild/SPECS/flexisip-account-manager.spec

View file

@ -6,8 +6,6 @@ Flexisip Account Manager brings several tools in one:
- a web portal, powered by FlexiAPI
- a remote provisioning server, able to generate configuration files compatible with Linphone's QrCode-based or URL-based remote provisioning feature
It replaces the historical XMLRPC tool that is still available in `xmlrpc/` for retrocompatibility purpose.
# License
Copyright © Belledonne Communications

View file

@ -1,94 +0,0 @@
<?php
/*
* The SIP domain to use to hash passwords.
*
* Default value: sip.example.org
*/
define("SIP_DOMAIN", "sip.example.org");
/*
* If true, when account is created, the password will be generated automatically (see below).
* Otherwise it has to be given as the last parameter of the create_account method call.
*
* Default value: False
*/
define("GENERATE_PASSWORD_ENABLED", False);
/*
* A string with each character allowed in the password generation.
*
* Default value: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789``-=~!@#$%^&*()_+,./<>?;:[]{}\|
*/
define("GENERATED_PASSWORD_CHARACTERS", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789``-=~!@#$%^&*()_+,./<>?;:[]{}\|");
/*
* The length of the passwords that will be generated.
*
* Default value: 8
*/
define("GENERATED_PASSWORD_LENGTH", 8);
/*
* The default algorithm to use if not specified in the request
*
* Default value: MD5
*/
define("DEFAULT_ALGORITHM", "MD5");
/*
* A string with each character allowed in the username generation.
*
* Default value: abcdefghijklmnopqrstuvwxyz0123456789.-_
*/
define("GENERATED_USERNAME_CHARACTERS", "abcdefghijklmnopqrstuvwxyz0123456789.-_");
/*
* The length of the username that will be generated.
*
* Default value: 12
*/
define("GENERATED_USERNAME_LENGTH", 12);
/*
* If set to True, a created account will automatically be activated and it's expiration date set to now + TRIAL_DURATION_DAYS,
* otherwise expiration date for trial will be set when account is activated via a different xml rpc call.
*/
define('AUTO_ACTIVATE_ACCOUNT', False);
/*
* Send an email to activate the account when it is created.
*/
define('SEND_ACTIVATION_EMAIL', True);
/*
* Send a sms to activate the phone account when it is created.
*/
define('SEND_ACTIVATION_SMS', True);
/*
* If false, creating an account with an email that is already used for another account will trigger an error
*/
define('ALLOW_SAME_EMAILS_ON_MULTILPLE_ACCOUNTS', True);
/*
* If true, when an account creation request is received for an existing number, assumes recover procedure
*/
define('RECOVER_ACCOUNT_IF_EXISTS', False);
/*
* Enabling geoloc of accounts in user_info table.
* When this option is set, the fields coutry_name and country_code will be filled
* with a call to api.ipapi.com
*
* Default value: False
*/
define("ENABLE_NEW_ACCOUNTS_GEOLOC", False);
/* API key for geoloc. If you need geoloc and don't have a key,
* ask it on ipapi.com
*/
define("GEOLOC_ACCESS_KEY", "");
?>

View file

@ -1,34 +0,0 @@
<?php
/* ### Authentication configuration ### */
/*
* Attempt to authenticate sensitive xmlrpc requests using DIGEST.
*
* Default value: FALSE
*/
define("USE_DIGEST_AUTH", FALSE);
/*
* The domain to use for digest auth.
*
* Default value: sip.example.org
*/
define("AUTH_REALM", "sip.example.org");
/* Authentication Nonce Key
* This value must be a random string(12 characters minimum length) specific to each server and is PRIVATE
*
* Default value : The default is empty to force using a key different for each server
*/
define("AUTH_NONCE_KEY", "");
/* Authentication Nonce Validity
* The authentication is aimed to provide a one time usage nonce, it is not strictly inforced by storing valid once, instead
* we use a short living period, the maximum validity period will be twice the minimum one, value is in seconds
*
* Default value : 10 seconds
*/
define("MIN_NONCE_VALIDITY_PERIOD", 10);
?>

View file

@ -1,126 +0,0 @@
<?php
/* ### Database configuration ### */
/*
* The host on which the database is located.
*
* Default value: localhost
*/
define("DB_HOST", "localhost");
/*
* Enable data transfert over ssl.
*
* Default value: False
*/
define("DB_ENABLE_SSL", "False");
/*
* rootca path. MANDATORY for DB SSL to work
*
* Default value: ""
* Possible value : /opt/belledonne-communications/share/linphone/rootca.pem
*/
define("ROOT_CA_PATH", "");
/*
* The database username.
*
* Default value: flexisip_rw
*/
define("DB_USER", "flexisip_rw");
/*
* The database user's password.
*
* Default value:
*/
define("DB_PASSWORD", "");
/*
* The name of the database.
*
* Default value: flexisip
*/
define("DB_NAME", "flexisip");
/*
* The name of the accounts table.
*
* Default value: accounts
*/
define("ACCOUNTS_DB_TABLE", "accounts");
/*
* The name of the accounts_algo table.
*
* Default value: passwords
*/
define("ACCOUNTS_ALGO_DB_TABLE", "passwords");
/*
* The name of the aliases table.
* It is used to store links between an alias (phone number, facebook id, google email, ...) and a SIP address
*
* Default value: aliases
*/
define("ALIAS_DB_TABLE", "aliases");
/*
* The name of the devices table.
* It is used to store hardware information about devices running linphone
*
* Default value: devices
*/
define("DEVICES_DB_TABLE", "devices");
/*
* The name of the sms table.
* It is used to keep track of sent SMS
*
* Default value: sms
*/
define("SMS_DB_TABLE", "sms");
/*
* The name of the inapp table.
* It is used to store informations about in-app purchases, accounts expiration, etc...
*
* Default value: inapp_purchases
*/
define("INAPP_DB_TABLE", "inapp_purchases");
/*
* The name of the user informations table.
* It is used to store informations about user like firstname, lastname, gender, etc...
*
* Default value: user_info
*/
define("USER_INFO_DB_TABLE", "user_info");
/*
* The delay in minutes before test account expiration.
* It is used to delete old test accounts from database;
*
* Default value: 180
*/
define("EXPIRATION_DELAY", 180);
/*
* The value to use in the database after a one time confirmation has been used
*
* Default value: ERROR
*/
define ("INVALID_CONFIRMATION_KEY", "ERROR");
/*
* Update confirmation key to INVALID_CONFIRMATION_KEY after correct use
*
* Default value: TRUE
*/
define("REMOVE_CONFIRMATION_KEY_AFTER_USE", TRUE);
?>

View file

@ -1,76 +0,0 @@
<?php
/* ### Email configuration ### */
/*
* Whever or not enable the send email feature.
* Used to send link to generate random password if user forgot it, or the newly generated email once the link has been clicked.
*
* Default value: False
*/
define("EMAIL_ENABLED", False);
/*
* The website address to display in the email header.
*
* Default value: https://linphone.org
*/
define("EMAIL_SITE", "https://linphone.org");
/*
* The link to open when click on activation
* It must have a %key% and %username% parameters and eventually a %domain% and/or %algo%
*
* Default value: www.linphone.org/flexisip-account-manager/activation.php?username=%username%&confirmation_key=%key%&domain=%domain%&algorithm=%algo%
*/
define("EMAIL_ACTIVATION_LINK", "www.linphone.org/flexisip-account-manager/activation.php?username=%username%&confirmation_key=%key%&domain=%domain%&algorithm=%algo%");
/*
* The FROM address to set in the email header.
*
* Default value: no.reply@linphone.org
*/
define("EMAIL_FROM_ADDR", "no.reply@linphone.org");
/*
* The FROM display name to set in the email header.
*
* Default value: No reply at Linphone.org
*/
define("EMAIL_FROM_NAME", "No reply at Linphone.org");
/*
* The subject of the activation account email.
*/
define("EMAIL_ACTIVATION_SUBJECT", "Start your sip.linphone.org service");
/*
* The body (as text) of the activation account email.
* It must have a %link% parameter somewhere with the link to click to activate the account
*/
define("EMAIL_ACTIVATION_BODY", "Hello,\nActivation pending for using your Linphone account.\nPlease use the link bellow to activate your account :\n\n%link%\n\nRegards,\nThe Linphone team.\n");
/*
* The body (as html) of the activation account email.
* It must have a %link% parameter somewhere with the link to click to activate the account
*/
define("EMAIL_ACTIVATION_BODY_HTML", '<html><head><title>Start your sip.linphone.org service</title></head><body><p>Hello,</p><p>Activation pending for using your Linphone account.<br />Please use the link bellow to activate your account :</p><p><a href="%link%">%link%</a></p><p>&nbsp;</p><p>Regards,<br />The Linphone team.</p></body></html>');
/*
* The subject of the account recovery email.
*/
define("EMAIL_RECOVERY_SUBJECT", "Recover your sip.linphone.org account");
/*
* The body (as text) of the account recovery email.
* It must have a %key% parameter that will be replaced with the recovery code
*/
define("EMAIL_RECOVERY_BODY", "Hello,\nHere is your recovery code: %key%\n\nRegards,\nThe Linphone team.\n");
/*
* The body (as html) of the account recovery email.
* It must have a %key% parameter that will be replaced with the recovery code
*/
define("EMAIL_RECOVERY_BODY_HTML", '<html><head><title>Recover your sip.linphone.org account</title></head><body><p>Hello,</p><p>Here is your recovery code: %key%</p><p>Regards,<br />The Linphone team.</p></body></html>');
?>

View file

@ -1,37 +0,0 @@
<?php
/* ### Hooks configuration ### */
/*
* Set the following to TRUE to be called in the below functions
*
* Default value: FALSE
*/
define('CUSTOM_HOOKS', FALSE);
/** ### Hooks implementation ### */
function hook_on_account_created($account) {
}
function hook_on_account_activated($account) {
}
/** ### request_params array my contain username, domain, transport, ha1 and algo ### */
function provisioning_hook_on_proxy_config(&$xml, $request_params) {
$xml .= '<entry name="conference_factory_uri" overwrite="true">sip:conference-factory@' . $request_params["domain"] . '</entry>';
}
function provisioning_hook_on_auth_info(&$xml, $request_params) {
}
function provisioning_hook_on_additional_section(&$xml, $request_params) {
$xml .= '<section name="sip">';
$xml .= '<entry name="rls_uri" overwrite="true">sips:rls@' . $request_params["domain"] . '</entry>';
$xml .= '</section>';
}
?>

View file

@ -1,90 +0,0 @@
<?php
/*
* If set to True, a created account will be flagged as trial with an expiration date set in TRIAL_DURATION_DAYS days in the future.
*/
define ('USE_IN_APP_PURCHASES', False);
/*
* This value determines the number of days for trial starting when the account will be activated.
*
* Default value: 365
*/
define('TRIAL_DURATION_DAYS', 365);
/* ### Apple/ioS configuration ### */
/*
* The URL to use to validate an Apple in app purchase receipts.
*
* Default value: https://buy.itunes.apple.com/verifyReceipt
*/
define("APPLE_URL", "https://buy.itunes.apple.com/verifyReceipt");
/*
* The URL to use to validate an Apple in app purchase receipts while app is in development.
*
* Default value: https://buy.itunes.apple.com/verifyReceipt
*/
define("APPLE_SANDBOX_URL", "https://sandbox.itunes.apple.com/verifyReceipt");
/*
* The shared secret for your application.
* Used to validate in app purchase receipts.
*
* Default value:
*/
define("APPLE_SECRET", "");
/* ### Google/Android configuration ### */
/*
* The package name of your Android application.
* Used to validate in app purchase receipts.
*
* Default value: org.linphone
*/
define("ANDROID_PACKAGE", "org.linphone");
/*
* The path to the public key generated by the Android Play Store.
* See the documentation to know how to get it.
*
* Default value: google.pem
*/
define("ANDROID_PUB_KEY_PATH", "google.pem");
/*
* The URL to use to get the authentication token to make calls to Google API server.
* Used to validate in app purchase receipts.
*
* Default value: https://accounts.google.com/o/oauth2/token
*/
define("GOOGLE_API_OAUTH_URL", "https://accounts.google.com/o/oauth2/token");
/*
* The project ID with the access to the Android Developer Console API
* Used to validate in app purchase receipts.
*
* Default value:
*/
define("GOOGLE_PROJECT_ID", "");
/*
* The previous project ID's password
* Used to validate in app purchase receipts.
*
* Default value:
*/
define("GOOGLE_PROJECT_PASSWORD", "");
/*
* The refresh token generated by the Google Developer server.
* See documentation to know how to get it.
* Used to validate in app purchase receipts.
*
* Default value:
*/
define("GOOGLE_PROJECT_REFRESH_TOKEN", "");
?>

View file

@ -1,35 +0,0 @@
<?php
/* ### Logs configuration ### */
/*
* Whever or not to log each function called.
* Passwords are never logged.
*
* Default value: True
*/
define("LOGS_ENABLED", True);
/*
* Whever or not to log everything in the same file.
* If false, a new log file will be created every day.
*
* Default value: True
*/
define("USE_ONE_LOG_FILE", True);
/*
* The file in which to log.
*
* Default value: "/var/opt/belledonne-communications/log/account-manager.log"
*/
define("LOG_FILE", "/var/opt/belledonne-communications/log/account-manager.log");
/*
* The dir in which to log.
*
* Default value: "/var/opt/belledonne-communications/log/account-manager.log"
*/
define("LOG_DIR", "/var/opt/belledonne-communications/log/");
?>

View file

@ -1,26 +0,0 @@
<?php
/* ### Overloads configuration ### */
/*
* Set the following to TRUE to overload the xmlrpc_recover_phone_account function
*
* Default value: FALSE
*/
define('XMLRPC_RECOVER_PHONE_ACCOUNT_OVERLOAD', FALSE);
/** ### Overloads implementation */
// We may need to access some of the functions provided by the server (database access at least)
// so we need to know where to find them
define("PATH_TO_INSTALLATION", "/opt/belledonne-communications/share/flexisip-account-manager");
if (XMLRPC_RECOVER_PHONE_ACCOUNT_OVERLOAD === True) {
include_once PATH_TO_INSTALLATION . '/database/database.php';
}
// args = [phone, [domain], [lang]]
// is expected to return the recovered account username or ACCOUNT_NOT_FOUND
function xmlrpc_recover_phone_account_overload($method, $args) {
}
?>

View file

@ -1,46 +0,0 @@
<?php
/*
* If set to True, each section will be flagged as overwrite, otherwise none of them will be flagged.
*
* Default value: False
*/
define("REMOTE_PROVISIONING_OVERWRITE_ALL", False);
/*
* The path to a default linphone rc file to add to the generated remote provisioning
* If using the default value, the default.rc file should be created in /opt/belledonne-communications/share/flexisip-account-manager/xmlrpc/ directory
* If the file does not exists it is ignored
*
* The file should follow the lpconfig format, for example:
* [sip]
* rls_uri=sips:rls@sip.linphone.org
* # This is a commentary, it won't appear in the generated xml provisioning
*
* Default value: "default.rc"
*/
define("REMOTE_PROVISIONING_DEFAULT_CONFIG", "default.rc");
/*
* The default transport to set in the proxy config if not specified
* Can be "tls", "tcp" or "udp"
*
* Default value: "tls"
*/
define("REMOTE_PROVISIONING_DEFAULT_TRANSPORT", "tls");
/*
* If set to True, provisioning.php will generate a new password if the account was not activated yet and activate it.
*
* Default value: False
*/
define("REMOTE_PROVISIONING_ONE_TIME_PASSWORD", False);
/*
* If set to True, digest authentication will be asked for remote provisioning process (see auth.conf).
*
* Default value: False
*/
define("REMOTE_PROVISIONING_USE_DIGEST_AUTH", False);
?>

View file

@ -1,124 +0,0 @@
<?php
/* ### SMS API configuration ### */
/*
* Whever or not enable the send SMS feature.
* Used to verify phone number when used as SIP username.
*
* Default value: False
*/
define("SMS_API_ENABLED", False);
/*
* The application key for OVH SMS platform
*
* Default value:
*/
define("SMS_OVH_API_KEY", "");
/*
* The application secret for OVH SMS platform
*
* Default value:
*/
define("SMS_OVH_API_SECRET", "");
/*
* The consumer key for OVH SMS platform
*
* Default value:
*/
define("SMS_OVH_CONSUMER_KEY", "");
/*
* The sender alias for OVH SMS
*
* Default value: "Linphone"
*/
define("SMS_OVH_SENDER", "Linphone");
/*
* Whever or not to use a sender to send the SMS.
* When using sender you can customize the name of the sender, otherwise it will be a phone number.
* To disable for clients using our own OVH SMS account.
*
* Default value: True
*/
define("SMS_USE_SENDER", True);
/*
* The sender reason for OVH SMS
*
* Default value: "created Linphone SMS sender"
*/
define("SMS_OVH_REASON", "created Linphone SMS sender");
/*
* The sender description for OVH SMS
*
* Default value: "Linphone SMS sender"
*/
define("SMS_OVH_DESC", "Linphone SMS sender");
/*
* The template to use to send SMS to the US
* Remember to stay under 160 characters
*
* Default value: "Your Linphone validation code is #CODE#"
*/
define("SMS_OVH_US_TEMPLATE", "Your Linphone validation code is #CODE#");
/*
* The OVH endpoint
*
* Default value: ovh-eu
*/
define("SMS_OVH_ENDPOINT", "ovh-eu");
/*
* The URL at which the SMS API is available.
*
* Default value:
*/
define("SMS_API_URL", "");
/*
* The username to authenticate to the SMS API if needed.
*
* Default value:
*/
define("SMS_API_USERNAME", "");
/*
* The username's password to authenticate to the SMS API if needed.
*
* Default value:
*/
define("SMS_API_PASSWORD", "");
/*
* The period of time (in milli seconds) over which we compute the number of sent sms
*
* Default value: 86400000 (24 hours)
*/
define("SMS_TIME_PERIOD", 86400000);
/*
* The maximum number of allowed SMS to be sent over the period
* MUST BE LESS THAN 255 !
*
* Default value: 3
*/
define("SMS_COUNT_LIMIT_IN_PERIOD", 3);
/**
* Translation for OVH SMS template
* Remember to stay under 160 characters
*/
$SMS_OVH_TEMPLATE = array (
'US' => 'Your Linphone validation code is #CODE#', // This one isn't required but if present it MUST be equal to SMS_OVH_US_TEMPLATE
'FR' => 'Votre code de validation Linphone est #CODE#',
);
?>

View file

@ -1,26 +0,0 @@
<?php
/* ### Tests configuration ### */
/*
* If true, more features are available for test purposes
*
* Default value: False
*/
define('ALLOW_TEST_ACCOUNTS', False);
/*
* Prefix used only by tests account to enable/disable some features
*
* Default value: "+1000555"
*/
define("TESTS_PHONE_PREFIX", "+1000555");
/*
* Prefix used only by tests account to enable/disable some features
*
* Default value: "XXXTEST"
*/
define("TESTS_LOGIN_PREFIX", "xxxtest");
?>

View file

@ -39,7 +39,12 @@ class SetAccountAdmin extends Command
$account = Account::withoutGlobalScopes()->where('id', $this->argument('id'))->first();
if (!$account) {
$this->error('Account not found, please use an existing SIP address');
$this->error('Account not found, please use an existing account id');
return 1;
}
if ($account->admin) {
$this->error('The account is already having the admin role');
return 1;
}

View file

@ -132,6 +132,11 @@ function resolveDomain(Request $request): string
: config('app.sip_domain');
}
function captchaConfigured(): bool
{
return env('NOCAPTCHA_SECRET', false) != false || env('NOCAPTCHA_SITEKEY', false) != false;
}
function resolveUserContacts(Request $request)
{
$selected = ['id', 'username', 'domain', 'activated', 'dtmf_protocol'];

View file

@ -53,6 +53,8 @@ class AccountController extends Controller
public function store(CreateAccountRequest $request)
{
$request->validate(['g-recaptcha-response' => captchaConfigured() ? 'required|captcha': '']);
$account = (new AccountService(api: false))->store($request);
Auth::login($account);

View file

@ -34,7 +34,7 @@ class CreationRequestTokenController extends Controller
'required',
new RulesAccountCreationRequestToken
],
'g-recaptcha-response' => 'required|captcha',
'g-recaptcha-response' => captchaConfigured() ? 'required|captcha' : '',
]);
$accountCreationRequestToken = AccountCreationRequestToken::where('token', $request->get('account_creation_request_token'))->firstOrFail();

View file

@ -34,7 +34,7 @@ class EmailController extends Controller
public function requestChange(Request $request)
{
//$request->validate(['g-recaptcha-response' => 'required|captcha']);
$request->validate(['g-recaptcha-response' => captchaConfigured() ? 'required|captcha': '']);
(new AccountService(api: false))->requestEmailChange($request);

View file

@ -34,7 +34,7 @@ class PhoneController extends Controller
public function requestChange(Request $request)
{
//$request->validate(['g-recaptcha-response' => 'required|captcha']);
$request->validate(['g-recaptcha-response' => captchaConfigured() ? 'required|captcha': '']);
(new AccountService(api: false))->requestPhoneChange($request);

View file

@ -33,7 +33,7 @@ class RecoveryController extends Controller
$rules = [
'email' => 'required_without:phone|email|exists:accounts,email',
'phone' => 'required_without:email|starts_with:+',
//'g-recaptcha-response' => 'required|captcha',
'g-recaptcha-response' => captchaConfigured() ? 'required|captcha' : '',
];
if ($request->get('email')) {

View file

@ -109,7 +109,6 @@ class AccountController extends Controller
]);
$account = Account::findOrFail($id);
$account->username = $request->get('username');
$account->email = $request->get('email');
$account->display_name = $request->get('display_name');
$account->dtmf_protocol = $request->get('dtmf_protocol');
@ -117,7 +116,10 @@ class AccountController extends Controller
$account->save();
$account->phone = $request->get('phone');
if ($request->filled('password') && $request->filled('password_confirmation')) {
$account->fillPassword($request);
}
$account->setRole($request->get('role'));

View file

@ -29,7 +29,6 @@ use Carbon\Carbon;
use App\Account;
use App\AccountTombstone;
use App\AccountCreationToken;
use App\Alias;
use App\Http\Controllers\Account\AuthenticateController as WebAuthenticateController;
use App\Http\Requests\CreateAccountRequest;
@ -37,7 +36,6 @@ use App\Libraries\OvhSMS;
use App\Mail\RegisterConfirmation;
use App\Rules\AccountCreationToken as RulesAccountCreationToken;
use App\Rules\BlacklistedUsername;
use App\Rules\IsNotPhoneNumber;
use App\Rules\NoUppercase;
use App\Rules\SIPUsername;
use App\Rules\WithoutSpaces;

View file

@ -44,7 +44,7 @@ class UpdateAccountRequest extends FormRequest
'phone' => [
'nullable',
Rule::unique('accounts', 'username')->where(function ($query) {
$query->where('domain', config('app.sip_domain'));
$query->where('domain', resolveDomain($this));
})->ignore($this->route('account_id'), 'id'),
Rule::unique('aliases', 'alias')->ignore($this->route('account_id'), 'account_id'),
new WithoutSpaces, 'starts_with:+'

View file

@ -111,6 +111,19 @@ pre {
color: var(--second-7);
}
pre {
overflow: auto;
background-color: var(--second-8);
border-radius: 1rem;
padding: 1rem;
margin-bottom: 1rem;
}
pre code {
color: var(--grey-1);
font-size: 1.3rem;
}
ul li {
margin-left: 2rem;
list-style-type: disc;
@ -138,7 +151,7 @@ p i {
}
code {
color: var(--second-6);
color: var(--second-7);
font-family: monospace;
}
@ -485,6 +498,11 @@ h4 {
padding: 0.5rem 0;
}
p + h1, p + h2, p + h3, p + h4,
ul + h1, ul + h2, ul + h3, ul + h4 {
margin-top: 1rem;
}
/** Badge **/
.badge {
@ -669,3 +687,18 @@ ul.pagination li:not(.disabled) .page-link:hover {
select.list_toggle {
display: none;
}
/** Specific elements */
.table-of-contents {
max-width: 40%;
float: right;
}
.card {
background-color: var(--grey-2);
border-radius: 1rem;
padding: 1rem;
margin-bottom: 1rem;
overflow: hidden;
}

View file

@ -189,6 +189,12 @@ form div textarea[disabled] {
pointer-events: none;
}
form div input[readonly],
form div textarea[readonly] {
border-color: var(--grey-2);
background-color: var(--grey-2);
}
input[type=checkbox] {
accent-color: var(--main-5);
}

View file

@ -22,13 +22,14 @@
<h2>Connexion</h2>
<div>
<input placeholder="Username" required="required" name="username" type="text"
value="{{ $account->username }}">
value="{{ $account->username }}" @if ($account->id) readonly @endif>
<label for="username">Username</label>
@include('parts.errors', ['name' => 'username'])
</div>
<div>
<input placeholder="domain.com" @if (config('app.admins_manage_multi_domains')) required @else disabled @endif name="domain"
type="text" value="{{ $account->domain ?? config('app.sip_domain') }}">
type="text" value="{{ $account->domain ?? config('app.sip_domain') }}"
@if ($account->id) readonly @endif>
<label for="domain">Domain</label>
</div>
@ -40,7 +41,7 @@
<div></div>
<div>
<input placeholder="Password" name="password" type="password" value="">
<input placeholder="Password" name="password" type="password" value="" autocomplete="off">
<label for="password">{{ $account->id ? 'Password (fill to change)' : 'Password' }}</label>
@include('parts.errors', ['name' => 'password'])
</div>
@ -188,13 +189,14 @@
<b>Identifier:</b> {{ $account->externalAccount->identifier }}<br />
</p>
@else
<a class="btn btn-sm @if ($external_accounts_count == 0)disabled @endif" href="{{ route('admin.account.external_account.attach', $account->id) }}">Attach an External Account ({{ $external_accounts_count}} left)</a>
<a class="btn btn-sm @if ($external_accounts_count == 0) disabled @endif"
href="{{ route('admin.account.external_account.attach', $account->id) }}">Attach an External Account
({{ $external_accounts_count }} left)</a>
@endif
<h2>Actions</h2>
@if ($account->dtmf_protocol)
<table class="table">
<tbody>
@foreach ($account->actions as $action)
@ -202,8 +204,10 @@
<th scope="row">{{ $action->key }}</th>
<td>{{ $action->code }}</td>
<td>
<a class="btn btn-sm mr-2" href="{{ route('admin.account.action.edit', [$account, $action->id]) }}">Edit</a>
<a class="btn btn-sm mr-2" href="{{ route('admin.account.action.delete', [$account, $action->id]) }}">Delete</a>
<a class="btn btn-sm mr-2"
href="{{ route('admin.account.action.edit', [$account, $action->id]) }}">Edit</a>
<a class="btn btn-sm mr-2"
href="{{ route('admin.account.action.delete', [$account, $action->id]) }}">Delete</a>
</td>
</tr>
@endforeach
@ -211,7 +215,6 @@
</table>
<a class="btn btn-sm" href="{{ route('admin.account.action.create', $account) }}">Add</a>
@else
<p>To manage actions, you must configure the DTMF protocol in the account settings.</p>
@endif

View file

@ -18,7 +18,7 @@ A `content-type` and `accept` HTTP headers are REQUIRED to use the API properly
Restricted endpoints are protected using a DIGEST authentication or an API Key mechanisms.
#### Access model
### Access model
The endpoints are accessible using three different models:
@ -26,7 +26,7 @@ The endpoints are accessible using three different models:
- <span class="badge badge-info">User</span> the endpoint can only be accessed by an authenticated user
- <span class="badge badge-warning">Admin</span> the endpoint can be only be accessed by an authenticated admin user
#### Using the API Key
### Using the API Key
You can retrieve an API Key from @if (config('app.web_panel')) [your account panel]({{ route('account.login') }}) @else your account panel @endif or using <a href="#get-accountsmeapikey">the dedicated API endpoint</a>.
@ -46,7 +46,7 @@ Or using a cookie:
>
```
#### Using DIGEST
### Using DIGEST
To discover the available hashing algorythm you MUST send an unauthenticated request to one of the restricted endpoints.<br />
Only DIGEST-MD5 and DIGEST-SHA-256 are supported through the authentication layer.

View file

@ -8,14 +8,12 @@
<title>{{ config('app.name') }}</title>
@if (config('instance.custom_theme'))
@if (file_exists(public_path('css/' . config('app.env') . '.style.css')))
<link rel="stylesheet" type="text/css" href="{{ asset('css/' . config('app.env') . '.style.css') }}">
@else
@endif
<script src="{{ asset('scripts/utils.js') }}""></script>
<link rel="stylesheet" type="text/css" href="{{ asset('css/far.css') }}">
<link rel="stylesheet" type="text/css" href="{{ asset('css/form.css') }}">
@if (config('instance.custom_theme') & file_exists(public_path('css/' . config('app.env') . '.style.css')))
<link rel="stylesheet" type="text/css" href="{{ asset('css/' . config('app.env') . '.style.css') }}">
<!--<link rel="stylesheet" type="text/css" href="{{ asset('css/charts.css') }}" >-->
@endif
</head>
@ -24,10 +22,12 @@
<header>
@if (config('app.web_panel'))
<nav>
<a id="logo" href="{{ route('account.home') }}"><span class="on_desktop">{{ config('app.name') }}</span></a>
<a id="logo" href="{{ route('account.home') }}"><span
class="on_desktop">{{ config('app.name') }}</span></a>
@if (!isset($welcome) || $welcome == false)
<a id="menu" class="on_mobile" href="#" onclick="document.body.classList.toggle('show_menu')"></a>
<a id="menu" class="on_mobile" href="#"
onclick="document.body.classList.toggle('show_menu')"></a>
@endif
<a class="oppose" href="{{ route('about') }}">
@ -35,7 +35,8 @@
</a>
@if (auth()->user())
<a class="oppose" href="{{ route('account.dashboard') }}">
<i class="material-icons">account_circle</i><span class="on_desktop">{{ auth()->user()->identifier }}</span>
<i class="material-icons">account_circle</i><span
class="on_desktop">{{ auth()->user()->identifier }}</span>
</a>
<a class="oppose" href="{{ route('account.logout') }}">
<i class="material-icons">logout</i>

View file

@ -1,6 +1,7 @@
@if (captchaConfigured())
<div class="large">
{!! NoCaptcha::renderJs() !!}
{!! NoCaptcha::display() !!}
@include('parts.errors', ['name' => 'g-recaptcha-response'])
</div>
@endif

View file

@ -3,11 +3,12 @@
%define build_number MAKE_FILE_BUILD_NUMBER_SEARCH
%define var_dir /var/opt/belledonne-communications
%define opt_dir /opt/belledonne-communications/share/flexisip-account-manager
%define etc_dir /etc/flexisip-account-manager
%if %{with deb}
%define env_config_file "/etc/flexisip-account-manager/flexiapi.env"
%define env_config_file %{etc_dir}/flexiapi.env
%else
%define env_config_file "$RPM_BUILD_ROOT/etc/flexisip-account-manager/flexiapi.env"
%define env_config_file "$RPM_BUILD_ROOT%{etc_dir}/flexiapi.env"
%endif
%define env_symlink_file %{opt_dir}/flexiapi/.env
@ -33,7 +34,7 @@ License: GPL
URL: http://www.linphone.org
Source0: flexisip-account-manager.tar.gz
Requires: php >= 8.0, php-gd, php-xmlrpc, php-pdo, php-redis, php-mysqlnd, php-mbstring
Requires: php >= 8.0, php-gd, php-pdo, php-redis, php-mysqlnd, php-mbstring
%description
PHP server for Linphone and Flexisip providing module for account creation.
@ -44,15 +45,11 @@ PHP server for Linphone and Flexisip providing module for account creation.
%install
rm -rf "$RPM_BUILD_ROOT"
mkdir -p "$RPM_BUILD_ROOT%{opt_dir}"
cp -R xmlrpc/src/* "$RPM_BUILD_ROOT%{opt_dir}/"
cp -R flexiapi "$RPM_BUILD_ROOT%{opt_dir}"
cp flexiapi/composer.json "$RPM_BUILD_ROOT%{opt_dir}/flexiapi"
cp README* "$RPM_BUILD_ROOT%{opt_dir}/"
mkdir -p "$RPM_BUILD_ROOT/etc/flexisip-account-manager"
cp -R conf/* "$RPM_BUILD_ROOT/etc/flexisip-account-manager/"
mkdir -p $RPM_BUILD_ROOT/etc/cron.daily
mkdir -p $RPM_BUILD_ROOT%{apache_conf_path}
@ -87,12 +84,12 @@ cp httpd/flexisip-account-manager.conf "$RPM_BUILD_ROOT%{apache_conf_path}/"
mkdir -p %{var_dir}/flexiapi/bootstrap/cache
mkdir -p %{var_dir}/log
touch %{var_dir}/log/account-manager.log
chown %{web_user}:%{web_user} %{var_dir}/log/account-manager.log
#touch %{var_dir}/log/account-manager.log
#chown %{web_user}:%{web_user} %{var_dir}/log/account-manager.log
%if %{without deb}
chcon -t httpd_sys_rw_content_t %{var_dir}/log/account-manager.log
%endif
#%if %{without deb}
# chcon -t httpd_sys_rw_content_t %{var_dir}/log/account-manager.log
#%endif
%if %{without deb}
setsebool -P httpd_can_network_connect_db on
@ -110,8 +107,8 @@ cp httpd/flexisip-account-manager.conf "$RPM_BUILD_ROOT%{apache_conf_path}/"
# FlexiAPI env file configuration
if ! test -f %{env_config_file}; then
cd %{opt_dir}/flexiapi/
cp .env.example %{env_config_file}
mkdir -p %{etc_dir}
cp -R .env.example %{env_config_file}
ln -s %{env_config_file} %{env_symlink_file}
php artisan key:generate
@ -138,20 +135,10 @@ fi
%files
%{opt_dir}/flexiapi/
%{opt_dir}/vendor/
%{opt_dir}/api/account/*.php
%{opt_dir}/config/*.php
%{opt_dir}/database/*.php
%{opt_dir}/misc/*.php
%{opt_dir}/objects/*.php
%{opt_dir}/tools/*.php
%{opt_dir}/xmlrpc/*.php
%{opt_dir}/README*
%exclude %{opt_dir}/flexiapi/storage/
%config(noreplace) /etc/flexisip-account-manager/*.conf
%config(noreplace) %{apache_conf_path}/flexisip-account-manager.conf
%if %{with deb}
%config(noreplace) /etc/cron.daily/flexiapi.debian

View file

@ -1,33 +1,4 @@
Alias /flexiapi /opt/belledonne-communications/share/flexisip-account-manager/flexiapi/public
Alias /flexisip-account-manager /opt/belledonne-communications/share/flexisip-account-manager/xmlrpc
<Directory /opt/belledonne-communications/share/flexisip-account-manager/xmlrpc/>
Options FollowSymLinks MultiViews
AllowOverride None
Require all denied
SetEnv FLEXISIP_ACCOUNT_MANAGER_PATH_TO_CONFIG /etc/flexisip-account-manager
<Files activation.php>
<RequireAll>
Require all granted
Require not env blockAccess
</RequireAll>
</Files>
<Files xmlrpc.php>
<RequireAll>
Require all granted
Require not env blockAccess
</RequireAll>
</Files>
<Files provisioning.php>
<RequireAll>
Require all granted
Require not env blockAccess
</RequireAll>
</Files>
</Directory>
<Directory /opt/belledonne-communications/share/flexisip-account-manager/flexiapi/public>
AllowOverride All

View file

@ -1,126 +0,0 @@
## Introduction
Flexisip Account Manager is a software product running on a server, dedicated to the creation and management of SIP accounts from Linphone-based apps.
It supports user identity validation via email or SMS, secure user authentication with SHA-256 digest or TLS client certificates.
Flexisip Account Manager also includes a remote provisioning server for static auto-configuration, compatible with Linphone URL / QR Code provisioning feature.
## License
Flexisip Account Manager is dual licensed, and can be licensed and distributed:
* under an Affero GPLv3 license for free (see LICENSE.txt file for details)
* under a proprietary license, for closed source projects. Contact [Belledonne Communications](https://www.linphone.org/contact) for any question about costs and services.
## Documentation
### Install RPM package with dependencies
Enable Belledonne Communications repository:
```bash
cat > /etc/yum.repos.d/Belledonne.repo << EOF
[Belledonne]
name=Belledonne
baseurl=https://www.linphone.org/snapshots/centos7/
enabled=1
gpgcheck=0
EOF
```
CentOS-SCLo-scl-rh repository is also required for PHP 7.3:
```bash
yum install centos-release-scl-rh
```
RPM package should install necessary dependencies automatically.
```bash
yum install bc-flexisip-account-manager
```
This package depends on `rh-php73` which will be installed in `/opt/rh/rh-php73/`.
If you don't have any other php installed on your server, use the following to be able to use php commands:
```bash
ln -s /opt/rh/rh-php73/root/usr/bin/php /usr/bin/php
```
### Apache server configuration
The RPM will create a `flexisip-account-manager.conf` file inside `/opt/rh/httpd24/root/etc/httpd/conf.d/`
It simply contains an Alias directive, up to you to configure your virtual host correctly.
Once you're done, reload the configuration inside httpd: `service httpd24-httpd reload`
### MySQL database configuration
For the account manager to work, you need a mysql database with a user that has read/write access.
### XMLRPC server configuration
The RPM package has installed the configuration files in `/etc/flexisip-account-manager/`
Each file name should be explicit on which settings it contains. If you have any doubt, leave the default value.
At least you MUST edit the following file and fill the values you used in previous step:
```bash
nano /etc/flexisip-account-manager/db.conf
```
To create the database schema, use the `artisan migrate` script provided by FlexiAPI.
### Email configuration
Flexisip Account Manager is sending email to allow the accounts activations. To allow emails to be sent a few configuration steps are required:
1. Install `sendmail` and `postfix`
2. Set `EMAIL_ENABLED` and `SEND_ACTIVATION_EMAIL` to `true` in the configuration
3. Ensure that postfix is correctly configured (regarding the `relayhost` setting in `main.cf` for example)
### Install OVH SMS gateway dependency (optionnal)
Download and install [composer](https://getcomposer.org/download/) or use the one already provided by your OS.
Then install the `php-ovh-sms` library in the `flexisip-account-manager` directory.
cd /opt/belledonne-communications/share/flexisip-account-manager/
php composer.phar require ovh/php-ovh-sms
### Packaging
To build a rpm package on centos7:
```bash
make rpm
```
To build a rpm package with docker:
```bash
docker run -v $PWD:/home/bc -it gitlab.linphone.org:4567/bc/public/flexisip-account-manager/bc-dev-centos:7 make rpm
```
GitLab is running the command above using `make rpm-dev`, this also install all the required dependencies to run `phpunit` properly (they are disabled by default to save space in the final rpm file).
The flexisip-account-manager rpm package can be found in `rpmbuild/RPMS/x86_64/bc-flexisip-account-manager*.rpm`
### Miscellaneous
- For remote provisioning create a `default.rc` file in `/opt/belledonne-communications/` and set the values you want
client side, set the provisioning uri to the same host but to `provisioning.php` instead of `xmlrpc.php`.
- If SELinux forbids mail sending you can try this command:
`setsebool -P httpd_can_sendmail=1`
- On CentOS firewalld might be running:
`firewall-cmd --state`
- If it is running you can add a rule to allow https traffic:
`firewall-cmd --zone public --permanent --add-port=444/tcp && firewall-cmd --reload`
- If you use the standard https port (443) or http (80) the following command might be better:
`firewall-cmd --zone public --permanent --add-service={http,https} && firewall-cmd --reload`
- Also it can listen on IPv6 only.
To fix that, edit `/opt/rh/httpd24/root/etc/httpd/conf.d/ssl.conf` and add/set: `Listen 0.0.0.0:444 https`

View file

@ -1,90 +0,0 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
include_once __DIR__ . '/../../database/database.php';
include_once __DIR__ . '/../../objects/account.php';
include_once __DIR__ . '/../../objects/password.php';
include_once __DIR__ . '/../../objects/alias.php';
include_once __DIR__ . '/../../misc/utilities.php';
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$data = json_decode(file_get_contents("php://input"));
if ((!empty($data->username) || !empty($data->phone)) && (!empty($data->password) || GENERATE_PASSWORD_ENABLED) && (!empty($data->phone) || !empty($data->email))) {
$account->username = empty($data->username) ? $data->phone : $data->username;
$account->domain = empty($data->domain) ? SIP_DOMAIN : $data->domain;
$account->email = empty($data->email) ? null : $data->email;
$account->activated = AUTO_ACTIVATE_ACCOUNT ? '1' : '0';
$account->confirmation_key = empty($data->phone) ? uniqid() : generate_4_digits_code();
$account->ip_address = getIp();
$account->user_agent = empty($data->user_agent) ? $_SERVER['HTTP_USER_AGENT'] : $data->user_agent;
$account->expire_time = empty($data->expire_time) ? null : $data->expire_time;
if (!$account->getOne()) {
if ($account->create()) {
$password = new Password($db);
$password->account_id = $account->id;
$password->algorithm = empty($data->algorithm) ? 'MD5' : $data->algorithm;
if (GENERATE_PASSWORD_ENABLED) {
$password->password = hash_password($account->username, generate_password(), $account->domain, $password->algorithm);
} else {
$password->password = empty($data->password)
? hash_password($account->username, generate_password(), $account->domain, $password->algorithm)
: $data->password;
}
if (!$password->create()) {
http_response_code(503);
echo json_encode(array("message" => "Unable to create password for account."));
return;
}
if (!empty($data->phone) && $data->phone != $account->username) {
$alias = new Alias($db);
$alias->account_id = $account->id;
$alias->alias = $data->phone;
$alias->domain = $account->domain;
if (!$alias->create()) {
http_response_code(503);
echo json_encode(array("message" => "Unable to create alias for account."));
return;
}
}
http_response_code(201);
echo json_encode(array("message" => "Account was created."));
} else {
http_response_code(503);
echo json_encode(array("message" => "Unable to create account."));
}
} else {
http_response_code(503);
echo json_encode(array("message" => "Account already exists"));
}
} else {
http_response_code(400);
echo json_encode(array("message" => "Unable to create account, data is incomplete."));
}

View file

@ -1,79 +0,0 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
include_once __DIR__ . '/../../database/database.php';
include_once __DIR__ . '/../../objects/account.php';
include_once __DIR__ . '/../../objects/password.php';
include_once __DIR__ . '/../../objects/alias.php';
include_once __DIR__ . '/../../misc/utilities.php';
$logger = Logger::getInstance();
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$data = json_decode(file_get_contents("php://input"));
if (!empty($data->id) || !empty($data->username)) {
if (!empty($data->id)) {
$account->id = $data->id;
} elseif (!empty($data->username)) {
$account->username = $data->username;
if (!empty($data->domain)) {
$account->domain = $data->domain;
}
}
if ($account->getOne()) {
$password = new Password($db);
$password->account_id = $account->id;
$alias = new Alias($db);
$alias->account_id = $account->id;
if ($account->delete()) {
if (!$password->delete()) {
$logger->error("Failed to delete password(s) for account id " . $password->account_id);
}
if ($alias->getOne()) {
if (!$alias->delete()) {
$logger->error("Failed to delete alias for account id " . $alias->account_id);
}
}
http_response_code(200);
echo json_encode(array("message" => "Account was deleted."));
} else {
http_response_code(503);
echo json_encode(array("message" => "Unable to delete account."));
}
} else {
http_response_code(404);
echo json_encode(array("message" => "Account doesn't exist"));
}
} else {
http_response_code(400);
echo json_encode(array("message" => "Unable to delete account, data is incomplete."));
}

View file

@ -1,70 +0,0 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
include_once __DIR__ . '/../../database/database.php';
include_once __DIR__ . '/../../objects/account.php';
include_once __DIR__ . '/../../objects/password.php';
include_once __DIR__ . '/../../objects/alias.php';
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$account->id = isset($_GET['id']) ? $_GET['id'] : null;
$account->username = isset($_GET['username']) ? $_GET['username'] : null;
$account->domain = isset($_GET['domain']) ? $_GET['domain'] : null;
$account->getOne();
if (!empty($account->id) && !empty($account->username) && !empty($account->domain)) {
$account_item = array(
"id" => $account->id,
"username" => $account->username,
"domain" => $account->domain,
"activated" => $account->activated,
"alias" => $account->alias,
"passwords" => array()
);
$pwd = new Password($db);
$pwd->account_id = $account->id;
$stmt = $pwd->getAll();
$num = $stmt->rowCount();
if ($num > 0) {
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
extract($row);
$password_item = array(
"id" => $id,
"password" => $password,
"algorithm" => $algorithm
);
$account_item["passwords"][$algorithm] = $password_item;
}
}
http_response_code(200);
echo json_encode($account_item);
} else {
http_response_code(404);
echo json_encode(array("message" => "Account doesn't exist"));
}

View file

@ -1,54 +0,0 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
include_once __DIR__ . '/../../database/database.php';
include_once __DIR__ . '/../../objects/account.php';
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$stmt = $account->getAll();
$num = $stmt->rowCount();
if ($num > 0) {
$accounts = array();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
extract($row);
$account_item = array(
"id" => $id,
"username" => $username,
"domain" => $domain,
"activated" => $activated,
"alias" => $alias
);
array_push($accounts, $account_item);
}
http_response_code(200);
echo json_encode($accounts);
} else {
http_response_code(404);
echo json_encode(array("message" => "No account found"));
}

View file

@ -1,106 +0,0 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
include_once __DIR__ . '/../../database/database.php';
include_once __DIR__ . '/../../objects/account.php';
include_once __DIR__ . '/../../objects/password.php';
include_once __DIR__ . '/../../objects/alias.php';
include_once __DIR__ . '/../../misc/utilities.php';
$logger = Logger::getInstance();
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$data = json_decode(file_get_contents("php://input"));
if (!empty($data->id) || !empty($data->username)) {
if (!empty($data->id)) {
$account->id = $data->id;
} elseif (!empty($data->username)) {
$account->username = $data->username;
if (!empty($data->domain)) {
$account->domain = $data->domain;
}
}
if ($account->getOne()) {
$account->username = empty($data->username) ? $data->phone : $data->username;
$account->domain = empty($data->domain) ? SIP_DOMAIN : $data->domain;
$account->email = empty($data->email) ? null : $data->email;
$account->activated = is_activated($data->activated) ? "1" : "0";
$password = new Password($db);
$password->account_id = $account->id;
$alias = new Alias($db);
$alias->account_id = $account->id;
if ($account->update()) {
if (!empty($data->password)) {
$password->algorithm = empty($data->algorithm) ? 'MD5' : $data->algorithm;
$getOne = $password->getOne();
// Wait after getOne as it will override data if found
$password->password = $data->password;
if ($getOne) {
if (!$password->update()) {
$logger->error("Failed to update password for account id " . $alias->account_id);
}
} else {
if (!$password->create()) {
$logger->error("Failed to create password for account id " . $alias->account_id);
}
}
}
if (!empty($data->phone)) {
$getOne = $alias->getOne();
// Wait after getOne as it will override data if found
$alias->alias = $data->phone;
$alias->domain = $account->domain;
if ($getOne) {
if (!$alias->update()) {
$logger->error("Failed to update alias for account id " . $alias->account_id);
}
} else {
if (!$alias->create()) {
$logger->error("Failed to create alias for account id " . $alias->account_id);
}
}
}
http_response_code(200);
echo json_encode(array("message" => "Account was updated."));
} else {
http_response_code(503);
echo json_encode(array("message" => "Unable to update account."));
}
} else {
http_response_code(404);
echo json_encode(array("message" => "Account doesn't exist"));
}
} else {
http_response_code(400);
echo json_encode(array("message" => "Unable to update account, data is incomplete."));
}

View file

@ -1,5 +0,0 @@
{
"require": {
"ovh/php-ovh-sms": "^1.0"
}
}

349
xmlrpc/src/composer.lock generated
View file

@ -1,349 +0,0 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "987e4b2962ecdd694c90a315d8b7d84a",
"packages": [
{
"name": "guzzlehttp/guzzle",
"version": "5.3.4",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "b87eda7a7162f95574032da17e9323c9899cb6b2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/b87eda7a7162f95574032da17e9323c9899cb6b2",
"reference": "b87eda7a7162f95574032da17e9323c9899cb6b2",
"shasum": ""
},
"require": {
"guzzlehttp/ringphp": "^1.1",
"php": ">=5.4.0",
"react/promise": "^2.2"
},
"require-dev": {
"ext-curl": "*",
"phpunit/phpunit": "^4.0"
},
"type": "library",
"autoload": {
"psr-4": {
"GuzzleHttp\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
}
],
"description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients",
"homepage": "http://guzzlephp.org/",
"keywords": [
"client",
"curl",
"framework",
"http",
"http client",
"rest",
"web service"
],
"support": {
"issues": "https://github.com/guzzle/guzzle/issues",
"source": "https://github.com/guzzle/guzzle/tree/5.3"
},
"time": "2019-10-30T09:32:00+00:00"
},
{
"name": "guzzlehttp/ringphp",
"version": "1.1.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/RingPHP.git",
"reference": "5e2a174052995663dd68e6b5ad838afd47dd615b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/RingPHP/zipball/5e2a174052995663dd68e6b5ad838afd47dd615b",
"reference": "5e2a174052995663dd68e6b5ad838afd47dd615b",
"shasum": ""
},
"require": {
"guzzlehttp/streams": "~3.0",
"php": ">=5.4.0",
"react/promise": "~2.0"
},
"require-dev": {
"ext-curl": "*",
"phpunit/phpunit": "~4.0"
},
"suggest": {
"ext-curl": "Guzzle will use specific adapters if cURL is present"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.1-dev"
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Ring\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
}
],
"description": "Provides a simple API and specification that abstracts away the details of HTTP into a single PHP function.",
"support": {
"issues": "https://github.com/guzzle/RingPHP/issues",
"source": "https://github.com/guzzle/RingPHP/tree/1.1.1"
},
"abandoned": true,
"time": "2018-07-31T13:22:33+00:00"
},
{
"name": "guzzlehttp/streams",
"version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/streams.git",
"reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/streams/zipball/47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5",
"reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5",
"shasum": ""
},
"require": {
"php": ">=5.4.0"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Stream\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
}
],
"description": "Provides a simple abstraction over streams of data",
"homepage": "http://guzzlephp.org/",
"keywords": [
"Guzzle",
"stream"
],
"support": {
"issues": "https://github.com/guzzle/streams/issues",
"source": "https://github.com/guzzle/streams/tree/master"
},
"abandoned": true,
"time": "2014-10-12T19:18:40+00:00"
},
{
"name": "ovh/ovh",
"version": "v1.1.2",
"source": {
"type": "git",
"url": "https://github.com/ovh/php-ovh.git",
"reference": "efd770390a3fe9b91c31c9f3a205f4023f75d161"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ovh/php-ovh/zipball/efd770390a3fe9b91c31c9f3a205f4023f75d161",
"reference": "efd770390a3fe9b91c31c9f3a205f4023f75d161",
"shasum": ""
},
"require": {
"guzzlehttp/guzzle": ">=4.0,<6.0"
},
"require-dev": {
"phpdocumentor/phpdocumentor": "2.*",
"phpunit/phpunit": "4.*",
"squizlabs/php_codesniffer": "1.*"
},
"type": "library",
"autoload": {
"psr-4": {
"Ovh\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Vincent Cassé"
}
],
"description": "Wrapper for OVH APIs",
"support": {
"issues": "https://github.com/ovh/php-ovh/issues",
"source": "https://github.com/ovh/php-ovh/tree/master"
},
"time": "2015-12-16T10:34:19+00:00"
},
{
"name": "ovh/php-ovh-sms",
"version": "1.0",
"source": {
"type": "git",
"url": "https://github.com/ovh/php-ovh-sms.git",
"reference": "96fb25947d30b6dac58c87638e09799870a4841c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ovh/php-ovh-sms/zipball/96fb25947d30b6dac58c87638e09799870a4841c",
"reference": "96fb25947d30b6dac58c87638e09799870a4841c",
"shasum": ""
},
"require": {
"ovh/ovh": "~1.1.1"
},
"require-dev": {
"phpdocumentor/phpdocumentor": "2.*",
"phpunit/phpunit": "4.*",
"squizlabs/php_codesniffer": "1.*"
},
"type": "library",
"autoload": {
"psr-0": {
"Ovh\\Sms\\": "src/"
},
"psr-4": {
"Ovh\\Sms\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "SDK for OVH SMS APIs",
"support": {
"issues": "https://github.com/ovh/php-ovh-sms/issues",
"source": "https://github.com/ovh/php-ovh-sms/tree/master"
},
"time": "2016-07-13T14:41:35+00:00"
},
{
"name": "react/promise",
"version": "v2.9.0",
"source": {
"type": "git",
"url": "https://github.com/reactphp/promise.git",
"reference": "234f8fd1023c9158e2314fa9d7d0e6a83db42910"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/reactphp/promise/zipball/234f8fd1023c9158e2314fa9d7d0e6a83db42910",
"reference": "234f8fd1023c9158e2314fa9d7d0e6a83db42910",
"shasum": ""
},
"require": {
"php": ">=5.4.0"
},
"require-dev": {
"phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.36"
},
"type": "library",
"autoload": {
"files": [
"src/functions_include.php"
],
"psr-4": {
"React\\Promise\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jan Sorgalla",
"email": "jsorgalla@gmail.com",
"homepage": "https://sorgalla.com/"
},
{
"name": "Christian Lück",
"email": "christian@clue.engineering",
"homepage": "https://clue.engineering/"
},
{
"name": "Cees-Jan Kiewiet",
"email": "reactphp@ceesjankiewiet.nl",
"homepage": "https://wyrihaximus.net/"
},
{
"name": "Chris Boden",
"email": "cboden@gmail.com",
"homepage": "https://cboden.dev/"
}
],
"description": "A lightweight implementation of CommonJS Promises/A for PHP",
"keywords": [
"promise",
"promises"
],
"support": {
"issues": "https://github.com/reactphp/promise/issues",
"source": "https://github.com/reactphp/promise/tree/v2.9.0"
},
"funding": [
{
"url": "https://github.com/WyriHaximus",
"type": "github"
},
{
"url": "https://github.com/clue",
"type": "github"
}
],
"time": "2022-02-11T10:27:51+00:00"
}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": [],
"plugin-api-version": "2.3.0"
}

View file

@ -1,38 +0,0 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
$path = isset($_SERVER['FLEXISIP_ACCOUNT_MANAGER_PATH_TO_CONFIG']) ? $_SERVER['FLEXISIP_ACCOUNT_MANAGER_PATH_TO_CONFIG'] : "/etc/flexisip-account-manager";
define("FLEXISIP_ACCOUNT_MANAGER_PATH_TO_CONFIG", $path);
include_once FLEXISIP_ACCOUNT_MANAGER_PATH_TO_CONFIG . '/accounts.conf';
include_once FLEXISIP_ACCOUNT_MANAGER_PATH_TO_CONFIG . '/auth.conf';
include_once FLEXISIP_ACCOUNT_MANAGER_PATH_TO_CONFIG . '/db.conf';
include_once FLEXISIP_ACCOUNT_MANAGER_PATH_TO_CONFIG . '/emails.conf';
include_once FLEXISIP_ACCOUNT_MANAGER_PATH_TO_CONFIG . '/inapp.conf';
include_once FLEXISIP_ACCOUNT_MANAGER_PATH_TO_CONFIG . '/logs.conf';
include_once FLEXISIP_ACCOUNT_MANAGER_PATH_TO_CONFIG . '/provisioning.conf';
include_once FLEXISIP_ACCOUNT_MANAGER_PATH_TO_CONFIG . '/sms.conf';
include_once FLEXISIP_ACCOUNT_MANAGER_PATH_TO_CONFIG . '/tests.conf';
// these two might include some of the scripts from the installation, so keep them last
include_once FLEXISIP_ACCOUNT_MANAGER_PATH_TO_CONFIG . '/hooks.conf';
include_once FLEXISIP_ACCOUNT_MANAGER_PATH_TO_CONFIG . '/overloads.conf';
?>

View file

@ -1,56 +0,0 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
include_once __DIR__ . '/../config/config.php';
include_once __DIR__ . '/../misc/logging.php';
include_once __DIR__ . '/../misc/utilities.php';
class Database
{
public $conn;
public function getConnection()
{
$this->conn = null;
try {
if(!empty(get_config_value("DB_ENABLE_SSL","")) && !empty(get_config_value("ROOT_CA_PATH",""))){
if(!file_exists (ROOT_CA_PATH)){
Logger::getInstance()->error("MySQL connection error: the provided ROOT_CA_PATH does not exists!");
}
else{
$this->conn = new PDO("mysql:host=" . DB_HOST . ";dbname=" . DB_NAME, DB_USER, DB_PASSWORD, array (
PDO::MYSQL_ATTR_SSL_CA => ROOT_CA_PATH,
PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => false
));
}
}
else{
$this->conn = new PDO("mysql:host=" . DB_HOST . ";dbname=" . DB_NAME, DB_USER, DB_PASSWORD);
}
$this->conn->prepare("set names utf8mb4 collate utf8mb4_unicode_ci")->execute();
} catch (PDOException $exception) {
Logger::getInstance()->error("Connection error: " . $exception->getMessage());
}
return $this->conn;
}
}

View file

@ -1,111 +0,0 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
include_once __DIR__ . '/../config/config.php';
include_once __DIR__ . '/../misc/logging.php';
function send_email($email, $subject, $text, $html)
{
$site = EMAIL_SITE;
$from = EMAIL_FROM_ADDR;
$name = EMAIL_FROM_NAME;
$to = $email;
$from = $name." <".$from.">";
$limite = "_----------=_parties_".md5(uniqid(rand()));
$headers = "Reply-to: ".$from."\n";
$headers .= "From: ".$from."\n";
$headers .= "Return-Path: ".$from."\n";
$headers .= "X-Sender: <".$site.">\n";
$headers .= "X-Mailer: PHP\n";
$headers .= "X-auth-smtp-user: ".$from." \n";
$headers .= "X-abuse-contact: ".$from." \n";
$headers .= "X-auth-smtp-user: ".$from." \n";
$headers .= "X-abuse-contact: ".$from." \n";
$headers .= "Date: ".date("D, j M Y G:i:s O")."\n";
$headers .= "MIME-Version: 1.0\n";
$headers .= "Content-Type: multipart/alternative; boundary=\"".$limite."\"";
$message = "";
$message .= "--".$limite."\n";
$message .= "Content-Type: text/plain; charset=\"utf-8\"\n";
$message .= "Content-Transfer-Encoding: 8bit\n\n";
$message .= $text;
$message .= "\n\n--".$limite."\n";
$message .= "Content-Type: text/html; charset=\"utf-8\"\n";
$message .= "Content-Transfer-Encoding: 8bit;\n\n";
$message .= $html;
$message .= "\n--".$limite."--";
$params = "-f" . EMAIL_FROM_ADDR . " -O DeliveryMode=b";
$result = mail($email, $subject, $message, $headers, $params);
if (!$result) {
Logger::getInstance()->error("[EMAIL] Email delivery declined !");
}
}
function send_email_with_activation_link($email, $key, $username, $domain, $algo)
{
if (!EMAIL_ENABLED) {
Logger::getInstance()->warning("[EMAIL] Emails are disabled");
return "WARNING_EMAILS_DISABLED";
}
$pageURL = 'http';
if ($_SERVER["HTTPS"] == "on") {
$pageURL .= "s";
}
$pageURL .= "://";
$link = $pageURL . EMAIL_ACTIVATION_LINK;
$link = str_replace("%key%", $key, $link);
$link = str_replace("%username%", $username, $link);
$link = str_replace("%domain%", $domain, $link);
$link = str_replace("%algo%", $algo, $link);
Logger::getInstance()->debug("[EMAIL] Activation link is " . $link);
$body = str_replace("%link%", $link, EMAIL_ACTIVATION_BODY);
Logger::getInstance()->debug("[EMAIL] Activation body is " . $body);
$body_html = str_replace("%link%", $link, EMAIL_ACTIVATION_BODY_HTML);
Logger::getInstance()->debug("[EMAIL] Activation html body is " . $body_html);
send_email($email, EMAIL_ACTIVATION_SUBJECT, $body, $body_html);
Logger::getInstance()->message("[EMAIL] Email sent to email " . $email . " to activate the account");
}
function send_email_with_recover_key($email, $key)
{
if (!EMAIL_ENABLED) {
Logger::getInstance()->warning("[EMAIL] Emails are disabled");
return "WARNING_EMAILS_DISABLED";
}
$body = str_replace("%key%", $key, EMAIL_RECOVERY_BODY);
Logger::getInstance()->debug("[EMAIL] Recovery body is " . $body);
$body_html = str_replace("%key%", $key, EMAIL_RECOVERY_BODY_HTML);
Logger::getInstance()->debug("[EMAIL] Recovery html body is " . $body_html);
send_email($email, EMAIL_RECOVERY_SUBJECT, $body, $body_html);
Logger::getInstance()->message("[EMAIL] Email sent to email " . $email . " to recover the account");
}

View file

@ -1,61 +0,0 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
include_once __DIR__ . '/../config/config.php';
class Geoloc
{
public static function getGeolocInfosFromIp($ip_address)
{
if ($ip_address == "::1" || $ip_address == "127.0.0.1" || $ip_address == "localhost") {
$service_url = 'https://ipecho.net/plain';
$curl = curl_init($service_url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$curl_response = curl_exec($curl);
if ($curl_response === false) {
$info = curl_getinfo($curl);
curl_close($curl);
Logger::getInstance()->error('Error occured during curl exec (getting public ip of server). Additionnal info: ' . var_export($info));
return false;
} else {
Logger::getInstance()->debug("Getting external public ip from ipecho.net= " . $curl_response);
$ip_address = $curl_response;
}
curl_close($curl);
}
$service_url = 'http://api.ipapi.com/' . $ip_address .'?access_key='. GEOLOC_ACCESS_KEY .'&fields=country_code,country_name';
Logger::getInstance()->debug("Getting geoloc infos for ip after parse if=" . $ip_address);
Logger::getInstance()->debug("Geoloc url = " . $service_url);
$curl = curl_init($service_url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$curl_response = curl_exec($curl);
if ($curl_response === false) {
$info = curl_getinfo($curl);
curl_close($curl);
Logger::getInstance()->error('Error occured during curl exec (geoloc). Additionnal info: ' . var_export($info));
return false;
}
curl_close($curl);
Logger::getInstance()->debug('geoloc, curl response : ' . $curl_response);
$decoded = json_decode($curl_response);
return $decoded;
}
}

View file

@ -1,133 +0,0 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
include_once __DIR__ . '/../config/config.php';
class Logger
{
private static $instance = null;
private $log_file;
public function __construct()
{
if (!LOGS_ENABLED) {
return;
}
if (USE_ONE_LOG_FILE) {
$this->log_file = LOG_FILE;
} else {
if (!file_exists(LOG_DIR)) {
mkdir(LOG_DIR, 0777, true);
}
$this->log_file = LOG_DIR . "/" . date('d-M-Y') . '.logs';
}
}
public static function getInstance()
{
if (!self::$instance) {
self::$instance = new Logger();
}
return self::$instance;
}
private function mylog($level, $message)
{
if (!LOGS_ENABLED) {
return;
}
if (is_array($message)) {
$message = implode(" ", $message);
}
$now = getdate();
$month = sprintf("%02d", $now["mon"]);
$day = sprintf("%02d", $now["mday"]);
$hours = sprintf("%02d", $now["hours"]);
$minutes = sprintf("%02d", $now["minutes"]);
$seconds = sprintf("%02d", $now["seconds"]);
$log_msg = "[" . $day . "/" . $month . "/" . $now["year"] . " " . $hours . ":" . $minutes . ":" . $seconds . "] [" . $level . "] " . $message . "\r\n";
file_put_contents($this->log_file, $log_msg, FILE_APPEND);
}
public function error($message)
{
$this->mylog("Error", $message);
}
public function warning($message)
{
$this->mylog("Warning", $message);
}
public function message($message)
{
$this->mylog("Message", $message);
}
public function debug($message)
{
$this->mylog("Debug", $message);
}
}
function systemErrorHandler($errno, string $errstr, string $errfile = '', int $errline = 0, $trace = '')
{
if (\is_array($trace)) $trace = '';
$error = $errstr . " in " . $errfile . ' (line ' . $errline . ")\n";
$fullError = $error . 'Trace' . "\n" . $trace;
Logger::getInstance()->debug($fullError);
return false;
}
function exceptionHandler($exception)
{
systemErrorHandler(
E_ERROR,
get_class($exception) . ': '. $exception->getMessage(),
$exception->getFile(),
$exception->getLine(),
$exception->getTraceAsString()
);
}
function fatalErrorShutdownHandler()
{
$lastError = error_get_last();
if ($lastError && $lastError['type'] === E_ERROR) {
systemErrorHandler(
E_ERROR,
$lastError['message'],
$lastError['file'],
$lastError['line']
);
}
}
set_error_handler('systemErrorHandler', E_ALL);
set_exception_handler('exceptionHandler');
register_shutdown_function('fatalErrorShutdownHandler');

View file

@ -1,84 +0,0 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define("OK", "OK");
define("NOK", "NOK");
define("OK_ALIAS", "OK_ALIAS");
define("OK_ACCOUNT", "OK_ACCOUNT");
/* Parameter related */
define("MISSING_PHONE_PARAM", "ERROR_PHONE_PARAMETER_NOT_FOUND");
define("MISSING_USERNAME_PARAM", "ERROR_USERNAME_PARAMETER_NOT_FOUND");
define("MISSING_EMAIL_PARAM", "ERROR_EMAIL_PARAMETER_NOT_FOUND");
define("MISSING_OLD_HASH", "ERROR_OLD_HASH_NOT_FOUND");
define("MISSING_NEW_HASH", "ERROR_NEW_HASH_NOT_FOUND");
define("MISSING_MD5_HASH", "ERROR_MD5_HASH_NOT_FOUND");
define("MISSING_SHA256_HASH", "ERROR_SHA256_HASH_NOT_FOUND");
define("EMAIL_UNCHANGED", "ERROR_EMAIL_NEW_SAME_AS_OLD");
/* Parameter not available because already in use */
define("PHONE_TAKEN", "ERROR_ALIAS_ALREADY_IN_USE");
define("USERNAME_TAKEN", "ERROR_ACCOUNT_ALREADY_IN_USE");
define("EMAIL_TAKEN", "ERROR_EMAIL_ALREADY_IN_USE");
/* Object not found */
define("ALIAS_NOT_FOUND", "ERROR_ALIAS_DOESNT_EXIST");
define("ACCOUNT_NOT_FOUND", "ERROR_ACCOUNT_DOESNT_EXIST");
define("PASSWORD_NOT_FOUND", "ERROR_PASSWORD_NOT_FOUND");
define("USERINFO_NOT_FOUND", "ERROR_USERINFO_NOT_FOUND");
/* Equality check failure */
define("KEY_DOESNT_MATCH", "ERROR_KEY_DOESNT_MATCH");
define("PASSWORD_DOESNT_MATCH", "ERROR_PASSWORD_DOESNT_MATCH");
define("EMAIL_DOESNT_MATCH", "ERROR_EMAIL_DOESNT_MATCH");
define("ALIAS_DOESNT_MATCH", "ERROR_ALIAS_DOESNT_MATCH");
/* Disabled features */
define("TEST_ACCOUNTS_DISABLED", "ERROR_NON_TEST_ACCOUNTS_UNAUTHORIZED");
define("SMS_DISABLED", "ERROR_SMS_API_DISABLED");
define("ALGO_NOT_SUPPORTED", "ERROR_ALGO_NOT_SUPPORTED");
/* Unexpected state */
define("ACCOUNT_ALREADY_ACTIVATED", "ERROR_ACCOUNT_ALREADY_ACTIVATED");
define("ACCOUNT_NOT_YET_ACTIVATED", "ERROR_ACCOUNT_NOT_ACTIVATED");
define("ACCOUNT_RECOVERY_IMPOSSIBLE", "ERROR_CANT_RECOVER_ACCOUNT");
/* Format error */
define("PHONE_NOT_E164", "ERROR_PHONE_ISNT_E164");
/* SMS error */
define("MAX_SMS_ALLOWED_EXCEEDED", "ERROR_MAX_SMS_EXCEEDED");
define("SMS_API_FAILURE", "ERROR_CANT_SEND_SMS");
/* Geoloc error */
define("GEOLOC_FAILED", "ERROR_GEOLOC_FAILED");
/* Other error */
define('SHA256_PASSWORD_ALREADY_EXISTS', 'ERROR_SHA256_PASSWORD_ALREADY_EXISTS');

View file

@ -1,181 +0,0 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// The following can't be put inside a function...
// So comment it out if not using the OVH SMS API
require __DIR__ . '/../vendor/autoload.php';
use \Ovh\Sms\SmsApi;
include_once __DIR__ . '/../database/database.php';
include_once __DIR__ . '/../objects/sms.php';
include_once __DIR__ . '/../misc/logging.php';
include_once __DIR__ . '/results_values.php';
include_once __DIR__ . '/utilities.php';
// Internationalization
function get_sms_string_for_lang($lang)
{
global $SMS_OVH_TEMPLATE;
if (isset($SMS_OVH_TEMPLATE[$lang])) {
return $SMS_OVH_TEMPLATE[$lang];
}
Logger::getInstance()->warning("SMS template not found for lang " . $lang . ", using US template");
return SMS_OVH_US_TEMPLATE;
}
// SMS API
function send_sms_ovh($phone, $key, $lang)
{
if (!SMS_API_ENABLED) {
Logger::getInstance()->warning("[SMS] SMS API disabled");
return SMS_DISABLED;
}
$sms = new SmsApi(SMS_OVH_API_KEY, SMS_OVH_API_SECRET, SMS_OVH_ENDPOINT, SMS_OVH_CONSUMER_KEY);
$accounts = $sms->getAccounts();
$sms->setAccount($accounts[0]);
if (SMS_USE_SENDER) {
$senders = $sms->getSenders();
/* The account must be validated in the OVH interface and by OVH itself */
if (count($senders) == 0) {
Logger::getInstance()->warning("[SMS] No sender found, creating one " . SMS_OVH_SENDER . " / " . SMS_OVH_REASON . " : " . SMS_OVH_DESC);
$sms->addSender(SMS_OVH_SENDER, SMS_OVH_REASON, SMS_OVH_DESC);
$senders = $sms->getSenders();
}
}
$message = $sms->createMessage();
if (SMS_USE_SENDER && count($senders) > 0) {
foreach ($senders as $sender) {
if ($sender == SMS_OVH_SENDER) {
if ($sms->checkSender($sender)) {
// Check if sender exists and is valid, otherwise it will create an exception and sms won't be sent
Logger::getInstance()->message("[SMS] Found valid sender " . $sender . ", using it");
$message->setSender($sender);
break;
} else {
Logger::getInstance()->error("[SMS] Found sender " . $sender . " but it is not valid");
}
}
}
}
$message->addReceiver($phone);
$message->setIsMarketing(false);
$text = get_sms_string_for_lang($lang);
$text = str_replace("#CODE#", $key, $text);
$result = $message->send($text);
$credits_removed = $result['totalCreditsRemoved'];
Logger::getInstance()->message("[SMS] " . $credits_removed . " credit removed");
$invalid_receiver = $result['invalidReceivers'];
$valid_receiver = $result['validReceivers'];
if (count($invalid_receiver) > 0) {
Logger::getInstance()->error("[SMS] phone number " . $phone . " seems invalid");
} elseif (count($valid_receiver) > 0) {
Logger::getInstance()->message("[SMS] " . $text . " sent to " . $phone);
} else {
Logger::getInstance()->warning("[SMS] Both valid and invalid receiver lists are empty...");
}
}
function send_sms_legacy($phone, $password)
{
if (!SMS_API_ENABLED) {
Logger::getInstance()->warning("[SMS] SMS API disabled");
return SMS_DISABLED;
}
$url = SMS_API_URL;
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FAILONERROR, false);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_USERPWD, SMS_API_USERNAME . ":" . SMS_API_PASSWORD);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/x-www-form-urlencoded'
));
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(array(
'mobile' => $phone,
'password' => $password,
)));
$result = curl_exec($ch);
Logger::getInstance()->message("[SMS] SMS confirmation sent to " . $phone . " using password " . $password . ", request result is " . $result);
curl_close($ch);
}
function send_sms($phone, $key, $lang)
{
if (!SMS_API_ENABLED) {
Logger::getInstance()->warning("[SMS] SMS API disabled");
return SMS_DISABLED;
}
if (startswith($phone, TESTS_PHONE_PREFIX)) {
Logger::getInstance()->error("[SMS] Not sending sms to fake number used for tests purposes: " . $phone);
return TEST_ACCOUNTS_DISABLED;
}
$now_date = new DateTime('now');
$now = $now_date->getTimestamp() * 1000;
$database = new Database();
$db = $database->getConnection();
$sms = new SMS($db);
$sms->phone = $phone;
if ($sms->getOne()) {
$diff = $now - $sms->last_sms;
if ($sms->count >= SMS_COUNT_LIMIT_IN_PERIOD and $diff < SMS_TIME_PERIOD) {
Logger::getInstance()->error("[SMS] Last sms was sent at " . $sms->last_sms . ", time elapsed since then is " . $diff . "ms which is less than the configured time period " . SMS_TIME_PERIOD);
return MAX_SMS_ALLOWED_EXCEEDED;
} elseif ($diff >= SMS_TIME_PERIOD) {
$sms->last_sms = $now;
$sms->count = 1;
$sms->update();
} else {
$sms->count = $sms->count + 1;
$sms->update();
}
} else {
$sms->last_sms = $now;
$sms->count = 1;
$sms->create();
}
if (SMS_OVH_API_KEY != null && SMS_OVH_API_KEY != "" && SMS_OVH_API_SECRET != null && SMS_OVH_API_SECRET != "" && SMS_OVH_CONSUMER_KEY != null && SMS_OVH_CONSUMER_KEY != "" && SMS_OVH_ENDPOINT != null && SMS_OVH_ENDPOINT != "") {
try {
send_sms_ovh($phone, $key, $lang);
return OK;
} catch (Exception $e) {
Logger::getInstance()->error("[OVH-SMS] Exception: " . $e->getMessage());
}
} elseif (SMS_API_URL != null && SMS_API_URL != "" && SMS_API_USERNAME != null && SMS_API_USERNAME != "" && SMS_API_PASSWORD != null && SMS_API_PASSWORD != "") {
send_sms_legacy($phone, $key);
return OK;
} else {
Logger::getInstance()->error("[SMS] No SMS API configured, discarding sms...");
return OK;
}
return SMS_API_FAILURE;
}

View file

@ -1,76 +0,0 @@
<?php
include_once __DIR__ . '/../database/database.php';
include_once __DIR__ . '/../objects/account.php';
include_once __DIR__ . '/../objects/password.php';
include_once __DIR__ . '/../objects/alias.php';
include_once __DIR__ . '/../objects/user_info.php';
include_once __DIR__ . '/utilities.php';
include_once __DIR__ . '/geoloc.php';
include_once __DIR__ . '/results_values.php';
// args = [username, ha1, firstname, lastname, gender, subscribe, [domain], [algo]]
function update_account_user_info($username, $ha1, $firstname, $lastname, $gender, $subscribe, $domain, $algo)
{
Logger::getInstance()->message("update_account_user_info(" . $username . ", " . $domain . " : " . $firstname . ", " . $lastname . ", " . $gender . ", " . $subscribe . ")");
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$account->username = $username;
$account->domain = $domain;
if (!$account->getOne()) {
return ACCOUNT_NOT_FOUND;
}
Logger::getInstance()->debug("userInfo : Account after get one " . $account);
$password = new Password($db);
$password->account_id = $account->id;
$password->algorithm = $algo;
if (!$password->getOne()) {
return PASSWORD_NOT_FOUND;
}
if (!password_match($ha1, $password->password)) {
return PASSWORD_DOESNT_MATCH;
}
$user_info = new UserInfo($db);
$user_info->account_id = $account->id;
if (get_config_value("ENABLE_NEW_ACCOUNTS_GEOLOC", FALSE)) {
Logger::getInstance()->debug("userInfo : Account ip after enable geoloc if " . $account->ip_address);
$country_infos = Geoloc::getGeolocInfosFromIp($account->ip_address);
if ($country_infos) {
$user_info->country_code = $country_infos->country_code;
$user_info->country_name = $country_infos->country_name;
}
//error message is displayed from geoloc method.
else {
return GEOLOC_FAILED;
}
Logger::getInstance()->debug("Getting geoloc infos : country_code=".
$country_infos->country_code . ' country_name=' . $country_infos->country_name);
}
$update = $user_info->getOne();
$user_info->firstname = $firstname;
$user_info->lastname = $lastname;
$user_info->gender = $gender;
$user_info->subscribe = $subscribe;
if ($update) {
$user_info->update();
} else {
$user_info->create();
}
return OK;
}

View file

@ -1,200 +0,0 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
include_once __DIR__ . '/../config/config.php';
include_once __DIR__ . '/../objects/account.php';
include_once __DIR__ . '/logging.php';
if (EMAIL_ENABLED) {
include_once __DIR__ . '/email.php';
}
if (SMS_API_ENABLED) {
include_once __DIR__ . '/sms.php';
}
define('CLEAR', 'clrtxt');
define('MD5', 'MD5');
define('SHA256', 'SHA-256');
function startswith($hay, $needle)
{
return substr($hay, 0, strlen($needle)) === $needle;
}
function endswith($hay, $needle)
{
return $needle === "" || (($temp = strlen($hay) - strlen($needle)) >= 0 and strpos($hay, $needle, $temp) !== false);
}
function getIp()
{
$ip = $_SERVER['REMOTE_ADDR'];
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
}
return $ip;
}
function get_trial_expiration_date()
{
$expiration_date = new DateTime('now +' . TRIAL_DURATION_DAYS . ' days');
$expiration = $expiration_date->getTimestamp() * 1000;
return $expiration;
}
function is_activated($activated)
{
return $activated == "1";
}
// XMLRPC parameters
function check_parameter($param, $param_name = "username")
{
if ($param == null || $param == "") {
Logger::getInstance()->warning("Parameter " . $param_name . " is missing");
return false;
}
return true;
}
function get_algo($algo)
{
if ($algo == null || $algo == "") {
Logger::getInstance()->warning("Algo parameter wasn't found, assume " . DEFAULT_ALGORITHM);
return DEFAULT_ALGORITHM;
}
if ($algo == MD5 || $algo == SHA256 || $algo == CLEAR) {
return $algo;
}
Logger::getInstance()->error("Algo " . $algo . " is not supported");
return null;
}
function get_domain($param)
{
if ($param == null || $param == "") {
Logger::getInstance()->warning("Domain parameter wasn't found, assume " . SIP_DOMAIN);
$param = SIP_DOMAIN;
}
return $param;
}
function get_lang($param)
{
if ($param == null || $param == "") {
Logger::getInstance()->warning("lang parameter wasn't found, use US");
return 'US';
} elseif (strlen($param) > 2) {
$param = substr($param, 0, 2);
}
return strtoupper($param);
}
// Password
function hash_password($user, $password, $domain, $algo)
{
$hashed_password = $password;
if ($algo == "" || $algo == MD5) {
$hashed_password = hash("md5", $user . ":" . $domain . ":" . $password);
} elseif ($algo == SHA256) {
$hashed_password = hash("sha256", $user . ":" . $domain . ":" . $password);
} else {
Logger::getInstance()->error("Algorithm not supported: " . $algo);
}
return $hashed_password;
}
function generate_username()
{
$generated_username = substr(str_shuffle(GENERATED_USERNAME_CHARACTERS), 0, GENERATED_USERNAME_LENGTH);
return $generated_username;
}
function generate_password()
{
$generated_password = substr(str_shuffle(GENERATED_PASSWORD_CHARACTERS), 0, GENERATED_PASSWORD_LENGTH);
return $generated_password;
}
function generate_4_digits_code()
{
$generated_password = substr(str_shuffle("0123456789"), 0, 4);
return $generated_password;
}
function password_match($pwd1, $pwd2)
{
if ($pwd1 != $pwd2) {
Logger::getInstance()->error("Password doesn't match");
return false;
}
return true;
}
function is_key_matching($key, $account)
{
$key_db = $account->confirmation_key;
if ($key == INVALID_CONFIRMATION_KEY || $key != $key_db) {
if ($key_db != INVALID_CONFIRMATION_KEY) {
$account->confirmation_key = INVALID_CONFIRMATION_KEY;
$account->update();
}
Logger::getInstance()->error("Key doesn't match");
return false;
}
if (REMOVE_CONFIRMATION_KEY_AFTER_USE) {
// Key is one time only
$account->confirmation_key = INVALID_CONFIRMATION_KEY;
$account->update();
}
return true;
}
// Time
function time_elapsed_as_string($secs)
{
$bit = array(
'y' => $secs / 31556926 % 12,
'w' => $secs / 604800 % 52,
'd' => $secs / 86400 % 7,
'h' => $secs / 3600 % 24,
'm' => $secs / 60 % 60,
's' => $secs % 60
);
foreach ($bit as $k => $v) {
if ($v > 0) {
$ret[] = $v . $k;
}
}
return join(' ', $ret);
}
// /!\ ALWAYS enter the const config value under quotes, otherwize it won't be taken into account
function get_config_value($param_name, $default_value) {
return defined($param_name) ? constant($param_name) : $default_value;
}

View file

@ -1,289 +0,0 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
class Account
{
private $conn;
public $id;
public $username;
public $domain;
public $email;
public $activated;
public $confirmation_key;
public $ip_address;
public $user_agent;
public $creation_time;
public $expire_time;
public $alias;
public function __construct($db)
{
$this->conn = $db;
}
public function __toString()
{
$to_string = "Account: ";
if (!empty($this->id)) {
$to_string = $to_string . "id=" . $this->id . ", ";
}
if (!empty($this->username)) {
$to_string = $to_string . "username=" . $this->username . ", ";
}
if (!empty($this->domain)) {
$to_string = $to_string . "domain=" . $this->domain . ", ";
}
if (!empty($this->email)) {
$to_string = $to_string . "email=" . $this->email . ", ";
}
if (!empty($this->activated)) {
$to_string = $to_string . "activated=" . $this->activated . ", ";
}
if (!empty($this->ip_address)) {
$to_string = $to_string . "ip_address=" . $this->ip_address . ", ";
}
if (!empty($this->confirmation_key)) {
$to_string = $to_string . "confirmation_key=" . $this->confirmation_key . ", ";
}
if (!empty($this->alias)) {
$to_string = $to_string . "alias=" . $this->alias . ", ";
}
return substr($to_string, 0, -2);
}
public function delete()
{
$query = "DELETE FROM " . ACCOUNTS_DB_TABLE . " WHERE id = ?";
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$stmt = $this->conn->prepare($query);
$this->id = htmlspecialchars(strip_tags($this->id));
$stmt->bindParam(1, $this->id);
Logger::getInstance()->debug("Deleting " . (string)$this);
if ($stmt->execute()) {
return true;
}
Logger::getInstance()->error($stmt->errorInfo());
return false;
}
public function create()
{
$query = "INSERT INTO " . ACCOUNTS_DB_TABLE . " SET username=:username, domain=:domain, email=:email, activated=:activated,
confirmation_key=:confirmation_key, ip_address=:ip_address, user_agent=:user_agent, creation_time=:creation_time";
if (USE_IN_APP_PURCHASES) {
$query = $query . ", expire_time=DATE_ADD(NOW(), INTERVAL " . EXPIRATION_DELAY . " MINUTE)";
$this->expire_time = htmlspecialchars(strip_tags($this->expire_time));
}
if (empty($this->creation_time)) {
$this->creation_time = date('Y-m-d H:i:s');
}
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$stmt = $this->conn->prepare($query);
$this->username = htmlspecialchars(strip_tags($this->username));
$this->domain = htmlspecialchars(strip_tags($this->domain));
$this->activated = htmlspecialchars(strip_tags($this->activated));
$this->email = htmlspecialchars(strip_tags($this->email));
$this->confirmation_key = htmlspecialchars(strip_tags($this->confirmation_key));
$this->ip_address = htmlspecialchars(strip_tags($this->ip_address));
$this->user_agent = htmlspecialchars(strip_tags($this->user_agent));
$this->creation_time = htmlspecialchars(strip_tags($this->creation_time));
$stmt->bindParam(":username", $this->username);
$stmt->bindParam(":domain", $this->domain);
$stmt->bindParam(":email", $this->email);
$stmt->bindParam(":activated", $this->activated);
$stmt->bindParam(":confirmation_key", $this->confirmation_key);
$stmt->bindParam(":ip_address", $this->ip_address);
$stmt->bindParam(":user_agent", $this->user_agent);
$stmt->bindParam(":creation_time", $this->creation_time);
Logger::getInstance()->debug("Creating " . (string)$this);
if ($stmt->execute()) {
$this->id = $this->conn->lastInsertId();
return true;
}
Logger::getInstance()->error($stmt->errorInfo());
return false;
}
public function activate()
{
$query = "UPDATE " . ACCOUNTS_DB_TABLE . " SET activated=1 WHERE id=:id";
$stmt = $this->conn->prepare($query);
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$stmt->bindParam(":id", $this->id);
Logger::getInstance()->debug("Activating " . (string)$this);
if ($stmt->execute()) {
$this->activated = "1";
return true;
}
Logger::getInstance()->error($stmt->errorInfo());
return false;
}
public function update()
{
$query = "UPDATE " . ACCOUNTS_DB_TABLE . " SET username=:username, domain=:domain, activated=:activated";
if (!empty($this->email)) {
$query = $query . ", email=:email";
}
if (!empty($this->confirmation_key)) {
$query = $query . ", confirmation_key=:confirmation_key";
}
if (USE_IN_APP_PURCHASES) {
$query = $query . ", expire_time=:expire_time";
}
$query = $query . " WHERE id=:id";
$stmt = $this->conn->prepare($query);
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$this->id = htmlspecialchars(strip_tags($this->id));
$this->username = htmlspecialchars(strip_tags($this->username));
$this->domain = htmlspecialchars(strip_tags($this->domain));
$this->activated = htmlspecialchars(strip_tags($this->activated));
$stmt->bindParam(":username", $this->username);
$stmt->bindParam(":domain", $this->domain);
$stmt->bindParam(":activated", $this->activated);
$stmt->bindParam(":id", $this->id);
if (!empty($this->email)) {
$this->email = htmlspecialchars(strip_tags($this->email));
$stmt->bindParam(":email", $this->email);
}
if (!empty($this->confirmation_key)) {
$this->confirmation_key = htmlspecialchars(strip_tags($this->confirmation_key));
$stmt->bindParam(":confirmation_key", $this->confirmation_key);
}
if (USE_IN_APP_PURCHASES) {
$this->expire_time = htmlspecialchars(strip_tags($this->expire_time));
$stmt->bindParam(":expire_time", $this->expire_time);
}
Logger::getInstance()->debug("Updating " . (string)$this);
if ($stmt->execute()) {
return true;
}
Logger::getInstance()->error($stmt->errorInfo());
return false;
}
public function getCount()
{
$query = "SELECT count(*) FROM " . ACCOUNTS_DB_TABLE;
$stmt = $this->conn->prepare($query);
Logger::getInstance()->debug("GetCount " . (string)$this);
if ($stmt->execute()) {
$number_of_rows = $stmt->fetchColumn();
return $number_of_rows;
}
Logger::getInstance()->error($stmt->errorInfo());
return -1;
}
public function getAll()
{
$query = "SELECT ac.id, ac.username, ac.domain, ac.activated, ac.confirmation_key, ac.email, al.alias FROM " . ACCOUNTS_DB_TABLE .
" ac LEFT JOIN " . ALIAS_DB_TABLE . " al ON ac.id = al.account_id";
$stmt = $this->conn->prepare($query);
Logger::getInstance()->debug("GetAll " . (string)$this);
$stmt->execute();
return $stmt;
}
public function getOne()
{
$query = "SELECT ac.id, ac.username, ac.domain, ac.activated, ac.confirmation_key, ac.email, ac.ip_address, al.alias FROM " . ACCOUNTS_DB_TABLE .
" ac LEFT JOIN " . ALIAS_DB_TABLE . " al ON ac.id = al.account_id";
if (!empty($this->id)) {
$query = $query . " WHERE ac.id = ?";
$this->id = htmlspecialchars(strip_tags($this->id));
} elseif (!empty($this->username)) {
$query = $query . " WHERE ac.username = ?";
$this->username = htmlspecialchars(strip_tags($this->username));
if (!empty($this->domain)) {
$query = $query . " AND ac.domain = ?";
$this->domain = htmlspecialchars(strip_tags($this->domain));
}
} elseif (!empty($this->email)) {
$query = $query . " WHERE ac.email = ?";
$this->email = htmlspecialchars(strip_tags($this->email));
} elseif (!empty($this->confirmation_key)) {
$query = $query . " WHERE ac.confirmation_key = ?";
$this->confirmation_key = htmlspecialchars(strip_tags($this->confirmation_key));
} else {
return false;
}
$query = $query . " LIMIT 0,1";
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$stmt = $this->conn->prepare($query);
if (!empty($this->id)) {
$stmt->bindParam(1, $this->id);
} elseif (!empty($this->username)) {
$stmt->bindParam(1, $this->username);
if (!empty($this->domain)) {
$stmt->bindParam(2, $this->domain);
}
} elseif (!empty($this->email)) {
$stmt->bindParam(1, $this->email);
} elseif (!empty($this->confirmation_key)) {
$stmt->bindParam(1, $this->confirmation_key);
}
Logger::getInstance()->debug("GetOne " . (string)$this);
if ($stmt->execute()) {
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if ($row == null) {
Logger::getInstance()->message("Couldn't find account matching " . (string)$this);
return false;
}
$this->id = $row['id'];
$this->username = $row['username'];
$this->domain = $row['domain'];
$this->email = $row['email'];
$this->activated = strval($row['activated']);
$this->confirmation_key = $row['confirmation_key'];
$this->ip_address = $row['ip_address'];
$this->alias = $row['alias'];
return true;
}
Logger::getInstance()->error($stmt->errorInfo());
return false;
}
}

View file

@ -1,210 +0,0 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
class Alias
{
private $conn;
public $id;
public $account_id;
public $alias;
public $domain;
public function __construct($db)
{
$this->conn = $db;
}
public function __toString()
{
$to_string = "Alias: ";
if (!empty($this->id)) {
$to_string = $to_string . "id=" . $this->id . ", ";
}
if (!empty($this->account_id)) {
$to_string = $to_string . "account_id=" . $this->account_id . ", ";
}
if (!empty($this->alias)) {
$to_string = $to_string . "alias=" . $this->alias . ", ";
}
if (!empty($this->domain)) {
$to_string = $to_string . "domain=" . $this->domain . ", ";
}
return substr($to_string, 0, -2);
}
public function delete()
{
$query = "DELETE FROM " . ALIAS_DB_TABLE;
if (!empty($this->id)) {
$query = $query . " WHERE id = ?";
$this->id = htmlspecialchars(strip_tags($this->id));
} elseif (!empty($this->account_id)) {
$query = $query . " WHERE account_id = ?";
$this->account_id = htmlspecialchars(strip_tags($this->account_id));
} elseif (!empty($this->alias)) {
$query = $query . " WHERE alias = ?";
$this->alias = htmlspecialchars(strip_tags($this->alias));
if (!empty($this->domain)) {
$query = $query . " AND domain = ?";
$this->domain = htmlspecialchars(strip_tags($this->domain));
}
} else {
return false;
}
$stmt = $this->conn->prepare($query);
$this->id = htmlspecialchars(strip_tags($this->id));
if (!empty($this->id)) {
$stmt->bindParam(1, $this->id);
} elseif (!empty($this->account_id)) {
$stmt->bindParam(1, $this->account_id);
} elseif (!empty($this->alias)) {
$stmt->bindParam(1, $this->alias);
if (!empty($this->domain)) {
$stmt->bindParam(2, $this->domain);
}
}
Logger::getInstance()->debug("Deleting " . (string)$this);
if ($stmt->execute()) {
return true;
}
Logger::getInstance()->error($stmt->errorInfo());
return false;
}
public function create()
{
$query = "INSERT INTO " . ALIAS_DB_TABLE . " SET account_id=:account_id, alias=:alias, domain=:domain";
$stmt = $this->conn->prepare($query);
$this->account_id = htmlspecialchars(strip_tags($this->account_id));
$this->alias = htmlspecialchars(strip_tags($this->alias));
$this->domain = htmlspecialchars(strip_tags($this->domain));
$stmt->bindParam(":account_id", $this->account_id);
$stmt->bindParam(":alias", $this->alias);
$stmt->bindParam(":domain", $this->domain);
Logger::getInstance()->debug("Creating " . (string)$this);
if ($stmt->execute()) {
$this->id = $this->conn->lastInsertId();
return true;
}
Logger::getInstance()->error($stmt->errorInfo());
return false;
}
public function update()
{
$query = "UPDATE " . ALIAS_DB_TABLE . " SET account_id=:account_id, alias=:alias, domain=:domain WHERE id=:id";
$stmt = $this->conn->prepare($query);
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$this->id = htmlspecialchars(strip_tags($this->id));
$this->account_id = htmlspecialchars(strip_tags($this->account_id));
$this->alias = htmlspecialchars(strip_tags($this->alias));
$this->domain = htmlspecialchars(strip_tags($this->domain));
$stmt->bindParam(":account_id", $this->account_id);
$stmt->bindParam(":alias", $this->alias);
$stmt->bindParam(":domain", $this->domain);
$stmt->bindParam(":id", $this->id);
Logger::getInstance()->debug("Updating " . (string)$this);
if ($stmt->execute()) {
return true;
}
Logger::getInstance()->error($stmt->errorInfo());
return false;
}
public function getAll()
{
$query = "SELECT id, account_id, alias, domain FROM " . ALIAS_DB_TABLE;
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$stmt = $this->conn->prepare($query);
Logger::getInstance()->debug("GetAll " . (string)$this);
$stmt->execute();
return $stmt;
}
public function getOne()
{
$query = "SELECT id, account_id, alias, domain FROM " . ALIAS_DB_TABLE;
if (!empty($this->id)) {
$query = $query . " WHERE id = ?";
$this->id = htmlspecialchars(strip_tags($this->id));
} elseif (!empty($this->account_id)) {
$query = $query . " WHERE account_id = ?";
$this->account_id = htmlspecialchars(strip_tags($this->account_id));
} elseif (!empty($this->alias)) {
$query = $query . " WHERE alias = ?";
$this->alias = htmlspecialchars(strip_tags($this->alias));
if (!empty($this->domain)) {
$query = $query . " AND domain = ?";
$this->domain = htmlspecialchars(strip_tags($this->domain));
}
} else {
return false;
}
$query = $query . " LIMIT 0,1";
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$stmt = $this->conn->prepare($query);
if (!empty($this->id)) {
$stmt->bindParam(1, $this->id);
} elseif (!empty($this->account_id)) {
$stmt->bindParam(1, $this->account_id);
} elseif (!empty($this->alias)) {
$stmt->bindParam(1, $this->alias);
if (!empty($this->domain)) {
$stmt->bindParam(2, $this->domain);
}
}
Logger::getInstance()->debug("GetOne " . (string)$this);
if ($stmt->execute()) {
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if ($row == null) {
Logger::getInstance()->message("Couldn't find alias matching " . (string)$this);
return false;
}
$this->id = $row['id'];
$this->account_id = $row['account_id'];
$this->alias = $row['alias'];
$this->domain = $row['domain'];
return true;
}
Logger::getInstance()->error($stmt->errorInfo());
return false;
}
}

View file

@ -1,146 +0,0 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
class Device
{
private $conn;
public $id;
public $manufacturer;
public $model;
public $status;
public $delay;
public $hardware_echo_canceller;
public function __construct($db)
{
$this->conn = $db;
}
public function __toString()
{
$to_string = "Device: ";
if (!empty($this->id)) {
$to_string = $to_string . "id=" . $this->id . ", ";
}
if (!empty($this->manufacturer)) {
$to_string = $to_string . "manufacturer=" . $this->manufacturer . ", ";
}
if (!empty($this->model)) {
$to_string = $to_string . "model=" . $this->model . ", ";
}
if (!empty($this->status)) {
$to_string = $to_string . "status=" . $this->status . ", ";
}
if (!empty($this->delay)) {
$to_string = $to_string . "delay=" . $this->delay . ", ";
}
if (!empty($this->hardware_echo_canceller)) {
$to_string = $to_string . "hardware_echo_canceller=" . $this->hardware_echo_canceller . ", ";
}
return substr($to_string, 0, -2);
}
public function delete()
{
$query = "DELETE FROM " . DEVICES_DB_TABLE . " WHERE id = ?";
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$stmt = $this->conn->prepare($query);
$this->id = htmlspecialchars(strip_tags($this->id));
$stmt->bindParam(1, $this->id);
Logger::getInstance()->debug("Deleting " . (string)$this);
if ($stmt->execute()) {
return true;
}
Logger::getInstance()->error($stmt->errorInfo());
return false;
}
public function create()
{
$query = "INSERT INTO " . DEVICES_DB_TABLE . " SET manufacturer=:manufacturer, model=:model, status=:status,
delay=:delay, hardware_echo_canceller=:hardware_echo_canceller";
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$stmt = $this->conn->prepare($query);
$this->manufacturer = htmlspecialchars(strip_tags($this->manufacturer));
$this->model = htmlspecialchars(strip_tags($this->model));
$this->status = htmlspecialchars(strip_tags($this->status));
$this->delay = htmlspecialchars(strip_tags($this->delay));
$this->hardware_echo_canceller = htmlspecialchars(strip_tags($this->hardware_echo_canceller));
$stmt->bindParam(":manufacturer", $this->manufacturer);
$stmt->bindParam(":model", $this->model);
$stmt->bindParam(":status", $this->status);
$stmt->bindParam(":delay", $this->delay);
$stmt->bindParam(":hardware_echo_canceller", $this->hardware_echo_canceller);
Logger::getInstance()->debug("Creating " . (string)$this);
if ($stmt->execute()) {
$this->id = $this->conn->lastInsertId();
return true;
}
Logger::getInstance()->error($stmt->errorInfo());
return false;
}
public function update()
{
$query = "UPDATE " . DEVICES_DB_TABLE . " SET manufacturer=:manufacturer, model=:model, status=:status,
delay=:delay, hardware_echo_canceller=:hardware_echo_canceller WHERE id=:id";
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$stmt = $this->conn->prepare($query);
$this->id = htmlspecialchars(strip_tags($this->id));
$this->manufacturer = htmlspecialchars(strip_tags($this->manufacturer));
$this->model = htmlspecialchars(strip_tags($this->model));
$this->status = htmlspecialchars(strip_tags($this->status));
$this->delay = htmlspecialchars(strip_tags($this->delay));
$this->hardware_echo_canceller = htmlspecialchars(strip_tags($this->hardware_echo_canceller));
$stmt->bindParam(":manufacturer", $this->manufacturer);
$stmt->bindParam(":model", $this->model);
$stmt->bindParam(":status", $this->status);
$stmt->bindParam(":delay", $this->delay);
$stmt->bindParam(":hardware_echo_canceller", $this->hardware_echo_canceller);
$stmt->bindParam(":id", $this->id);
Logger::getInstance()->debug("Updating " . (string)$this);
if ($stmt->execute()) {
return true;
}
Logger::getInstance()->error($stmt->errorInfo());
return false;
}
public function getAll()
{
$query = "SELECT id, manufacturer, model, status, delay, hardware_echo_canceller FROM " . DEVICES_DB_TABLE;
$stmt = $this->conn->prepare($query);
Logger::getInstance()->debug("GetAll " . (string)$this);
$stmt->execute();
return $stmt;
}
}

View file

@ -1,201 +0,0 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
class Password
{
private $conn;
public $id;
public $account_id;
public $password;
public $algorithm;
public function __construct($db)
{
$this->conn = $db;
}
public function __toString()
{
$to_string = "Password: ";
if (!empty($this->id)) {
$to_string = $to_string . "id=" . $this->id . ", ";
}
if (!empty($this->account_id)) {
$to_string = $to_string . "account_id=" . $this->account_id . ", ";
}
if (!empty($this->password)) {
$to_string = $to_string . "password=********"/* . $this->password*/ . ", ";
}
if (!empty($this->algorithm)) {
$to_string = $to_string . "algorithm=" . $this->algorithm . ", ";
}
return substr($to_string, 0, -2);
}
public function delete()
{
$query = "DELETE FROM " . ACCOUNTS_ALGO_DB_TABLE;
if (!empty($this->id)) {
$query = $query . " WHERE id = ?";
$this->id = htmlspecialchars(strip_tags($this->id));
} elseif (!empty($this->account_id)) {
$query = $query . " WHERE account_id = ?";
$this->account_id = htmlspecialchars(strip_tags($this->account_id));
if (!empty($this->algorithm)) {
$query = $query . " AND algorithm = ?";
$this->algorithm = htmlspecialchars(strip_tags($this->algorithm));
}
} else {
return false;
}
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$stmt = $this->conn->prepare($query);
$this->id = htmlspecialchars(strip_tags($this->id));
if (!empty($this->id)) {
$stmt->bindParam(1, $this->id);
} elseif (!empty($this->account_id)) {
$stmt->bindParam(1, $this->account_id);
if (!empty($this->algorithm)) {
$stmt->bindParam(2, $this->algorithm);
}
}
Logger::getInstance()->debug("Deleting " . (string)$this);
if ($stmt->execute()) {
return true;
}
Logger::getInstance()->error($stmt->errorInfo());
return false;
}
public function create()
{
$query = "INSERT INTO " . ACCOUNTS_ALGO_DB_TABLE . " SET account_id=:account_id, password=:password, algorithm=:algorithm";
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$stmt = $this->conn->prepare($query);
$this->account_id = htmlspecialchars(strip_tags($this->account_id));
$this->password = htmlspecialchars(strip_tags($this->password));
$this->algorithm = htmlspecialchars(strip_tags($this->algorithm));
$stmt->bindParam(":account_id", $this->account_id);
$stmt->bindParam(":password", $this->password);
$stmt->bindParam(":algorithm", $this->algorithm);
Logger::getInstance()->debug("Creating " . (string)$this);
if ($stmt->execute()) {
$this->id = $this->conn->lastInsertId();
return true;
}
Logger::getInstance()->error($stmt->errorInfo());
return false;
}
public function update()
{
$query = "UPDATE " . ACCOUNTS_ALGO_DB_TABLE . " SET account_id=:account_id, password=:password, algorithm=:algorithm WHERE id=:id";
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$stmt = $this->conn->prepare($query);
$this->id = htmlspecialchars(strip_tags($this->id));
$this->account_id = htmlspecialchars(strip_tags($this->account_id));
$this->password = htmlspecialchars(strip_tags($this->password));
$this->algorithm = htmlspecialchars(strip_tags($this->algorithm));
$stmt->bindParam(":account_id", $this->account_id);
$stmt->bindParam(":password", $this->password);
$stmt->bindParam(":algorithm", $this->algorithm);
$stmt->bindParam(":id", $this->id);
Logger::getInstance()->debug("Updating " . (string)$this);
if ($stmt->execute()) {
return true;
}
Logger::getInstance()->error($stmt->errorInfo());
return false;
}
public function getAll()
{
$query = "SELECT id, password, algorithm FROM " . ACCOUNTS_ALGO_DB_TABLE . " WHERE account_id = ?";
$stmt = $this->conn->prepare($query);
$this->account_id = htmlspecialchars(strip_tags($this->account_id));
$stmt->bindParam(1, $this->account_id);
Logger::getInstance()->debug("GetAll " . (string)$this);
$stmt->execute();
return $stmt;
}
public function getOne()
{
$query = "SELECT id, password, algorithm FROM " . ACCOUNTS_ALGO_DB_TABLE . " WHERE account_id = ?";
$this->account_id = htmlspecialchars(strip_tags($this->account_id));
if (!empty($this->algorithm)) {
$query = $query . " AND algorithm = ?";
$this->algorithm = htmlspecialchars(strip_tags($this->algorithm));
if (!empty($this->password)) {
$query = $query . " AND password = ?";
$this->password = htmlspecialchars(strip_tags($this->password));
}
} elseif (!empty($this->password)) {
$query = $query . " AND password = ?";
$this->password = htmlspecialchars(strip_tags($this->password));
}
$query = $query . " LIMIT 0,1";
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$stmt = $this->conn->prepare($query);
$stmt->bindParam(1, $this->account_id);
if (!empty($this->algorithm)) {
$stmt->bindParam(2, $this->algorithm);
if (!empty($this->password)) {
$stmt->bindParam(3, $this->password);
}
} elseif (!empty($this->password)) {
$stmt->bindParam(2, $this->password);
}
Logger::getInstance()->debug("GetOne " . (string)$this);
if ($stmt->execute()) {
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if ($row == null) {
Logger::getInstance()->message("Couldn't find password matching " . (string)$this);
return false;
}
$this->id = $row['id'];
$this->password = $row['password'];
$this->algorithm = $row['algorithm'];
return true;
}
Logger::getInstance()->error($stmt->errorInfo());
return false;
}
}

View file

@ -1,153 +0,0 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
class SMS
{
private $conn;
public $id;
public $phone;
public $last_sms;
public $count;
public function __construct($db)
{
$this->conn = $db;
}
public function __toString()
{
$to_string = "SMS: ";
if (!empty($this->id)) {
$to_string = $to_string . "id=" . $this->id . ", ";
}
if (!empty($this->phone)) {
$to_string = $to_string . "phone=" . $this->phone . ", ";
}
if (!empty($this->last_sms)) {
$to_string = $to_string . "last_sms=" . $this->last_sms . ", ";
}
if (!empty($this->count)) {
$to_string = $to_string . "count=" . $this->count . ", ";
}
return substr($to_string, 0, -2);
}
public function delete()
{
$query = "DELETE FROM " . SMS_DB_TABLE . " WHERE id = ?";
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$stmt = $this->conn->prepare($query);
$this->id = htmlspecialchars(strip_tags($this->id));
$stmt->bindParam(1, $this->id);
Logger::getInstance()->debug("Deleting " . (string)$this);
if ($stmt->execute()) {
return true;
}
Logger::getInstance()->error($stmt->errorInfo());
return false;
}
public function create()
{
$query = "INSERT INTO " . SMS_DB_TABLE . " SET phone=:phone, last_sms=:last_sms, count=:count";
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$stmt = $this->conn->prepare($query);
$this->phone = htmlspecialchars(strip_tags($this->phone));
$this->last_sms = htmlspecialchars(strip_tags($this->last_sms));
$this->count = htmlspecialchars(strip_tags($this->count));
$stmt->bindParam(":phone", $this->phone);
$stmt->bindParam(":last_sms", $this->last_sms);
$stmt->bindParam(":count", $this->count);
Logger::getInstance()->debug("Creating " . (string)$this);
if ($stmt->execute()) {
$this->id = $this->conn->lastInsertId();
return true;
}
Logger::getInstance()->error($stmt->errorInfo());
return false;
}
public function update()
{
$query = "UPDATE " . SMS_DB_TABLE . " SET phone=:phone, last_sms=:last_sms, count=:count WHERE id=:id";
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$stmt = $this->conn->prepare($query);
$this->id = htmlspecialchars(strip_tags($this->id));
$this->phone = htmlspecialchars(strip_tags($this->phone));
$this->last_sms = htmlspecialchars(strip_tags($this->last_sms));
$this->count = htmlspecialchars(strip_tags($this->count));
$stmt->bindParam(":phone", $this->phone);
$stmt->bindParam(":last_sms", $this->last_sms);
$stmt->bindParam(":count", $this->count);
$stmt->bindParam(":id", $this->id);
Logger::getInstance()->debug("Updating " . (string)$this);
if ($stmt->execute()) {
return true;
}
Logger::getInstance()->error($stmt->errorInfo());
return false;
}
public function getAll()
{
$query = "SELECT id, phone, last_sms, count FROM " . SMS_DB_TABLE;
$stmt = $this->conn->prepare($query);
Logger::getInstance()->debug("GetAll " . (string)$this);
$stmt->execute();
return $stmt;
}
public function getOne()
{
$query = "SELECT id, phone, last_sms, count FROM " . SMS_DB_TABLE . " WHERE phone = ?";
$stmt = $this->conn->prepare($query);
$this->phone = htmlspecialchars(strip_tags($this->phone));
$stmt->bindParam(1, $this->phone);
Logger::getInstance()->debug("GetOne " . (string)$this);
if ($stmt->execute()) {
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if ($row == null) {
Logger::getInstance()->message("Couldn't find SMS matching " . (string)$this);
return false;
}
$this->id = $row['id'];
$this->phone = $row['phone'];
$this->last_sms = $row['last_sms'];
$this->count = $row['count'];
return true;
}
Logger::getInstance()->error($stmt->errorInfo());
return false;
}
}

View file

@ -1,221 +0,0 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
class UserInfo
{
private $conn;
public $id;
public $account_id;
public $firstname;
public $lastname;
public $gender;
public $country_code;
public $country_name;
public $subscribe;
public function __construct($db)
{
$this->conn = $db;
}
public function __toString()
{
$to_string = "UserInfo: ";
if (!empty($this->id)) {
$to_string .= "id=" . $this->id . ", ";
}
if (!empty($this->account_id)) {
$to_string .= "account_id=" . $this->account_id . ", ";
}
if (!empty($this->firstname)) {
$to_string .= "firstname=" . $this->firstname . ", ";
}
if (!empty($this->lastname)) {
$to_string .= "lastname=" . $this->lastname . ", ";
}
if (!empty($this->gender)) {
$to_string .= "gender=" . $this->gender . ", ";
}
if (!empty($this->country_code)) {
$to_string .= "country_code=" . $this->country_code . ", ";
}
if (!empty($this->country_name)) {
$to_string .= "country_name=" . $this->country_name . ", ";
}
if (!empty($this->subscribe)) {
$to_string .= "subscribe=" . $this->subscribe . ", ";
}
return substr($to_string, 0, -2);
}
public function delete()
{
$query = "DELETE FROM " . USER_INFO_DB_TABLE . " WHERE id = ?";
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$stmt = $this->conn->prepare($query);
$this->id = htmlspecialchars(strip_tags($this->id));
$stmt->bindParam(1, $this->id);
Logger::getInstance()->debug("Deleting " . (string)$this);
if ($stmt->execute()) {
return true;
}
Logger::getInstance()->error($stmt->errorInfo());
return false;
}
public function create()
{
$query = "INSERT INTO " . USER_INFO_DB_TABLE . " SET account_id=:account_id, firstname=:firstname, lastname=:lastname, gender=:gender, subscribe=:subscribe";
if (get_config_value("ENABLE_NEW_ACCOUNTS_GEOLOC", FALSE)) {
$query .= ", country_code=:country_code, country_name=:country_name";
}
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$stmt = $this->conn->prepare($query);
$this->account_id = htmlspecialchars(strip_tags($this->account_id));
$this->firstname = htmlspecialchars(strip_tags($this->firstname));
$this->lastname = htmlspecialchars(strip_tags($this->lastname));
$this->gender = htmlspecialchars(strip_tags($this->gender));
$this->subscribe = htmlspecialchars(strip_tags($this->subscribe));
$stmt->bindParam(":account_id", $this->account_id);
$stmt->bindParam(":firstname", $this->firstname);
$stmt->bindParam(":lastname", $this->lastname);
$stmt->bindParam(":gender", $this->gender);
$stmt->bindParam(":subscribe", $this->subscribe);
if (get_config_value("ENABLE_NEW_ACCOUNTS_GEOLOC", FALSE)) {
$this->country_code = htmlspecialchars(strip_tags($this->country_code));
$this->country_name = htmlspecialchars(strip_tags($this->country_name));
$stmt->bindParam(":country_code", $this->country_code);
$stmt->bindParam(":country_name", $this->country_name);
}
Logger::getInstance()->debug("Creating " . (string)$this);
if ($stmt->execute()) {
$this->id = $this->conn->lastInsertId();
return true;
}
Logger::getInstance()->error($stmt->errorInfo());
return false;
}
public function update()
{
$query = "UPDATE " . USER_INFO_DB_TABLE . " SET firstname=:firstname, lastname=:lastname, subscribe=:subscribe, gender=:gender";
$query = $query . " WHERE id=:id";
$stmt = $this->conn->prepare($query);
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$this->id = htmlspecialchars(strip_tags($this->id));
$this->firstname = htmlspecialchars(strip_tags($this->firstname));
$this->lastname = htmlspecialchars(strip_tags($this->lastname));
$this->gender = htmlspecialchars(strip_tags($this->gender));
$this->subscribe = htmlspecialchars(strip_tags($this->subscribe));
$stmt->bindParam(":firstname", $this->firstname);
$stmt->bindParam(":lastname", $this->lastname);
$stmt->bindParam(":subscribe", $this->subscribe);
$stmt->bindParam(":gender", $this->gender);
$stmt->bindParam(":id", $this->id);
Logger::getInstance()->debug("Updating " . (string)$this);
if ($stmt->execute()) {
return true;
}
Logger::getInstance()->error($stmt->errorInfo());
return false;
}
public function getAll()
{
$query = "SELECT id, account_id, firstname, lastname, gender, subscribe FROM " . USER_INFO_DB_TABLE;
$stmt = $this->conn->prepare($query);
Logger::getInstance()->debug("GetAll " . (string)$this);
$stmt->execute();
return $stmt;
}
public function getOne()
{
$query = "SELECT id, account_id, firstname, lastname, gender, subscribe FROM " . USER_INFO_DB_TABLE;
if (!empty($this->id)) {
$query = $query . " WHERE id = ?";
$this->id = htmlspecialchars(strip_tags($this->id));
} elseif (!empty($this->account_id)) {
$query = $query . " WHERE account_id = ?";
$this->account_id = htmlspecialchars(strip_tags($this->account_id));
} elseif (!empty($this->lastname)) {
$query = $query . " WHERE lastname = ?";
$this->lastname = htmlspecialchars(strip_tags($this->lastname));
if (!empty($this->firstname)) {
$query = $query . " AND firstname = ?";
$this->firstname = htmlspecialchars(strip_tags($this->firstname));
}
} else {
return false;
}
$query = $query . " LIMIT 0,1";
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$stmt = $this->conn->prepare($query);
if (!empty($this->id)) {
$stmt->bindParam(1, $this->id);
} elseif (!empty($this->account_id)) {
$stmt->bindParam(1, $this->account_id);
} elseif (!empty($this->lastname)) {
$stmt->bindParam(1, $this->lastname);
if (!empty($this->firstname)) {
$stmt->bindParam(2, $this->firstname);
}
}
Logger::getInstance()->debug("GetOne " . (string)$this);
if ($stmt->execute()) {
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if ($row == null) {
Logger::getInstance()->message("Couldn't find account matching " . (string)$this);
return false;
}
$this->id = $row['id'];
$this->account_id = $row['account_id'];
$this->firstname = $row['firstname'];
$this->lastname = $row['lastname'];
$this->gender = $row['gender'];
$this->country_code = $row['country_code'];
$this->country_name = $row['country_name'];
$this->subscribe = $row['subscribe'];
return true;
}
Logger::getInstance()->error($stmt->errorInfo());
return false;
}
}

View file

@ -1,207 +0,0 @@
#!/usr/bin/env php
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
include_once __DIR__ . '/../database/database.php';
include_once __DIR__ . '/../objects/account.php';
include_once __DIR__ . '/../objects/alias.php';
include_once __DIR__ . '/../objects/device.php';
include_once __DIR__ . '/../objects/password.php';
include_once __DIR__ . '/../objects/sms.php';
include_once __DIR__ . '/../objects/user_info.php';
include_once __DIR__ . '/../misc/utilities.php';
$database = new Database();
$db = $database->getConnection();
$old_db = null;
try {
$old_db = new PDO("mysql:host=" . DB_HOST . ";dbname=belledonne_proxy", DB_USER, DB_PASSWORD);
$old_db->exec("set names utf8");
} catch (PDOException $exception) {
Logger::getInstance()->error("Connection error: " . $exception->getMessage());
return;
}
Logger::getInstance()->message("Ready to migrate");
$start_time = time();
/* **************************************************** */
Logger::getInstance()->message("Starting accounts migration");
$query = "SELECT ac.id, ac.login, ac.password, ac.activated, ac.email, ac.confirmation_key, ac.ip_address, ac.date_last_update, ac.user_agent, ac.firstname, ac.name, ac.gender, ac.subscribe, al.alias FROM "
. ACCOUNTS_DB_TABLE . " ac LEFT JOIN " . ALIAS_DB_TABLE . " al ON ac.id = al.account_id";
$old_db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$old_db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); // For large sets this is mandatory
$stmt = $old_db->prepare($query);
$stmt->execute();
$accounts_to_migrate_count = 0;
$account_created_count = 0;
$password_created_count = 0;
$alias_created_count = 0;
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$accounts_to_migrate_count += 1;
extract($row);
$account = new Account($db);
$account->username = $login;
$account->domain = SIP_DOMAIN;
$account->email = $email;
$account->activated = $activated;
$account->confirmation_key = $confirmation_key;
$account->ip_address = $ip_address;
$account->user_agent = $user_agent;
$account->creation_time = $date_last_update;
$account->expire_time = null;
if ($account->getOne()) {
// If an account as multiple aliases we will go here
if (!empty($alias)) {
$al = new Alias($db);
$al->account_id = $account->id;
$al->alias = $alias;
$al->domain = $account->domain;
if (!$al->create()) {
Logger::getInstance()->error("Failed to create alias !");
} else {
$alias_created_count += 1;
}
}
} else {
if ($account->create()) {
$account_created_count += 1;
$user_info = new UserInfo($db);
$user_info->account_id = $account->id;
$user_info->firstname = $firstname;
$user_info->lastname = $name;
$user_info->gender = $gender;
$user_info->subscribe = $subscribe;
if (!$user_info->create()) {
Logger::getInstance()->error("Failed to create user_info !");
}
$pwd = new Password($db);
$pwd->account_id = $account->id;
$pwd->algorithm = 'MD5';
$pwd->password = $password;
if (!$pwd->create()) {
Logger::getInstance()->error("Failed to create password !");
} else {
$password_created_count += 1;
}
if (!empty($alias)) {
$al = new Alias($db);
$al->account_id = $account->id;
$al->alias = $alias;
$al->domain = $account->domain;
if (!$al->create()) {
Logger::getInstance()->error("Failed to create alias !");
} else {
$alias_created_count += 1;
}
}
} else {
Logger::getInstance()->error("Failed to create account !");
}
}
}
Logger::getInstance()->message("Accounts migration done");
Logger::getInstance()->message($accounts_to_migrate_count . " were to migrate, " . $account_created_count . " were succesfully created including "
. $password_created_count . " passwords and " . $alias_created_count . " aliases");
/* **************************************************** */
Logger::getInstance()->message("Starting SMS migration");
$all_sms = new SMS($old_db);
$stmt = $all_sms->getAll();
$sms_to_migrate_count = 0;
$sms_created_count = 0;
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$sms_to_migrate_count += 1;
extract($row);
$sms = new SMS($db);
$sms->phone = $phone;
$sms->last_sms = $last_sms;
$sms->count = $count;
if (!$sms->create()) {
Logger::getInstance()->error("Failed to create sms !");
} else {
$sms_created_count += 1;
}
}
Logger::getInstance()->message("SMS migration done");
Logger::getInstance()->message($sms_to_migrate_count . " were to migrate, " . $sms_created_count . " were succesfully created");
/* **************************************************** */
Logger::getInstance()->message("Starting devices migration");
$all_devices = new Device($old_db);
$stmt = $all_devices->getAll();
$devices_to_migrate_count = 0;
$devices_created_count = 0;
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$devices_to_migrate_count += 1;
extract($row);
$device = new Device($db);
$device->manufacturer = $manufacturer;
$device->model = $model;
$device->status = $status;
$device->delay = $delay;
$device->hardware_echo_canceller = $hardware_echo_canceller;
if (!$device->create()) {
Logger::getInstance()->error("Failed to create device !");
} else {
$devices_created_count += 1;
}
}
Logger::getInstance()->message("Devices migration done");
Logger::getInstance()->message($devices_to_migrate_count . " were to migrate, " . $devices_created_count . " were succesfully created");
/* **************************************************** */
$end_time = time();
$time_diff = $end_time - $start_time;
Logger::getInstance()->message("Migration took " . time_elapsed_as_string($time_diff));
?>

View file

@ -1,243 +0,0 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
include_once __DIR__ . '/../database/database.php';
include_once __DIR__ . '/../objects/account.php';
include_once __DIR__ . '/../objects/password.php';
include_once __DIR__ . '/../objects/alias.php';
include_once __DIR__ . '/../objects/user_info.php';
include_once __DIR__ . '/../misc/utilities.php';
include_once __DIR__ . '/accounts_email.php';
include_once __DIR__ . '/accounts_phone.php';
include_once __DIR__ . '/../misc/results_values.php';
// args = [username, [domain]]
function xmlrpc_is_account_used($method, $args)
{
$user = $args[0];
$domain = get_domain($args[1]);
Logger::getInstance()->message("[XMLRPC] xmlrpc_is_account_used(" . $user . ", " . $domain . ")");
if (!check_parameter($user)) {
return MISSING_USERNAME_PARAM;
}
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$account->username = $user;
$account->domain = $domain;
if ($account->getOne()) {
return OK;
}
$alias = new Alias($db);
$alias->alias = $user;
$alias->domain = $domain;
if ($alias->getOne()) {
return OK;
}
return NOK;
}
// args = [username, [domain]]
function xmlrpc_is_account_activated($method, $args)
{
$user = $args[0];
$domain = get_domain($args[1]);
Logger::getInstance()->message("[XMLRPC] xmlrpc_is_account_activated(" . $user . ", " . $domain . ")");
if (!check_parameter($user)) {
return MISSING_USERNAME_PARAM;
}
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$account->username = $user;
$account->domain = $domain;
if (!$account->getOne()) {
$alias = new Alias($db);
$alias->alias = $user;
$alias->domain = $domain;
if ($alias->getOne()) {
$account->id = $alias->account_id;
if (!$account->getOne()) {
return ACCOUNT_NOT_FOUND;
}
} else {
return ACCOUNT_NOT_FOUND;
}
}
Logger::getInstance()->message("Account activation status is " . $account->activated);
if (is_activated($account->activated)) {
return OK;
}
return NOK;
}
// args = [username, key, [domain], [algo]]
function xmlrpc_recover_account_from_confirmation_key($method, $args)
{
$username = $args[0];
$key = $args[1];
$domain = get_domain($args[2]);
$algo = get_algo($args[3]);
Logger::getInstance()->message("[XMLRPC] xmlrpc_recover_account_from_confirmation_key(" . $username . ", " . $domain . ", " . $key . ", " . $algo . ")");
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$account->username = $username;
$account->domain = $domain;
if (!$account->getOne()) {
return ACCOUNT_NOT_FOUND;
}
if (!is_key_matching($key, $account)) {
return KEY_DOESNT_MATCH;
}
Logger::getInstance()->message("Account activation status is " . $account->activated);
if (!is_activated($account)) {
if (!$account->activate()) {
Logger::getInstance()->error("Failed to activate account !");
}
}
$password = new Password($db);
$password->account_id = $account->id;
$password->algorithm = $algo;
if ($password->getOne()) {
$result = array(
"password" => $password->password,
"algorithm" => $password->algorithm
);
return $result;
}
// If not found, try without algo
$password2 = new Password($db);
$password2->account_id = $account->id;
if ($password2->getOne()) {
$result = array(
"password" => $password2->password,
"algorithm" => $password2->algorithm
);
return $result;
}
return PASSWORD_NOT_FOUND;
}
// args = []
function xmlrpc_get_accounts_count($method, $args)
{
Logger::getInstance()->message("[XMLRPC] xmlrpc_get_accounts_count()");
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
return $account->getCount();
}
// args = [user_agent, [domain], [algo]]
function xmlrpc_create_push_account($method, $args)
{
$user_agent = $args[0];
$domain = get_domain($args[1]);
$algo = get_algo($args[2]);
Logger::getInstance()->message("[XMLRPC] xmlrpc_create_push_account(" . $domain . ", " . $algo . ")");
if ($algo == null) {
return ALGO_NOT_SUPPORTED;
}
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$account->domain = $domain;
do {
$user = generate_username();
$account->username = $user;
} while ($account->getOne());
Logger::getInstance()->message("[XMLRPC] Push account generated username is: " . $user);
$hashed_password = hash_password($user, generate_password(), $domain, $algo);
$account->user_agent = $user_agent;
$account->ip_address = getIp();
$account->activated = "1";
$account->create();
$password = new Password($db);
$password->account_id = $account->id;
$password->password = $hashed_password;
$password->algorithm = $algo;
$password->create();
if (CUSTOM_HOOKS) {
hook_on_account_created($account);
}
$result = array(
"username" => $account->username,
"domain" => $account->domain,
"password" => $password->password,
"algorithm" => $password->algorithm
);
return $result;
}
function xmlrpc_accounts_register_methods($server)
{
xmlrpc_server_register_method($server, 'is_account_used', 'xmlrpc_is_account_used');// args = [username, [domain]], return OK or NOK
xmlrpc_server_register_method($server, 'is_account_activated', 'xmlrpc_is_account_activated');// args = [username, [domain]], return OK or NOK
xmlrpc_server_register_method($server, 'recover_account_from_confirmation_key', 'xmlrpc_recover_account_from_confirmation_key');// args = [username, key, [domain], [algo]]
xmlrpc_server_register_method($server, 'get_accounts_count', 'xmlrpc_get_accounts_count');// args = []
xmlrpc_server_register_method($server, 'create_push_account', 'xmlrpc_create_push_account');// args = [user_agent, [domain], [algo]]
xmlrpc_accounts_email_register_methods($server);
xmlrpc_accounts_phone_register_methods($server);
}

View file

@ -1,415 +0,0 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
include_once __DIR__ . '/../database/database.php';
include_once __DIR__ . '/../objects/account.php';
include_once __DIR__ . '/../objects/password.php';
include_once __DIR__ . '/../objects/alias.php';
include_once __DIR__ . '/../objects/user_info.php';
include_once __DIR__ . '/../misc/utilities.php';
include_once __DIR__ . '/../misc/user_info.php';
include_once __DIR__ . '/../misc/results_values.php';
// args = [username, email, [hash], useragent, [domain], [algo]]
function xmlrpc_create_email_account($method, $args)
{
$user = $args[0];
$email = $args[1];
$hashed_password = $args[2];
$user_agent = $args[3];
$domain = get_domain($args[4]);
$algo = get_algo($args[5]);
Logger::getInstance()->message("[XMLRPC] xmlrpc_create_email_account(" . $user . ", " . $domain . ", " . $email . ", " . $algo . ")");
if (!check_parameter($user)) {
return MISSING_USERNAME_PARAM;
} elseif (!check_parameter($email, "email")) {
return MISSING_EMAIL_PARAM;
} elseif ($algo == null) {
return ALGO_NOT_SUPPORTED;
}
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$account->username = $user;
$account->domain = $domain;
if ($account->getOne()) {
return USERNAME_TAKEN;
}
if (!ALLOW_SAME_EMAILS_ON_MULTILPLE_ACCOUNTS) {
$email_account = new Account($db);
$email_account->email = $email;
if ($email_account->getOne()) {
return EMAIL_TAKEN;
}
}
if (GENERATE_PASSWORD_ENABLED) {
$hashed_password = hash_password($user, generate_password(), $domain, $algo);
}
$account->confirmation_key = uniqid();
$account->email = $email;
$account->user_agent = $user_agent;
$account->ip_address = getIp();
$account->activated = AUTO_ACTIVATE_ACCOUNT ? "1" : "0";
$account->create();
$password = new Password($db);
$password->account_id = $account->id;
$password->password = $hashed_password;
$password->algorithm = $algo;
$password->create();
if (CUSTOM_HOOKS) {
hook_on_account_created($account);
}
if (SEND_ACTIVATION_EMAIL && EMAIL_ENABLED) {
send_email_with_activation_link($email, $account->confirmation_key, $account->username, $account->domain, $algo);
} elseif (AUTO_ACTIVATE_ACCOUNT) {
//TODO
/*if (USE_IN_APP_PURCHASES) {
$expiration = get_trial_expiration_date();
db_inapp_add_account($user, $domain, $expiration);
}*/
}
// args = [username, email, [hash], useragent, [domain], [algo]]
// args needed = [username, ha1, firstname, lastname, gender, subscribe, [domain], [algo]]
//need username + domain
//We call this function to set the geoloc if enabled
if (get_config_value("ENABLE_NEW_ACCOUNTS_GEOLOC", FALSE)) {
return update_account_user_info($account->username, $hashed_password, null, null, "unknown", '0', $account->domain, $algo);
}
return OK;
}
// args = [username, email, md5_hash, sha256_hash, useragent, [domain]], return OK
function xmlrpc_create_email_md5_sha256_account($method, $args)
{
$user = $args[0];
$email = $args[1];
$md5_hash = $args[2];
$sha256_hash = $args[3];
$user_agent = $args[4];
$domain = get_domain($args[5]);
Logger::getInstance()->message("[XMLRPC] xmlrpc_create_email_md5_sha256_account(" . $user . ", " . $domain . ", " . $email . ")");
if (!check_parameter($user)) {
return MISSING_USERNAME_PARAM;
} elseif (!check_parameter($email, "email")) {
return MISSING_EMAIL_PARAM;
}
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$account->username = $user;
$account->domain = $domain;
if ($account->getOne()) {
return USERNAME_TAKEN;
}
if (!ALLOW_SAME_EMAILS_ON_MULTILPLE_ACCOUNTS) {
$email_account = new Account($db);
$email_account->email = $email;
if ($email_account->getOne()) {
return EMAIL_TAKEN;
}
}
if (GENERATE_PASSWORD_ENABLED) {
$pwd = generate_password();
$md5_hash = hash_password($user, $pwd, $domain, MD5);
$sha256_hash = hash_password($user, $pwd, $domain, SHA256);
}
$account->confirmation_key = uniqid();
$account->email = $email;
$account->user_agent = $user_agent;
$account->ip_address = getIp();
$account->activated = AUTO_ACTIVATE_ACCOUNT ? "1" : "0";
$account->create();
$md5_password = new Password($db);
$md5_password->account_id = $account->id;
$md5_password->password = $md5_hash;
$md5_password->algorithm = MD5;
$md5_password->create();
$sha256_password = new Password($db);
$sha256_password->account_id = $account->id;
$sha256_password->password = $sha256_hash;
$sha256_password->algorithm = SHA256;
$sha256_password->create();
if (CUSTOM_HOOKS) {
hook_on_account_created($account);
}
if (SEND_ACTIVATION_EMAIL && EMAIL_ENABLED) {
send_email_with_activation_link($email, $account->confirmation_key, $account->username, $account->domain, SHA256);
} elseif (AUTO_ACTIVATE_ACCOUNT) {
//TODO
/*if (USE_IN_APP_PURCHASES) {
$expiration = get_trial_expiration_date();
db_inapp_add_account($user, $domain, $expiration);
}*/
}
//We call this function to set the geoloc if enabled
// args needed = [username, ha1, firstname, lastname, gender, subscribe, [domain], [algo]]
//need username + domain
if (get_config_value("ENABLE_NEW_ACCOUNTS_GEOLOC", FALSE)) {
return update_account_user_info($account->username, $md5_hash, null, null, "unknown", '0', $account->domain, MD5);
}
return OK;
}
// args = [username, key, [domain], [algo]]
function xmlrpc_activate_email_account($method, $args)
{
$user = $args[0];
$key = $args[1];
$domain = get_domain($args[2]);
$algo = get_algo($args[3]);
Logger::getInstance()->message("[XMLRPC] xmlrpc_activate_account(" . $user . ", " . $domain . ", " . $key . ", " . $algo . ")");
if (!check_parameter($user)) {
return MISSING_USERNAME_PARAM;
} elseif ($algo == null) {
return ALGO_NOT_SUPPORTED;
}
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$account->username = $user;
$account->domain = $domain;
if (!$account->getOne()) {
return ACCOUNT_NOT_FOUND;
} elseif ($account->activated != "0") {
return ACCOUNT_ALREADY_ACTIVATED;
}
if (!is_key_matching($key, $account)) {
return KEY_DOESNT_MATCH;
}
if (!$account->activate()) {
Logger::getInstance()->error("Failed to activate account id " . $account->id);
}
$expiration = null;
// TODO
/*if (USE_IN_APP_PURCHASES) {
$expiration = get_trial_expiration_date();
db_inapp_add_account($user, $domain, $expiration);
}*/
if (CUSTOM_HOOKS) {
hook_on_account_activated($account);
}
$password = new Password($db);
$password->account_id = $account->id;
$password->algorithm = $algo;
if ($password->getOne()) {
return $password->password;
}
return PASSWORD_NOT_FOUND;
}
// args = [username, email, [domain]]
function xmlrpc_recover_email_account($method, $args)
{
$username = $args[0];
$email = $args[1];
$domain = get_domain($args[2]);
Logger::getInstance()->message("[XMLRPC] xmlrpc_recover_email_account(" . $username . ", " . $email . ", " . $domain . ")");
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$account->username = $username;
$account->domain = $domain;
if (!$account->getOne()) {
return ACCOUNT_NOT_FOUND;
}
if (strcasecmp($email, $account->email) != 0) { // Email case insensitive compare
return EMAIL_DOESNT_MATCH;
}
$account->confirmation_key = uniqid();
$account->update();
if (SEND_ACTIVATION_EMAIL && EMAIL_ENABLED) {
send_email_with_recover_key($email, $account->confirmation_key);
}
return OK;
}
// args = [username, password, new email, [domain], [algo]]
function xmlrpc_update_email($method, $args)
{
$user = $args[0];
$pwd = $args[1];
$new_email = $args[2];
$domain = get_domain($args[3]);
$algo = get_algo($args[4]);
Logger::getInstance()->message("[XMLRPC] xmlrpc_update_email(" . $user . ", " . $domain . ", " . $new_email . ", " . $algo . ")");
if (!check_parameter($user)) {
return MISSING_USERNAME_PARAM;
} elseif ($algo == null) {
return ALGO_NOT_SUPPORTED;
}
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$account->username = $user;
$account->domain = $domain;
if (!$account->getOne()) {
return ACCOUNT_NOT_FOUND;
}
$password = new Password($db);
$password->account_id = $account->id;
$password->algorithm = $algo;
if (!$password->getOne()) {
return PASSWORD_NOT_FOUND;
}
$hashed_old_password = hash_password($user, $pwd, $domain, $algo);
if (!password_match($password->password, $hashed_old_password)) {
return PASSWORD_DOESNT_MATCH;
}
if ($account->email == $new_email) {
Logger::getInstance()->warning("New email same as previous one");
return EMAIL_UNCHANGED;
}
if (!ALLOW_SAME_EMAILS_ON_MULTILPLE_ACCOUNTS) {
$email_account = new Account($db);
$email_account->email = $email;
if ($email_account->getOne()) {
return EMAIL_TAKEN;
}
}
$account->email = $new_email;
if ($account->update()) {
Logger::getInstance()->message("Email updated successfully");
return OK;
}
return NOK;
}
// args = [username, email, ha1, [domain], [algo]]
function xmlrpc_delete_email_account($method, $args)
{
$username = $args[0];
$email = $args[1];
$ha1 = $args[2];
$domain = get_domain($args[3]);
$algo = get_algo($args[4]);
Logger::getInstance()->message("[XMLRPC] xmlrpc_delete_email_account(" . $username . ", " . $email . ", " . $domain . ", " . $algo . ")");
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$account->username = $username;
$account->domain = $domain;
if (!$account->getOne()) {
return ACCOUNT_NOT_FOUND;
}
if ($email != $account->email) {
return EMAIL_DOESNT_MATCH;
}
$password = new Password($db);
$password->account_id = $account->id;
$password->algorithm = $algo;
if (!$password->getOne()) {
return PASSWORD_NOT_FOUND;
}
if ($ha1 != $password->password) {
return PASSWORD_DOESNT_MATCH;
}
if ($account->delete()) {
if ($password->delete()) {
$alias = new Alias($db);
$alias->account_id = $account->id;
$alias->delete();
$userinfo = new UserInfo($db);
$userinfo->account_id = $account->id;
$userinfo->delete();
return OK;
}
}
return NOK;
}
function xmlrpc_accounts_email_register_methods($server)
{
xmlrpc_server_register_method($server, 'create_email_account', 'xmlrpc_create_email_account');// args = [username, email, [hash], useragent, [domain], [algo]], return OK
xmlrpc_server_register_method($server, 'create_email_md5_sha256_account', 'xmlrpc_create_email_md5_sha256_account');// args = [username, email, md5_hash, sha256_hash, useragent, [domain]], return OK
xmlrpc_server_register_method($server, 'activate_email_account', 'xmlrpc_activate_email_account');// args = [username, key, [domain], [algo]], return ha1_password
xmlrpc_server_register_method($server, 'recover_email_account', 'xmlrpc_recover_email_account');// args = [username, email, [domain]], return OK
xmlrpc_server_register_method($server, 'update_email', 'xmlrpc_update_email');// args = [username, password, new email, [domain], [algo]], return OK
xmlrpc_server_register_method($server, 'delete_email_account', 'xmlrpc_delete_email_account');// args = [username, email, ha1, [domain], [algo]]
}

View file

@ -1,421 +0,0 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
include_once __DIR__ . '/../database/database.php';
include_once __DIR__ . '/../objects/account.php';
include_once __DIR__ . '/../objects/password.php';
include_once __DIR__ . '/../objects/alias.php';
include_once __DIR__ . '/../objects/user_info.php';
include_once __DIR__ . '/../misc/utilities.php';
include_once __DIR__ . '/../misc/user_info.php';
include_once __DIR__ . '/../misc/results_values.php';
// args = [phone, [username], [password], useragent, [domain], [lang], [algo]]
function xmlrpc_create_phone_account($method, $args)
{
$phone = $args[0];
$user = $args[1];
$hashed_password = $args[2];
$user_agent = $args[3];
$domain = get_domain($args[4]);
$lang = get_lang($args[5]);
$algo = get_algo($args[6]);
Logger::getInstance()->message("[XMLRPC] xmlrpc_create_phone_account(" . $user . ", " . $domain . ", " . $phone . ", " . $lang . ", " . $algo . ")");
if (!check_parameter($phone, "phone")) {
return MISSING_PHONE_PARAM;
} elseif (!startswith($phone, "+")) {
Logger::getInstance()->error("Phone doesn't start by +");
return PHONE_NOT_E164;
} elseif ($algo == null) {
return ALGO_NOT_SUPPORTED;
}
if (startswith($user, "+") && $user != $phone) {
return ALIAS_DOESNT_MATCH;
}
if (!check_parameter($user)) {
$user = $phone;
}
$recover_params = array(
0 => $phone,
1 => $domain,
2 => $lang,
);
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$account->username = $user;
$account->domain = $domain;
$alias = new Alias($db);
$alias->alias = $phone;
$alias->domain = $domain;
if ($account->getOne()) {
if (RECOVER_ACCOUNT_IF_EXISTS) {
$recovered_user = xmlrpc_recover_phone_account($method, $recover_params);
if ($recovered_user == $user) {
return OK;
}
return ACCOUNT_RECOVERY_IMPOSSIBLE;
}
return USERNAME_TAKEN;
} elseif ($alias->getOne()) {
if (RECOVER_ACCOUNT_IF_EXISTS) {
$recovered_user = xmlrpc_recover_phone_account($method, $recover_params);
if ($recovered_user == $user) {
return OK;
}
return ACCOUNT_RECOVERY_IMPOSSIBLE;
}
return PHONE_TAKEN;
}
$pwd = $hashed_password;
if (!check_parameter($hashed_password, "hashed password")) {
$pwd = generate_password();
$hashed_password = hash_password($user, $pwd, $domain, $algo);
}
$account->confirmation_key = generate_4_digits_code();
$account->user_agent = $user_agent;
$account->ip_address = getIp();
$account->activated = AUTO_ACTIVATE_ACCOUNT ? "1" : "0";
$account->create();
$password = new Password($db);
$password->account_id = $account->id;
$password->password = $hashed_password;
$password->algorithm = $algo;
$password->create();
if (CUSTOM_HOOKS) {
hook_on_account_created($account);
}
if (SEND_ACTIVATION_SMS) {
if (!SMS_API_ENABLED) {
// This is a hack to allow testing without sending SMS
return OK;
}
$ok = send_sms($phone, $account->confirmation_key, $lang);
return $ok;
} elseif (AUTO_ACTIVATE_ACCOUNT) {
if (USE_IN_APP_PURCHASES) {
//TODO
/*$expiration = get_trial_expiration_date();
db_inapp_add_account($user, $domain, $expiration);*/
}
}
//We call this function to set the geoloc if enabled
// args needed = [username, ha1, firstname, lastname, gender, subscribe, [domain], [algo]]
//need username + domain
if (get_config_value("ENABLE_NEW_ACCOUNTS_GEOLOC", FALSE)) {
return update_account_user_info($account->username, $hashed_password, null, null, "unknown", '0', $account->domain, $algo);
}
return OK;
}
// args = [phone, username, key, [domain], [algo]]
function xmlrpc_activate_phone_account($method, $args)
{
$phone = $args[0];
$user = $args[1];
$key = $args[2];
$domain = get_domain($args[3]);
$algo = get_algo($args[4]);
Logger::getInstance()->message("[XMLRPC] xmlrpc_activate_phone_account(" . $user . ", " . $domain . ", " . $phone . ", " . $key . ", " . $algo . ")");
if (!check_parameter($phone, "phone")) {
return MISSING_PHONE_PARAM;
} elseif (!check_parameter($user)) {
return MISSING_USERNAME_PARAM;
} elseif (!startswith($phone, "+")) {
Logger::getInstance()->error("Phone doesn't start by +");
return PHONE_NOT_E164;
}
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$account->username = $user;
$account->domain = $domain;
if (!$account->getOne()) {
return ACCOUNT_NOT_FOUND;
}
if (!is_key_matching($key, $account)) {
return KEY_DOESNT_MATCH;
}
// If this is a recovery, account is already activated, don't go through the following again
if (!is_activated($account->activated)) {
$expiration = null;
if (!$account->activate()) {
Logger::getInstance()->error("Failed to activate account id " . $account->id);
}
$alias = new Alias($db);
$alias->account_id = $account->id;
$alias->alias = $phone;
$alias->domain = $account->domain;
$alias->create();
if (USE_IN_APP_PURCHASES) {
$expiration = get_trial_expiration_date();
//db_inapp_add_account($user, $domain, $expiration);
//TODO
}
if (CUSTOM_HOOKS) {
hook_on_account_activated($account);
}
}
$password = new Password($db);
$password->account_id = $account->id;
$password->algorithm = $algo;
if ($password->getOne()) {
return $password->password;
}
return PASSWORD_NOT_FOUND;
}
// args = [phone, [domain], [lang]]
function xmlrpc_recover_phone_account($method, $args)
{
// Is this function overloaded
if (XMLRPC_RECOVER_PHONE_ACCOUNT_OVERLOAD === true) {
return xmlrpc_recover_phone_account_overload($method, $args);
}
$phone = $args[0];
$domain = get_domain($args[1]);
$lang = get_lang($args[2]);
Logger::getInstance()->message("[XMLRPC] xmlrpc_recover_phone_account(" . $phone . ", " . $domain . ", " . $lang . ")");
if (!check_parameter($phone, "phone")) {
return MISSING_PHONE_PARAM;
} elseif (!startswith($phone, "+")) {
return PHONE_NOT_E164;
}
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$account->username = $phone;
$account->domain = $domain;
$alias = new Alias($db);
$alias->alias = $phone;
$alias->domain = $domain;
if (!$account->getOne()) {
if ($alias->getOne()) {
$account->id = $alias->account_id;
// This time the search will be done on the id instead of couple username / domain
if (!$account->getOne()) {
return ACCOUNT_NOT_FOUND;
}
} else {
return ACCOUNT_NOT_FOUND;
}
}
if (SEND_ACTIVATION_SMS) {
$account->confirmation_key = generate_4_digits_code();
$account->update();
if (!SMS_API_ENABLED) {
// This is a hack to allow testing without sending SMS
return $account->username;
}
$ok = send_sms($phone, $account->confirmation_key, $lang);
if ($ok != OK) {
return $ok;
}
}
return $account->username;
}
// args = [username, phone, ha1, [domain], [algo]]
function xmlrpc_delete_phone_account($method, $args)
{
$username = $args[0];
$phone = $args[1];
$ha1 = $args[2];
$domain = get_domain($args[3]);
$algo = get_algo($args[4]);
Logger::getInstance()->message("[XMLRPC] xmlrpc_delete_phone_account(" . $username . ", " . $phone . ", " . $domain . ", " . $algo . ")");
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$account->username = $username;
$account->domain = $domain;
if (!$account->getOne()) {
return ACCOUNT_NOT_FOUND;
}
if ($phone != $username && $phone != $account->alias) {
return ALIAS_DOESNT_MATCH;
}
$password = new Password($db);
$password->account_id = $account->id;
$password->algorithm = $algo;
if (!$password->getOne()) {
return PASSWORD_NOT_FOUND;
}
if ($ha1 != $password->password) {
return PASSWORD_DOESNT_MATCH;
}
if ($account->delete()) {
if ($password->delete()) {
$alias = new Alias($db);
$alias->account_id = $account->id;
$alias->delete();
$userinfo = new UserInfo($db);
$userinfo->account_id = $account->id;
$userinfo->delete();
return OK;
}
}
return NOK;
}
// args = [phone, [domain]]
function xmlrpc_is_phone_number_used($method, $args)
{
$phone = $args[0];
$domain = get_domain($args[1]);
Logger::getInstance()->message("[XMLRPC] xmlrpc_is_phone_number_used(" . $phone . ", " . $domain . ")");
if (!check_parameter($phone, "phone")) {
return MISSING_PHONE_PARAM;
} elseif (!startswith($phone, "+")) {
return PHONE_NOT_E164;
}
$database = new Database();
$db = $database->getConnection();
$alias = new Alias($db);
$alias->alias = $phone;
$alias->domain = $domain;
if ($alias->getOne()) {
return OK_ALIAS;
}
$account = new Account($db);
$account->username = $phone;
$account->domain = $domain;
if ($account->getOne()) {
return OK_ACCOUNT;
}
return NOK;
}
// args = [username, [domain]]
function xmlrpc_get_phone_number_for_account($method, $args)
{
$user = $args[0];
$domain = get_domain($args[1]);
Logger::getInstance()->message("[XMLRPC] xmlrpc_get_phone_number_for_account(" . $user . ")");
if (!check_parameter($user)) {
return MISSING_USERNAME_PARAM;
}
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$account->username = $user;
$account->domain = $domain;
if (!$account->getOne()) {
$alias = new Alias($db);
$alias->alias = $user;
$alias->domain = $domain;
if ($alias->getOne()) {
return $user;
}
return ACCOUNT_NOT_FOUND;
}
$phone = $account->alias;
if ($phone == null) {
return ALIAS_NOT_FOUND;
}
if (RECOVER_ACCOUNT_IF_EXISTS) {
return ACCOUNT_NOT_FOUND;
}
return $phone;
}
function xmlrpc_accounts_phone_register_methods($server)
{
xmlrpc_server_register_method($server, 'create_phone_account', 'xmlrpc_create_phone_account');// args = [phone, [username], [password], useragent, [domain], [lang], [algo]], return OK
xmlrpc_server_register_method($server, 'activate_phone_account', 'xmlrpc_activate_phone_account');// args = [phone, username, key, [domain], [algo]], return ha1_password
xmlrpc_server_register_method($server, 'recover_phone_account', 'xmlrpc_recover_phone_account');// args = [phone, [domain], [lang]], return username
xmlrpc_server_register_method($server, 'delete_phone_account', 'xmlrpc_delete_phone_account');// args = [username, phone, ha1, [domain], [algo]]
xmlrpc_server_register_method($server, 'is_phone_number_used', 'xmlrpc_is_phone_number_used');// args = [phone], return OK_ACCOUNT, OK_ALIAS or NOK
xmlrpc_server_register_method($server, 'get_phone_number_for_account', 'xmlrpc_get_phone_number_for_account');// args = [username, [domain]], return a phone number or an error
}

View file

@ -1,78 +0,0 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
include_once __DIR__ . '/../database/database.php';
include_once __DIR__ . '/../objects/account.php';
include_once __DIR__ . '/../objects/password.php';
include_once __DIR__ . '/../objects/alias.php';
include_once __DIR__ . '/../objects/user_info.php';
include_once __DIR__ . '/../misc/utilities.php';
include_once __DIR__ . '/accounts_email.php';
include_once __DIR__ . '/accounts_phone.php';
include_once __DIR__ . '/../misc/results_values.php';
function activate_email_account($user, $domain, $key, $algo) {
$domain = get_domain($domain);
$algo = get_algo($algo);
Logger::getInstance()->message("[HTTP] activate_email_account(" . $user . ", " . $domain . ", " . $key . ", " . $algo . ")");
if (!check_parameter($user)) {
return MISSING_USERNAME_PARAM;
} elseif ($algo == null) {
return ALGO_NOT_SUPPORTED;
}
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$account->username = $user;
$account->domain = $domain;
if (!$account->getOne()) {
Logger::getInstance()->error("[HTTP] Account not found");
return ACCOUNT_NOT_FOUND;
} elseif ($account->activated != "0") {
Logger::getInstance()->warning("[HTTP] Account already activated");
return ACCOUNT_ALREADY_ACTIVATED;
}
if (!is_key_matching($key, $account)) {
Logger::getInstance()->error("[HTTP] Key doesn't match");
return KEY_DOESNT_MATCH;
}
if (!$account->activate()) {
Logger::getInstance()->error("[HTTP] Failed to activate account id " . $account->id);
return;
}
Logger::getInstance()->message("[HTTP] Account activated");
}
$user = $_GET["username"];
$domain = $_GET["domain"];
$key = $_GET["confirmation_key"];
$algo = $_GET["algo"];
activate_email_account($user, $domain, $key, $algo);
?>

View file

@ -1,204 +0,0 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
include_once __DIR__ . '/../database/database.php';
include_once __DIR__ . '/../objects/account.php';
include_once __DIR__ . '/../objects/password.php';
include_once __DIR__ . '/../objects/alias.php';
include_once __DIR__ . '/../misc/utilities.php';
include_once __DIR__ . '/../misc/results_values.php';
// args = [phone, [domain]]
function xmlrpc_is_alias_used($method, $args)
{
$phone = $args[0];
$domain = get_domain($args[1]);
Logger::getInstance()->message("[XMLRPC] xmlrpc_is_alias_used(" . $phone . ", " . $domain . ")");
if (!check_parameter($phone, "phone")) {
return MISSING_PHONE_PARAM;
} elseif (!startswith($phone, "+")) {
return PHONE_NOT_E164;
}
$database = new Database();
$db = $database->getConnection();
$alias = new Alias($db);
$alias->alias = $phone;
$alias->domain = $domain;
if (!$alias->getOne()) {
return ALIAS_NOT_FOUND;
}
return OK;
}
// args = [phone, account, [domain], [lang]]
function xmlrpc_link_phone_number_with_account($method, $args)
{
$phone = $args[0];
$user = $args[1];
$domain = get_domain($args[2]);
$lang = get_lang($args[3]);
Logger::getInstance()->message("[XMLRPC] xmlrpc_link_phone_number_with_account(" . $user . ", " . $domain . ", " . $phone . ", " . $lang . ")");
if (!check_parameter($phone)) {
return MISSING_PHONE_PARAM;
} elseif (!check_parameter($user)) {
return MISSING_USERNAME_PARAM;
} elseif (!startswith($phone, "+")) {
return PHONE_NOT_E164;
/*} else if (db_alias_is_in_use($phone, $domain)) {
return PHONE_TAKEN;*/
}
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$account->username = $user;
$account->domain = $domain;
if (!$account->getOne()) {
return ACCOUNT_NOT_FOUND;
}
if (SEND_ACTIVATION_SMS) {
if (!SMS_API_ENABLED) {
// This is a hack to allow testing without sending SMS
return OK;
}
$account->confirmation_key = generate_4_digits_code();
$account->update();
$ok = send_sms($phone, $account->confirmation_key, $lang);
return $ok;
}
return SMS_DISABLED;
}
// args = [phone, user, key, ha1, [domain], [algo]]
function xmlrpc_activate_phone_number_link($method, $args)
{
$phone = $args[0];
$user = $args[1];
$key = $args[2];
$ha1 = $args[3];
$domain = get_domain($args[4]);
$algo = get_algo($args[5]);
Logger::getInstance()->message("[XMLRPC] xmlrpc_activate_phone_number_link(" . $user . ", " . $domain . ", " . $phone . ", " . $key . ", " . $algo . ")");
if (!check_parameter($phone, "phone")) {
return MISSING_PHONE_PARAM;
} elseif (!check_parameter($user)) {
return MISSING_USERNAME_PARAM;
} elseif (!startswith($phone, "+")) {
return PHONE_NOT_E164;
}
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$account->username = $user;
$account->domain = $domain;
if (!$account->getOne()) {
return ACCOUNT_NOT_FOUND;
}
if (!is_activated($account->activated)) {
return ACCOUNT_NOT_YET_ACTIVATED;
}
if (!is_key_matching($key, $account)) {
return KEY_DOESNT_MATCH;
}
$password = new Password($db);
$password->account_id = $account->id;
$password->algorithm = $algo;
if (!$password->getOne()) {
return PASSWORD_NOT_FOUND;
}
if (!password_match($password->password, $ha1)) {
return PASSWORD_DOESNT_MATCH;
}
$alias = new Alias($db);
$alias->alias = $phone;
$alias->domain = $domain;
if ($alias->getOne()) {
$alias->account_id = $account->id;
$alias->update();
} else {
$alias->account_id = $account->id;
$alias->create();
}
return OK;
}
// args = [phone, [domain]]
function xmlrpc_get_alias($method, $args)
{
$phone = $args[0];
$domain = get_domain($args[1]);
Logger::getInstance()->message("[XMLRPC] xmlrpc_get_alias(" . $phone . ", " . $domain . ")");
if (!check_parameter($phone, "phone")) {
return MISSING_PHONE_PARAM;
} elseif (!startswith($phone, "+")) {
return PHONE_NOT_E164;
}
$database = new Database();
$db = $database->getConnection();
$alias = new Alias($db);
$alias->alias = $phone;
$alias->domain = $domain;
if (!$alias->getOne()) {
return ALIAS_NOT_FOUND;
}
$account = new Account($db);
$account->id = $alias->account_id;
if ($account->getOne()) {
return $account->username;
}
return ACCOUNT_NOT_FOUND;
}
function xmlrpc_aliases_register_methods($server)
{
xmlrpc_server_register_method($server, 'is_alias_used', 'xmlrpc_is_alias_used');// args = [phone, [domain]], return OK
xmlrpc_server_register_method($server, 'link_phone_number_with_account', 'xmlrpc_link_phone_number_with_account');// args = [phone, account, [domain], [lang]], return OK
xmlrpc_server_register_method($server, 'activate_phone_number_link', 'xmlrpc_activate_phone_number_link');// args = [phone, user, key, ha1, [domain], [algo]], return OK
xmlrpc_server_register_method($server, 'get_alias', 'xmlrpc_get_alias');// args = [phone, [domain]], return username
}

View file

@ -1,188 +0,0 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
include_once __DIR__ . '/../database/database.php';
include_once __DIR__ . '/../objects/account.php';
include_once __DIR__ . '/../objects/password.php';
include_once __DIR__ . '/../misc/utilities.php';
// Nonce are one-time usage, in order to avoid storing them in a table
// The nonce is built using:
// - timestamp : nonce is valid for MIN_NONCE_VALIDITY_PERIOD seconds at minimum and twice it at maximum (our goal is one time usage anyway, typical value shall be 10 )
// - request content : the response uses only the URI, enforce the content to be the same so the nonce is actually a one time usage
// a replay is not devastating (it would just be an actual replay, not a different command to server)
// - secret key : avoid an attacker to be able to generate a valid nonce
function auth_get_valid_nonces()
{
$request = file_get_contents('php://input');
$time = time();
$time -= $time%MIN_NONCE_VALIDITY_PERIOD; // our nonce will be valid at leat MIN_NONCE_VALIDITY_PERIOD seconds and max twice it, so floor the timestamp
return array(
hash_hmac("sha256", $time.':'.$request, AUTH_NONCE_KEY),
hash_hmac("sha256", $time-MIN_NONCE_VALIDITY_PERIOD.':'.$request, AUTH_NONCE_KEY));
}
function request_authentication($realm = "sip.example.org", $username = null)
{
$has_md5 = false;
$has_sha256 = false;
if ($username != null) {
// Get the password/hash from database to include only available password hash in the authenticate header
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$account->username = $username;
if (!$account->getOne()) {
Logger::getInstance()->error("Couldn't find account " . (string)$account);
return null;
}
$pwd = new Password($db);
$pwd->account_id = $account->id;
$stmt = $pwd->getAll();
$num = $stmt->rowCount();
if ($num <= 0) {
Logger::getInstance()->error("Couldn't find password " . (string)$pwd);
return null;
}
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
extract($row);
// Generate the valid response
switch ($algorithm) {
case 'CLRTXT':
$has_md5 = true;
$has_sha256 = true;
break;
case 'MD5':
$has_md5 = true;
break;
case 'SHA-256':
$has_sha256 = true;
break;
default:
Logger::getInstance()->error("Digest error : Given algorithm '" . $algorithm . "' is invalid (neither of 'CLRTXT', 'MD5', 'SHA-256')");
}
}
} else { // we don't have the username, authorize both MD5 and SHA256
$has_md5 = true;
$has_sha256 = true;
Logger::getInstance()->debug("Username not found, replying with both auth anyway");
}
if (($has_md5 || $has_sha256) == false) {
// reply anyway with both hash authorized
$has_md5 = true;
$has_sha256 = true;
Logger::getInstance()->debug("Doesn't have MD5 or SHA-256, replying with both auth anyway");
}
header('HTTP/1.1 401 Unauthorized');
if ($has_md5 == true) {
header('WWW-Authenticate: Digest realm="' . $realm.
'",qop="auth",algorithm=MD5,nonce="' . auth_get_valid_nonces()[0] . '",opaque="' . md5($realm) . '"');
}
if ($has_sha256 == true) {
header('WWW-Authenticate: Digest realm="' . $realm.
'",qop="auth",algorithm=SHA-256,nonce="' . auth_get_valid_nonces()[0] . '",opaque="' . md5($realm) . '"', false);
}
exit();
}
function authenticate($auth_digest, $realm = "sip.example.org")
{
Logger::getInstance()->debug("Authenticate : Digest ".(print_r($auth_digest, true))." realm " . $realm);
// Parse the client authentication data in 3 arrays.
// One containing raw auth_digest, the second containing keys and the third containing values
preg_match_all('@(realm|username|nonce|uri|nc|cnonce|qop|response|opaque|algorithm)=[\'"]?([^\'",]+)@', $auth_digest, $a);
//Combining array of keys and array of values to get a dictionary
$data = array_combine($a[1], $a[2]);
// Get the password/hash from database
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$account->username = $data['username'];
$account->domain = empty($data['domain']) ? SIP_DOMAIN : $data['domain'];
if (!$account->getOne()) {
Logger::getInstance()->error("Couldn't find account " . (string)$account);
return null;
}
$pwd = new Password($db);
$pwd->account_id = $account->id;
$stmt = $pwd->getAll();
$num = $stmt->rowCount();
if ($num <= 0) {
Logger::getInstance()->error("Couldn't find password " . (string)$pwd);
return null;
}
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
extract($row);
// Generate the valid response
switch ($algorithm) {
case 'CLRTXT':
$A1 = md5($data['username'].':'.$data['realm'].':'.$password);
$A2 = md5(getenv('REQUEST_METHOD').':'.$data['uri']);
$valid_response = md5($A1.':'.$data['nonce'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.$A2);
break;
case 'MD5':
$A1 = $password; // username:realm:password
$A2 = md5(getenv('REQUEST_METHOD').':'.$data['uri']);
$valid_response = md5($A1.':'.$data['nonce'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.$A2);
break;
case 'SHA-256':
$A1 = $password; // username:realm:password
$A2 = hash('sha256', getenv('REQUEST_METHOD').':'.$data['uri']);
$valid_response = hash('sha256', $A1.':'.$data['nonce'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.$A2);
break;
default:
Logger::getInstance()->error("Digest error : Given algorithm '" . $algorithm . "' is invalid (neither of 'CLRTXT', 'MD5', 'SHA-256')");
}
// Compare with the client response
if ($data['response'] === $valid_response) {
return $data['username'];
}
Logger::getInstance()->debug("Digest : received username=" . $data['username']);
Logger::getInstance()->debug("Digest : received realm=" . $data['realm']);
Logger::getInstance()->debug("Digest : computed A1 hashed([username]:[realm]:[password])=" . $A1);
Logger::getInstance()->debug("Digest : received method=" . getenv('REQUEST_METHOD'));
Logger::getInstance()->debug("Digest : received uri=" . $data['uri']);
Logger::getInstance()->debug("Digest : computed A2 hashed([request_method]:[uri])='" . $A2);
Logger::getInstance()->debug("Digest : received nonce=" . $data['nonce']);
Logger::getInstance()->debug("Digest : received nc=" . $data['nc']);
Logger::getInstance()->debug("Digest : received cnonce=" . $data['cnonce']);
Logger::getInstance()->debug("Digest : received qop=" . $data['qop']);
Logger::getInstance()->debug("Digest : computed A2 hashed([request_method]:[uri])=" . $A2);
Logger::getInstance()->debug("Digest : expected response hashed([A1]:[nonce]:[nc]:[cnonce]:[qop]:[A2])=" . $valid_response);
Logger::getInstance()->debug("Digest : got instead response ([request_method]:[uri])=" . $data['response']);
}
Logger::getInstance()->error("Failed to authenticate request");
return null;
}

View file

@ -1,55 +0,0 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
include_once __DIR__ . '/../database/database.php';
include_once __DIR__ . '/../objects/device.php';
include_once __DIR__ . '/../misc/results_values.php';
// args = [manufacturer, model, status, delay, hasHEC]
function xmlrpc_add_ec_calibration_result($method, $args)
{
$manufacturer = $args[0];
$model = $args[1];
$status = $args[2];
$delay = $args[3];
$hasHEC = 0;
if (count($args) == 5) {
$hasHEC = (int)$args[4];
}
$database = new Database();
$db = $database->getConnection();
$device = new Device($db);
$device->manufacturer = $manufacturer;
$device->model = $model;
$device->status = $status;
$device->delay = $delay;
$device->hardware_echo_canceller = $hasHEC;
$device->create();
return OK;
}
function xmlrpc_devices_register_methods($server)
{
xmlrpc_server_register_method($server, 'add_ec_calibration_result', 'xmlrpc_add_ec_calibration_result');// args = [manufacturer, model, status, delay, hasHEC]
}

View file

@ -1,415 +0,0 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Google/Android specifics
// Get an access token to access Google APIs
function get_google_access_token()
{
$ch = curl_init(GOOGLE_API_OAUTH_URL);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FAILONERROR, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/x-www-form-urlencoded'
));
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(array(
'client_id' => GOOGLE_PROJECT_ID,
'client_secret' => GOOGLE_PROJECT_PASSWORD,
'refresh_token' => GOOGLE_PROJECT_REFRESH_TOKEN,
'grant_type' => "refresh_token",
)));
$result = curl_exec($ch);
curl_close($ch);
$json = json_decode($result, true);
$token = $json["access_token"];
mylog("[GOOGLE] Access token is " . $token);
return $token;
}
// Query Google for the expiration time given the transaction token as described here: https://developers.google.com/android-publisher/api-ref/purchases/subscriptions/get
function get_expiration_for_android_token_and_subscription($token, $subscription)
{
$google_access_token = get_google_access_token();
$url = "https://www.googleapis.com/androidpublisher/v2/applications/" . ANDROID_PACKAGE . "/purchases/subscriptions/" . $subscription . "/tokens/" . $token . "?access_token=" . $google_access_token;
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
$result = curl_exec($ch);
curl_close($ch);
$json = json_decode($result, true);
$expiration = $json["expiryTimeMillis"];
mylog("[GOOGLE] expire timestamp for token = " . $token . " and product id = " . $subscription . " is " . $expiration);
return $expiration . "";
}
// Returns 1 if the payload/signature has been issued by Google.
function check_google_signature($payload, $signature)
{
$certFile = fopen(ANDROID_PUB_KEY_PATH, "r");
$cert = fread($certFile, 8192);
fclose($certFile);
$pubKeyId = openssl_get_publickey($cert);
$ok = openssl_verify($payload, base64_decode($signature), $pubKeyId, OPENSSL_ALGO_SHA1);
mylog("[GOOGLE] signature verification result is " . $ok);
return $ok;
}
// End of Google/Android specifics
// Apple/iOS specifics
function get_apple_receipt($payload)
{
$ch = curl_init(APPLE_URL);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FAILONERROR, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(array('receipt-data' => $payload, 'password' => APPLE_SECRET)));
$result = curl_exec($ch);
curl_close($ch);
mylog("[APPLE] decoded receipt is " . $result);
$json = json_decode($result, true);
$status_code = $json["status"];
if ($status_code == 21007) {
mylog("[APPLE] Error 21007 found, sending receipt to sandbox instead of production");
$ch = curl_init(APPLE_SANDBOX_URL);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FAILONERROR, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(array('receipt-data' => $payload, 'password' => APPLE_SECRET)));
$result = curl_exec($ch);
curl_close($ch);
mylog("[APPLE] decoded receipt is " . $result);
$json = json_decode($result, true);
}
return $json;
}
// Returns 1 if the payload/signature has been signed by Apple, else will return the error code as described here: https://developer.apple.com/library/ios/releasenotes/General/ValidateAppStoreReceipt/Chapters/ValidateRemotely.html#//apple_ref/doc/uid/TP40010573-CH104-SW1
function check_apple_signature($payload)
{
$status = -1;
$status = $payload["status"];
mylog("[APPLE] Status in apple receipt is " . $status);
if ($status == 0) {
return 1;
}
return $status;
}
function parse_apple_receipt_get_expiration($user, $domain, $json)
{
$last_used = db_inapp_get_last_used_field($user, $domain);
$days = 0;
$receipt = $json["receipt"];
$in_app = $receipt["in_app"];
foreach ($in_app as $item => $value) {
if (array_key_exists("original_purchase_date_ms", $value) and array_key_exists("product_id", $value)) {
$purchase_date = $value["original_purchase_date_ms"];
$product_id = $value["product_id"];
if ($purchase_date > $last_used) {
$days_bought = 0;
if (endswith($product_id, "1_month")) {
$days_bought = 30;
} elseif (endswith($product_id, "1_year")) {
$days_bought = 365;
} else {
mylog("[ERROR] Unknown duration for product ID " . $product_id);
continue;
}
if (startswith($product_id, "test.")) {
mylog("[APPLE] Test mode detected, time accelerated (1 month => 1 minute)");
$days_bought /= 43200;
}
if ($days_bought > 0) {
$days = $days + $days_bought;
db_inapp_update_last_used_field($user, $domain, $purchase_date);
}
}
}
}
if ($days <= 0) {
mylog("[WARN] [APPLE] Either no receipt or all receipts have already been consumed");
return 0;
}
$millis = 86400000 * $days;
$now = get_trial_expiration_date();
$expiration = db_inapp_get_expiration_date($user, $domain);
$max = max($now, $expiration);
$expiration_date = $max + $millis;
mylog("[APPLE] Adding " . $days . " days to current expiration date (= " . $millis . " ms). New expiration date is " . $expiration_date);
return $expiration_date;
}
// End of Apple/iOS specifics
// XMLRPC methods
// Returns 1 if the payload/signature has been signed by either Google or Apple, depending on $os.
function check_signature($os, $payload, $signature)
{
if (strcmp($os, "google") == 0) {
return check_google_signature($payload, $signature);
} elseif (strcmp($os, "apple") == 0) {
return check_apple_signature($payload);
}
return -2;
}
// args = [username, ha1, [domain]]
function xmlrpc_is_account_trial($method, $args)
{
$user = $args[0];
$password = $args[1];
$domain = get_domain($args[2]);
mylog("[XMLRPC] xmlrpc_is_account_trial(" . $user . ", " . $domain . ")");
if (!check_parameter($user)) {
return "ERROR_USERNAME_PARAMETER_NOT_FOUND";
}
if (!db_account_is_existing($user, $domain)) {
mylog("[ERROR] User account " . $user . " / " . $domain . " doesn't exist");
return "ERROR_ACCOUNT_DOESNT_EXIST";
} else {
$hashed_password = hash_password($user, $password, $domain);
$db_hashed_password = db_account_get_password($user, $domain);
if (strcmp($hashed_password, $db_hashed_password) != 0 and strcmp($password, $db_hashed_password) != 0) {
mylog("[ERROR] Password doesn't match");
return "ERROR_PASSWORD_DOESNT_MATCH";
}
}
if (!USE_IN_APP_PURCHASES || !db_inapp_is_account($user, $domain)) {
return "ERROR_NO_EXPIRATION";
}
if (db_inapp_is_account_trial($user, $domain)) {
return "OK";
} else {
return "NOK";
}
}
// args = [username, ha1, [domain]]
function xmlrpc_is_account_expired($method, $args)
{
$user = $args[0];
$password = $args[1];
$domain = get_domain($args[2]);
mylog("[XMLRPC] xmlrpc_is_account_expired(" . $user . ", " . $domain . ")");
if (!check_parameter($user)) {
return "ERROR_USERNAME_PARAMETER_NOT_FOUND";
}
if (!db_account_is_existing($user, $domain)) {
mylog("[ERROR] User account " . $user . " / " . $domain . " doesn't exist");
return "ERROR_ACCOUNT_DOESNT_EXIST";
} else {
$hashed_password = hash_password($user, $password, $domain);
$db_hashed_password = db_account_get_password($user, $domain);
if (strcmp($hashed_password, $db_hashed_password) != 0 and strcmp($password, $db_hashed_password) != 0) {
mylog("[ERROR] Password doesn't match");
return "ERROR_PASSWORD_DOESNT_MATCH";
}
}
if (!USE_IN_APP_PURCHASES || !db_inapp_is_account($user, $domain)) {
return "ERROR_NO_EXPIRATION";
}
$expiration = db_inapp_get_expiration_date($user, $domain);
$now_date = new DateTime('now');
$now = $now_date->getTimestamp() * 1000;
if ($now > $expiration) {
return "OK";
} else {
return "NOK";
}
}
// args = [payload, signature]
function xmlrpc_check_payload_signature($method, $args)
{
$payload = $args[0];
$signature = $args[1];
mylog("[XMLRPC] xmlrpc_check_payload_signature(payload, signature)");
$result = 0;
$os = "google";
$payloadJson = $payload;
if ($signature == "") {
$payloadJson = get_apple_receipt($payload);
$os = "apple";
}
$result = check_signature($os, $payloadJson, $signature);
if ($result == 1) {
return "OK";
}
return "NOK";
}
// args = [username, ha1, [domain], payload, signature=""]
function xmlrpc_update_expiration_date($method, $args)
{
$user = $args[0];
$password = $args[1];
$payload = $args[3];
$signature = $args[4];
$domain = get_domain($args[2]);
mylog("[XMLRPC] xmlrpc_update_expiration_date(" . $user . ", " . $domain . ", payload, signature)");
if (!check_parameter($user)) {
return "ERROR_USERNAME_PARAMETER_NOT_FOUND";
}
if (!db_account_is_existing($user, $domain)) {
mylog("[ERROR] User account " . $user . " / " . $domain . " doesn't exist");
return "ERROR_ACCOUNT_DOESNT_EXIST";
} elseif (!db_account_is_activated($user, $domain)) {
mylog("[ERROR] User account " . $user . " / " . $domain . " isn't activated");
return "ERROR_ACCOUNT_NOT_ACTIVATED";
} else {
$hashed_password = hash_password($user, $password, $domain);
$db_hashed_password = db_account_get_password($user, $domain);
if (strcmp($hashed_password, $db_hashed_password) != 0 and strcmp($password, $db_hashed_password) != 0) {
mylog("[ERROR] Password doesn't match");
return "ERROR_PASSWORD_DOESNT_MATCH";
}
}
if (!USE_IN_APP_PURCHASES || !db_inapp_is_account($user, $domain)) {
return "ERROR_NO_EXPIRATION";
}
$result = 0;
$os = "google";
$payloadJson = $payload;
if ($signature == "") {
$payloadJson = get_apple_receipt($payload);
$os = "apple";
}
$result = check_signature($os, $payloadJson, $signature);
if ($result == 1) {
$expiration_date = 0;
if (strcmp($os, "google") == 0) {
$json = json_decode($payload, true);
$token = $json["purchaseToken"];
$subscription = $json["productId"];
$expiration_date = get_expiration_for_android_token_and_subscription($token, $subscription);
} elseif (strcmp($os, "apple") == 0) {
$expiration_date = parse_apple_receipt_get_expiration($user, $domain, $payloadJson);
}
if ($expiration_date >= 0) {
if ($expiration_date > 0) {
db_inapp_update_trial($user, $domain, 0);
db_inapp_update_expiration_date($user, $domain, $expiration_date);
/*if (CUSTOM_HOOKS) {
hook_on_expiration_date_updated($user, $domain, $expiration_date, $payloadJson, $os);
}*/
return $expiration_date . "";
} else {
return db_inapp_get_expiration_date($user, $domain) . "";
}
} else {
mylog("[ERROR] Expiration is " . $expiration_date);
}
}
mylog("[ERROR] Couldn't verify signature of payload...");
return "ERROR_SIGNATURE_VERIFICATION_FAILED";
}
// args = [username, ha1, [domain]]
function xmlrpc_get_account_expiration($method, $args)
{
$user = $args[0];
$password = $args[1];
$domain = get_domain($args[2]);
mylog("[XMLRPC] xmlrpc_get_account_expiration(" . $user . ")");
if (!check_parameter($user)) {
return "ERROR_USERNAME_PARAMETER_NOT_FOUND";
}
if (!db_account_is_existing($user, $domain)) {
mylog("[ERROR] User account " . $user . " doesn't exist");
return "ERROR_ACCOUNT_DOESNT_EXIST";
} elseif (!db_account_is_activated($user, $domain)) {
mylog("[ERROR] User account " . $user . " isn't activated");
return "ERROR_ACCOUNT_NOT_ACTIVATED";
} else {
$hashed_password = hash_password($user, $password, $domain);
$db_hashed_password = db_account_get_password($user, $domain);
if (strcmp($hashed_password, $db_hashed_password) != 0 and strcmp($password, $db_hashed_password) != 0) {
mylog("[ERROR] Password doesn't match");
return "ERROR_PASSWORD_DOESNT_MATCH";
}
}
if (!USE_IN_APP_PURCHASES || !db_inapp_is_account($user, $domain)) {
return "ERROR_NO_EXPIRATION";
}
$expiration = db_inapp_get_expiration_date($user, $domain);
return $expiration . "";
}
function xmlrpc_inapp_register_methods($server)
{
xmlrpc_server_register_method($server, 'is_account_trial', 'xmlrpc_is_account_trial');// args = [username, ha1, [domain]]
xmlrpc_server_register_method($server, 'is_account_expired', 'xmlrpc_is_account_expired');// args = [username, ha1, [domain]]
xmlrpc_server_register_method($server, 'get_account_expiration', 'xmlrpc_get_account_expiration');// args = [username, ha1, [domain]]
xmlrpc_server_register_method($server, 'update_expiration_date', 'xmlrpc_update_expiration_date');// args = [username, ha1, [domain], payload, [signature]]
xmlrpc_server_register_method($server, 'check_payload_signature', 'xmlrpc_check_payload_signature');// args = [payload, signature]
}

View file

@ -1,153 +0,0 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
include_once __DIR__ . '/../database/database.php';
include_once __DIR__ . '/../objects/account.php';
include_once __DIR__ . '/../objects/password.php';
include_once __DIR__ . '/../objects/alias.php';
include_once __DIR__ . '/../misc/utilities.php';
include_once __DIR__ . '/../misc/results_values.php';
// args = [user, pwd, [domain], [algo]]
// /!\ This method must be used for tests purposes only /!\
function xmlrpc_get_confirmation_key($method, $args)
{
$user = $args[0];
$pwd = $args[1];
$domain = get_domain($args[2]);
$algo = get_algo($args[3]);
Logger::getInstance()->message("[XMLRPC] xmlrpc_get_confirmation_key(" . $user . ", " . $domain . ", " . $algo . ")");
if (!check_parameter($user)) {
return MISSING_USERNAME_PARAM;
} elseif (!ALLOW_TEST_ACCOUNTS) {
Logger::getInstance()->error("Non test account unauthorized");
return TEST_ACCOUNTS_DISABLED;
} elseif ($algo == null) {
return ALGO_NOT_SUPPORTED;
}
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$account->username = $user;
$account->domain = $domain;
if (!$account->getOne()) {
return ACCOUNT_NOT_FOUND;
}
$password = new Password($db);
$password->account_id = $account->id;
$password->algorithm = $algo;
if (!$password->getOne()) {
return PASSWORD_NOT_FOUND;
}
if ($algo == CLEAR) {
$hashed_password = $pwd;
} else {
$hashed_password = hash_password($user, $pwd, $domain, $algo);
}
if (!password_match($hashed_password, $password->password)
&& !password_match($pwd, $password->password)) { // This condition is specific for liblinphone tester....
return PASSWORD_DOESNT_MATCH;
}
if ($account->confirmation_key == INVALID_CONFIRMATION_KEY) {
// We have to generate a new one because
$account->confirmation_key = uniqid();
$account->update();
}
$key = $account->confirmation_key;
Logger::getInstance()->debug("[XMLRPC] returning key = " . $key);
return $key;
}
// args = [user, pwd, [domain], [algo]]
// /!\ This method must be used for tests purposes only /!\
function xmlrpc_delete_account($method, $args)
{
$user = $args[0];
$pwd = $args[1];
$domain = get_domain($args[2]);
$algo = get_algo($args[3]);
Logger::getInstance()->message("[XMLRPC] xmlrpc_delete_account(" . $user . ", " . $domain . ", " . $algo . ")");
if ($algo == null) {
return ALGO_NOT_SUPPORTED;
} elseif (!check_parameter($user)) {
return MISSING_USERNAME_PARAM;
} elseif (!ALLOW_TEST_ACCOUNTS) {
return TEST_ACCOUNTS_DISABLED;
}
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$account->username = $user;
$account->domain = $domain;
if (!$account->getOne()) {
return ACCOUNT_NOT_FOUND;
}
$password = new Password($db);
$password->account_id = $account->id;
$password->algorithm = $algo;
if (!$password->getOne()) {
return PASSWORD_NOT_FOUND;
}
if ($algo == CLEAR) {
$hashed_password = $pwd;
} else {
$hashed_password = hash_password($user, $pwd, $domain, $algo);
}
if (!password_match($hashed_password, $password->password)
&& !password_match($pwd, $password->password)) { // This condition is specific for liblinphone tester....
return PASSWORD_DOESNT_MATCH;
}
$alias = new Alias($db);
$alias->account_id = $account->id;
$account->delete();
$password->delete();
$alias->delete();
return OK;
}
// /!\ This methods must be used for tests purposes only /!\
function xmlrpc_liblinphone_tester_register_methods($server)
{
xmlrpc_server_register_method($server, 'get_confirmation_key', 'xmlrpc_get_confirmation_key');// args = [user, pwd, [domain], [algo]], return confirmation_key
xmlrpc_server_register_method($server, 'delete_account', 'xmlrpc_delete_account');// args = [user, pwd, [domain], [algo]]
}

View file

@ -1,288 +0,0 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
include_once __DIR__ . '/../database/database.php';
include_once __DIR__ . '/../objects/account.php';
include_once __DIR__ . '/../objects/password.php';
include_once __DIR__ . '/../objects/alias.php';
include_once __DIR__ . '/../objects/user_info.php';
include_once __DIR__ . '/../misc/utilities.php';
include_once __DIR__ . '/../misc/results_values.php';
// args = [username, old hash, new hash, [domain], [algo]]
function xmlrpc_update_password($method, $args)
{
$username = $args[0];
$hashed_old_password = $args[1];
$hashed_new_password = $args[2];
$domain = get_domain($args[3]);
$algo = get_algo($args[4]);
Logger::getInstance()->message("[XMLRPC] xmlrpc_update_password(" . $username . ", " . $domain . ", " . $algo . ")");
if (!check_parameter($username)) {
return MISSING_USERNAME_PARAM;
} elseif (!check_parameter($hashed_old_password, "old password")) {
return MISSING_OLD_HASH;
} elseif (!check_parameter($hashed_new_password, "md5 password")) {
return MISSING_NEW_HASH;
} elseif ($algo == null) {
return ALGO_NOT_SUPPORTED;
}
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$account->username = $username;
$account->domain = $domain;
if (!$account->getOne()) {
return ACCOUNT_NOT_FOUND;
}
$password = new Password($db);
$password->account_id = $account->id;
$password->password = $hashed_old_password;
$password->algorithm = $algo;
if (!$password->getOne()) {
return PASSWORD_DOESNT_MATCH;
}
$password->password = $hashed_new_password;
if ($password->update()) {
Logger::getInstance()->message("Password updated successfully");
return OK;
}
return NOK;
}
// args = [username, old hash, md5_hash, sha256_hash, [domain]]
function xmlrpc_update_passwords($method, $args)
{
$username = $args[0];
$hashed_password = $args[1];
$md5_hashed_password = $args[2];
$sha256_hashed_password = $args[3];
$domain = get_domain($args[4]);
if (!check_parameter($username)) {
return MISSING_USERNAME_PARAM;
} elseif (!check_parameter($hashed_password, "old password")) {
return MISSING_OLD_HASH;
} elseif (!check_parameter($md5_hashed_password, "md5 password")) {
return MISSING_MD5_HASH;
} elseif (!check_parameter($sha256_hashed_password, "sha256 password")) {
return MISSING_SHA256_HASH;
}
Logger::getInstance()->message("[XMLRPC] xmlrpc_update_passwords(" . $username . ", " . $domain . ")");
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$account->username = $username;
$account->domain = $domain;
if (!$account->getOne()) {
return ACCOUNT_NOT_FOUND;
}
$password = new Password($db);
$password->account_id = $account->id;
$password->password = $hashed_password;
if (!$password->getOne()) {
return PASSWORD_DOESNT_MATCH;
}
// Old password is OK, now let's hash the new password for both MD5 and SHA-256
$md5_password = new Password($db);
$md5_password->account_id = $account->id;
$md5_password->algorithm = MD5;
$md5_exists = $md5_password->GetOne();
$md5_password->password = $md5_hashed_password;
if ($md5_exists) {
$md5_password->update();
} else {
$md5_password->create();
}
$sha256_password = new Password($db);
$sha256_password->account_id = $account->id;
$sha256_password->algorithm = SHA256;
$sha256_exists = $sha256_password->GetOne();
$sha256_password->password = $sha256_hashed_password;
if ($sha256_exists) {
$sha256_password->update();
} else {
$sha256_password->create();
}
return OK;
}
// args = [username, old md5 hash, sha256 hash, [domain]]
function xmlrpc_upgrade_password($method, $args)
{
$username = $args[0];
$md5_hash = $args[1];
$sha256_hash = $args[2];
$domain = get_domain($args[3]);
Logger::getInstance()->message("[XMLRPC] xmlrpc_upgrade_password(" . $username . ", " . $domain . ")");
if (!check_parameter($username)) {
return MISSING_USERNAME_PARAM;
}
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$account->username = $username;
$account->domain = $domain;
if (!$account->getOne()) {
return ACCOUNT_NOT_FOUND;
}
$sha256_password = new Password($db);
$sha256_password->account_id = $account->id;
$sha256_password->algorithm = SHA256;
// There is already a SHA-256 password for this account, abort upgrade
if ($sha256_password->getOne()) {
return SHA256_PASSWORD_ALREADY_EXISTS;
}
$md5_password = new Password($db);
$md5_password->account_id = $account->id;
$md5_password->password = $md5_hash;
$md5_password->algorithm = MD5;
// No MD5 or wrong hash, abort
if (!$md5_password->getOne()) {
return PASSWORD_DOESNT_MATCH;
}
// Upgrade MD5 to SHA-256
$md5_password->password = $sha256_hash;
$md5_password->algorithm = SHA256;
if ($md5_password->update()) {
Logger::getInstance()->message("Password upgraded successfully");
return OK;
}
return NOK;
}
// args = [username, hash, [domain]]
function xmlrpc_check_authentication($method, $args)
{
$username = $args[0];
$hashed_password = $args[1];
$domain = get_domain($args[2]);
Logger::getInstance()->message("[XMLRPC] xmlrpc_check_authentication(" . $username . ", " . $domain . ")");
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$account->username = $username;
$account->domain = $domain;
if (!$account->getOne()) {
return ACCOUNT_NOT_FOUND;
}
$password = new Password($db);
$password->account_id = $account->id;
$password->password = $hashed_password;
if (!$password->getOne()) {
return PASSWORD_DOESNT_MATCH;
}
return OK;
}
// args = [username, md5_hash, sha256_hash, [domain]]
function xmlrpc_check_authentication_and_upgrade_password($method, $args)
{
$username = $args[0];
$md5_hashed_password = $args[1];
$sha256_hashed_password = $args[2];
$domain = get_domain($args[3]);
Logger::getInstance()->message("[XMLRPC] xmlrpc_check_authentication_and_upgrade_password(" . $username . ", " . $domain . ")");
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$account->username = $username;
$account->domain = $domain;
if (!$account->getOne()) {
return ACCOUNT_NOT_FOUND;
}
$sha256_password = new Password($db);
$sha256_password->account_id = $account->id;
$sha256_password->password = $sha256_hashed_password;
$sha256_password->algorithm = SHA256;
if (!$sha256_password->getOne()) {
// SHA-256 doesn't exists or doesn't match, let's try MD5
$md5_password = new Password($db);
$md5_password->account_id = $account->id;
$md5_password->password = $md5_hashed_password;
$md5_password->algorithm = MD5;
if (!$md5_password->getOne()) {
return PASSWORD_DOESNT_MATCH;
}
if ($sha256_password->id > 0) {
// SHA-256 exists, let's update it
$sha256_password->update();
} else {
$sha256_password->create();
}
}
return OK;
}
function xmlrpc_passwords_register_methods($server)
{
// The below two methods are the same but with different names, update_hash was the previous one and is kept here for the time being for compatibility purposes
xmlrpc_server_register_method($server, 'update_hash', 'xmlrpc_update_password');// args = [username, old hash, new hash, [domain], [algo]], return OK
xmlrpc_server_register_method($server, 'update_password', 'xmlrpc_update_password');// args = [username, old hash, new hash, [domain], [algo]], return OK
xmlrpc_server_register_method($server, 'update_passwords', 'xmlrpc_update_passwords');// args = [username, old hash, md5_hash, sha256_hash, [domain]]
xmlrpc_server_register_method($server, 'upgrade_password', 'xmlrpc_upgrade_password');// args = [username, old md5 hash, sha256 hash, [domain]]
xmlrpc_server_register_method($server, 'check_authentication', 'xmlrpc_check_authentication');// args = [username, hash, [domain]]
xmlrpc_server_register_method($server, 'check_authentication_and_upgrade_password', 'xmlrpc_check_authentication_and_upgrade_password');// args = [username, md5_hash, sha256_hash, [domain]]
}

View file

@ -1,212 +0,0 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
header("Access-Control-Allow-Origin: *");
include_once __DIR__ . '/../misc/utilities.php';
include_once __DIR__ . '/../objects/account.php';
include_once __DIR__ . '/../objects/password.php';
include_once __DIR__ . '/authentication.php';
$logger = Logger::getInstance();
$username = isset($_GET['username']) ? $_GET['username'] : null;
$domain = isset($_GET['domain']) ? $_GET['domain'] : SIP_DOMAIN;
$realm = isset($_GET['domain']) ? $_GET['domain'] : AUTH_REALM;
if (REMOTE_PROVISIONING_USE_DIGEST_AUTH) {
$headers = getallheaders();
// From is the GRUU('sip:username@AUTH_REALM;gr=*;), we need to extract the username from it:
// from position 4(skip 'sip:') until the first occurence of @
// pass it through rawurldecode has GRUU may contain escaped characters
$from = rawurldecode(substr($headers['From'],4,strpos($headers['From'], '@')-4));
if (empty($from)) {
$from = $username;
$logger->debug("Empty From, using username = " . $username);
}
$authorization = null;
// Get authentication header if there is one
if (!empty($headers['Auth-Digest'])) {
$logger->debug("Auth-Digest = " . $headers['Auth-Digest']);
$authorization = $headers['Auth-Digest'];
} elseif (!empty($headers['Authorization'])) {
$logger->debug("Authorization = " . $headers['Authorization']);
$authorization = $headers['Authorization'];
}
if (!empty($authorization)) {
$authentication_status = authenticate($authorization, $realm);
if ($authentication_status != null) {
Logger::getInstance()->debug("Authentication successful");
} else {
Logger::getInstance()->debug("Authentication failed");
request_authentication($realm, $from);
}
} else {
Logger::getInstance()->debug("No authentication header");
request_authentication($realm, $from);
}
}
if (isset($_GET['qrcode']) && $_GET['qrcode'] == 1) {
$query = $_GET;
$query['qrcode'] = 0;
$query_result = http_build_query($query);
$data = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https://" : "http://") . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'] . "?" . $query_result;
// https://github.com/tecnickcom/tc-lib-barcode GPLv3
require __DIR__ . '/../vendor/tecnickcom/tc-lib-barcode/resources/autoload.php';
$barcode = new \Com\Tecnick\Barcode\Barcode();
$bobj = $barcode->getBarcodeObj(
'QRCODE,H', // barcode type and additional comma-separated parameters
$data, // data string to encode
-4, // bar width (use absolute or negative value as multiplication factor)
-4, // bar height (use absolute or negative value as multiplication factor)
'black', // foreground color
array(-2, -2, -2, -2) // padding (use absolute or negative values as multiplication factors)
)->setBackgroundColor('white'); // background color
header("Content-Type: text/html; charset=UTF-8");
echo $bobj->getHtmlDiv();
return;
}
header("Content-Type: application/xml; charset=UTF-8");
$xml = '<?xml version="1.0" encoding="UTF-8"?>';
$xml .= '<config xmlns="http://www.linphone.org/xsds/lpconfig.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.linphone.org/xsds/lpconfig.xsd lpconfig.xsd">';
$proxy_config_index = 0;
$auth_info_index = 0;
if (file_exists(REMOTE_PROVISIONING_DEFAULT_CONFIG)) {
$rc_array = parse_ini_file(REMOTE_PROVISIONING_DEFAULT_CONFIG, true);
foreach ($rc_array as $section => $values) {
$xml .= '<section name="' . $section . '">';
if (startswith($section, "proxy_config_")) {
$proxy_config_index += 1;
} elseif (startswith($section, "auth_info_")) {
$auth_info_index += 1;
}
foreach ($values as $key => $value) {
// We need to replace any < or > by &lt; and &gt; or the xml won't be valid !
$value = str_replace("<", "&lt;", $value);
$value = str_replace(">", "&gt;", $value);
$xml .= '<entry name="' . $key . '"' . (REMOTE_PROVISIONING_OVERWRITE_ALL ? ' overwrite="true"' : '') . '>' . $value . '</entry>';
}
$xml .= '</section>';
}
}
$transport = isset($_GET['transport']) ? $_GET['transport'] : REMOTE_PROVISIONING_DEFAULT_TRANSPORT;
$request_params = array(
"username" => $username,
"domain" => $domain,
"transport" => $transport,
"ha1" => null,
"algo" => DEFAULT_ALGORITHM,
);
if (!empty($username)) {
if (REMOTE_PROVISIONING_USE_DIGEST_AUTH) {
if ($username != $authentication_status) {
$logger->error("User " . $authentication_status . " is trying to impersonate another user: " . $username);
header('HTTP/1.1 403 Forbidden: Authenticated username and provisioning username mismatch');
exit();
}
}
$ha1 = isset($_GET['ha1']) ? $_GET['ha1'] : null;
$algo = isset($_GET['algorithm']) ? $_GET['algorithm'] : DEFAULT_ALGORITHM;
if (REMOTE_PROVISIONING_ONE_TIME_PASSWORD) {
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$account->username = $username;
$account->domain = $domain;
if ($account->getOne()) {
if (!is_activated($account->activated)) {
$password = new Password($db);
$password->account_id = $account->id;
$password->algorithm = $algo;
if ($password->getOne()) {
$new_password = generate_password();
$ha1 = hash_password($username, $new_password, $domain, $algo);
$password->password = $ha1;
if (!$password->update()) {
$logger->error("Failed to update password for account id " . $account->id);
}
} else {
$logger->error("Password not found for account id " . $account->id);
}
if (!$account->activate()) {
$logger->error("Failed to activate account id " . $account->id);
}
} else {
$logger->message("Account id " . $account->id . " is already activated");
}
}
}
$request_params["ha1"] = $ha1;
$request_params["algo"] = $algo;
$xml .= '<section name="proxy_' . $proxy_config_index . '">';
$xml .= '<entry name="reg_identity"' . (REMOTE_PROVISIONING_OVERWRITE_ALL ? ' overwrite="true"' : '') . '>&lt;sip:' . $username . '@' . $domain . '&gt;</entry>';
$xml .= '<entry name="reg_sendregister"' . (REMOTE_PROVISIONING_OVERWRITE_ALL ? ' overwrite="true"' : '') . '>1</entry>';
$xml .= '<entry name="refkey"' . (REMOTE_PROVISIONING_OVERWRITE_ALL ? ' overwrite="true"' : '') . '>push_notification</entry>';
if (get_config_value("CUSTOM_HOOKS", FALSE)) {
provisioning_hook_on_proxy_config($xml, $request_params);
}
$xml .= '</section>';
if (!empty($ha1)) {
$xml .= '<section name="auth_info_' . $auth_info_index . '">';
$xml .= '<entry name="username"' . (REMOTE_PROVISIONING_OVERWRITE_ALL ? ' overwrite="true"' : '') . '>' . $username . '</entry>';
$xml .= '<entry name="ha1"' . (REMOTE_PROVISIONING_OVERWRITE_ALL ? ' overwrite="true"' : '') . '>' . $ha1 . '</entry>';
$xml .= '<entry name="realm"' . (REMOTE_PROVISIONING_OVERWRITE_ALL ? ' overwrite="true"' : '') . '>' . $domain . '</entry>';
$xml .= '<entry name="algorithm"' . (REMOTE_PROVISIONING_OVERWRITE_ALL ? ' overwrite="true"' : '') . '>' . $algo . '</entry>';
if (get_config_value("CUSTOM_HOOKS", FALSE)) {
provisioning_hook_on_auth_info($xml, $request_params);
}
$xml .= '</section>';
}
}
if (get_config_value("CUSTOM_HOOKS", FALSE)) {
provisioning_hook_on_additional_section($xml, $request_params);
}
$xml .= '</config>';
http_response_code(200);
echo $xml;

View file

@ -1,171 +0,0 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
include_once __DIR__ . '/../database/database.php';
include_once __DIR__ . '/../objects/account.php';
include_once __DIR__ . '/../objects/password.php';
include_once __DIR__ . '/../objects/alias.php';
include_once __DIR__ . '/../objects/user_info.php';
include_once __DIR__ . '/../misc/utilities.php';
include_once __DIR__ . '/../misc/geoloc.php';
include_once __DIR__ . '/../misc/results_values.php';
include_once __DIR__ . '/../misc/user_info.php';
// args = [username, ha1, [domain], [algo]]
function xmlrpc_get_email_account($method, $args)
{
$username = $args[0];
$ha1 = $args[1];
$domain = get_domain($args[2]);
$algo = get_algo($args[3]);
Logger::getInstance()->message("[XMLRPC] xmlrpc_get_email_account(" . $username . ")");
$database = new Database();
$db = $database->getConnection();
$account = new Account($db);
$account->username = $username;
$account->domain = $domain;
if (!$account->getOne()) {
return ACCOUNT_NOT_FOUND;
}
$password = new Password($db);
$password->account_id = $account->id;
$password->algorithm = $algo;
if (!$password->getOne()) {
return PASSWORD_NOT_FOUND;
}
if (!password_match($ha1, $password->password)) {
return PASSWORD_DOESNT_MATCH;
}
$user_info = new UserInfo($db);
$user_info->account_id = $account->id;
$user_info->getOne();
$result = array(
"id" => $account->id,
"username" => $account->username,
"domain" => $account->domain,
"email" => $account->email,
"alias" => $account->alias,
"activated" => $account->activated,
"firstname" => $user_info->firstname,
"lastname" => $user_info->lastname,
"gender" => $user_info->gender,
"subscribe" => $user_info->subscribe
);
return $result;
}
// args = [tel, ha1, [domain], [algo]]
function xmlrpc_get_phone_account($method, $args)
{
$phone = $args[0];
$ha1 = $args[1];
$domain = get_domain($args[2]);
$algo = get_algo($args[3]);
Logger::getInstance()->message("[XMLRPC] xmlrpc_get_phone_account(" . $phone . ")");
$database = new Database();
$db = $database->getConnection();
$alias = new Alias($db);
$alias->alias = $phone;
$alias->domain = $domain;
$account = new Account($db);
if (!$alias->getOne()) {
$account->username = $phone;
$account->domain = $domain;
} else {
$account->id = $alias->account_id;
}
if (!$account->getOne()) {
return ACCOUNT_NOT_FOUND;
}
$password = new Password($db);
$password->account_id = $account->id;
$password->algorithm = $algo;
if (!$password->getOne()) {
return PASSWORD_NOT_FOUND;
}
if (!password_match($ha1, $password->password)) {
return PASSWORD_DOESNT_MATCH;
}
$user_info = new UserInfo($db);
$user_info->account_id = $account->id;
$user_info->getOne();
$result = array(
"id" => $account->id,
"username" => $account->username,
"domain" => $account->domain,
"email" => $account->email,
"alias" => $account->alias,
"activated" => $account->activated,
"firstname" => $user_info->firstname,
"lastname" => $user_info->lastname,
"gender" => $user_info->gender,
"subscribe" => $user_info->subscribe
);
return $result;
}
// args = [username, ha1, firstname, lastname, gender, subscribe, [domain], [algo]]
function xmlrpc_update_account_user_info($method, $args)
{
$username = $args[0];
$ha1 = $args[1];
$firstname = $args[2];
$lastname = $args[3];
$gender = $args[4];
$subscribe = $args[5];
$domain = get_domain($args[6]);
$algo = get_algo($args[7]);
Logger::getInstance()->message("[XMLRPC] xmlrpc_update_account_user_info(" . $username . ", " . $domain . " : " . $firstname . ", " . $lastname . ", " . $gender . ", " . $subscribe . ")");
return update_account_user_info($username, $ha1, $firstname, $lastname, $gender, $subscribe, $domain, $algo);
}
function xmlrpc_user_info_register_methods($server)
{
xmlrpc_server_register_method($server, 'get_email_account', 'xmlrpc_get_email_account'); // args = [username, ha1, [domain], [algo]]
xmlrpc_server_register_method($server, 'get_phone_account', 'xmlrpc_get_phone_account'); // args = [tel, ha1, [domain], [algo]]
xmlrpc_server_register_method($server, 'update_account_user_info', 'xmlrpc_update_account_user_info'); // args = [username, ha1, firstname, lastname, gender, subscribe, [domain], [algo]]
}

View file

@ -1,122 +0,0 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
include_once __DIR__ . '/../database/database.php';
include_once __DIR__ . '/../misc/utilities.php';
include_once __DIR__ . '/authentication.php';
include_once __DIR__ . '/accounts.php';
include_once __DIR__ . '/aliases.php';
include_once __DIR__ . '/devices.php';
include_once __DIR__ . '/passwords.php';
include_once __DIR__ . '/user_info.php';
$request = file_get_contents("php://input");
if (empty($request)) {
Logger::getInstance()->error("Request is empty");
}
$server = xmlrpc_server_create();
if (!$server) {
die("Couldn't create server");
}
if (USE_DIGEST_AUTH) {
$headers = getallheaders();
$xml = simplexml_load_string($request);
$request_type = $xml->methodName;
$unauthenticated_requests = array(
// email accounts
0 => 'create_email_account',
1 => 'create_email_md5_sha256_account',
2 => 'activate_email_account',
3 => 'recover_email_account',
// phone accounts
4 => 'create_phone_account',
5 => 'activate_phone_account',
6 => 'recover_phone_account',
7 => 'is_phone_number_used',
8 => 'get_phone_number_for_account',
// accounts
9 => 'get_confirmation_key',
10 => 'is_account_used',
11 => 'is_account_activated',
12 => 'recover_account_from_confirmation_key',
13 => 'get_accounts_count',
// aliases
14 => 'is_alias_used',
15 => 'link_phone_number_with_account',
16 => 'get_alias',
// devices
17 => 'add_ec_calibration_result',
);
// Get authentication header if there is one
if (!empty($headers['Auth-Digest'])) {
Logger::getInstance()->debug("Auth-Digest = " . $headers['Auth-Digest']);
$authorization = $headers['Auth-Digest'];
} elseif (!empty($headers['Authorization'])) {
Logger::getInstance()->debug("Authorization = " . $headers['Authorization']);
$authorization = $headers['Authorization'];
}
// Authentication
if (in_array($request_type, $unauthenticated_requests) == false) {
if (!empty($authorization)) {
$authentication_status = authenticate($authorization, AUTH_REALM);
if ($authentication_status != null) {
Logger::getInstance()->debug("Authentication successful");
} else {
Logger::getInstance()->debug("Authentication failed");
request_authentication(AUTH_REALM);
}
} else {
Logger::getInstance()->debug("No authentication header");
request_authentication(AUTH_REALM);
}
}
}
xmlrpc_accounts_register_methods($server);
xmlrpc_aliases_register_methods($server);
xmlrpc_devices_register_methods($server);
xmlrpc_passwords_register_methods($server);
xmlrpc_user_info_register_methods($server);
if (USE_IN_APP_PURCHASES) {
include_once __DIR__ . '/inapp.php';
xmlrpc_inapp_register_methods($server);
}
if (ALLOW_TEST_ACCOUNTS) {
include_once __DIR__ . '/liblinphone_tester.php';
xmlrpc_liblinphone_tester_register_methods($server);
}
if ($request) {
$options = array('output_type' => 'xml', 'version' => 'auto');
echo xmlrpc_server_call_method($server, $request, null, $options);
}