AlkantarClanX12
Your IP : 216.73.217.24
<?php
/*
Copyright (C) 2015-26 CERBER TECH INC., https://wpcerber.com
Licensed under the GNU GPL.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
if ( ! defined( 'WPINC' ) ) { exit; }
final class CRB_DS {
private static string $setting = '_crb_ds_shadowing';
private static $config = null;
private static $the_user = null;
private static $update_user = null;
private static $acc_owner = false;
private static $user_blocked = false;
private static $user_fields = array( 'user_login' => 'lgn', 'user_pass' => 'pwd', 'user_email' => 'eml' );
private static $opt_cache = array();
private static $no_user_meta_shadow = ''; // Do not return user meta from shadow when meta is updating.
//private static $user_metas = array( 'capabilities' );
private static $setting_id; // A controlling plugin setting (last used)
static function enable_shadowing( $type ) {
if ( self::get_config( $type ) || ! lab_lab() ) {
return;
}
$conf = self::get_config();
if ( ! $conf ) {
$conf = array();
}
$data = array();
$data[0] = time();
$data[1] = 0;
$data[2] = get_current_user_id();
$data[3] = get_wp_cerber()->getRequestID();
switch ( $type ) {
case 1: // Users data
if ( defined( 'CRB_USHD_KEY' ) && is_string( CRB_USHD_KEY ) ) {
$data[5] = CRB_USHD_KEY; // If users' tables are shared among mutiple websites, define it in the wp-config.php on all websites before (!) activation shadowing
}
else {
$data[5] = crb_random_string( 14, 16, false, false );
}
$conf[ $type ] = $data;
self::save_config( $conf );
self::update_user_shadow( get_current_user_id(), null, null, self::is_meta_preserve() );
CRB_Deferred_Tasks::add( '_crb_ds_background', array( 'exec_until' => 'done', 'retry_limit' => 1000 ) );
break;
case 2: // Roles
case 3: // Settings
$data[1] = time(); // Should be set after all shadows has created
$data[5] = crb_random_string( 10, 12, false, false );
$data[6] = crb_random_string( 8, 14, true, false );
$conf[ $type ] = $data;
self::save_config( $conf );
foreach ( self::get_protected_settings()[ $type ] as $item ) {
self::update_setting_shadow( $item, get_option( $item ) );
}
break;
}
}
static function disable_shadowing( $type ) {
global $wpdb;
if ( ! $type_conf = self::get_config( $type ) ) {
return;
}
if ( ! is_super_admin() && ! nexus_is_valid_request() ) {
return;
}
$conf = self::get_config();
unset( $conf[ $type ] );
self::save_config( $conf );
switch ( $type ) {
case 1:
cerber_db_query( 'DELETE FROM ' . $wpdb->usermeta . ' WHERE meta_key ="' . $type_conf[5] . '"' );
break;
case 2:
case 3:
cerber_db_query( 'DELETE FROM ' . cerber_get_db_prefix() . CERBER_SETS_TABLE . ' WHERE the_key LIKE "' . $type_conf[5] . '%"' );
break;
}
}
static function is_ready( $type ) {
if ( lab_lab() && ( $conf = self::get_config( $type ) ) && $conf[1] ) {
return true;
}
return false;
}
private static function save_config( $conf ) {
self::$config = $conf;
// Encoding
reset( $conf );
$lenght = count( $conf );
$b = rand( 1, 10 );
//$config = array_fill( $b, rand( 12, 14 ), 0 );
$config = array_fill( $b, rand( $lenght + 8, $lenght + 10 ), 0 );
$s = rand( 3, 5 );
$config[ $b + 1 ] = $s; // crucial for extracting
$config[ $b + $s ] = $conf;
$config[ $b + $s + 1 ] = array( array( $b ) ); // is not used
$config[] = $b + 3; // crucial for verification
update_site_option( self::$setting, $config );
}
private static function get_config( $type = null ) {
if ( ! isset( self::$config ) ) {
$s = get_site_option( self::$setting );
if ( ! $s || ! is_array( $s ) ) {
return false;
}
reset( $s );
if ( key( $s ) != ( end( $s ) - 3 ) ) {
return false;
}
$s = array_values( $s );
self::$config = $s[ $s[1] ];
}
if ( $type ) {
if ( isset( self::$config[ $type ] ) ) {
return self::$config[ $type ];
}
return false;
}
return self::$config;
}
/**
* Creating shadow in bulk
*
* @return bool true if not completed, false = completed or nothing to do
*/
static function iterate_users() {
global $wpdb;
if ( ( ! $type_conf = self::get_config( 1 ) ) || self::is_ready( 1 ) ) {
return false;
}
$to_do = cerber_db_get_col( 'SELECT DISTINCT ID FROM ' . $wpdb->users . ' WHERE ID NOT IN (SELECT DISTINCT user_id FROM ' . $wpdb->usermeta . ' WHERE meta_key = "' . $type_conf[5] . '")' );
if ( ! $to_do ) { // Creating shadow completed
$conf = self::get_config();
$conf[1][1] = time();
self::save_config( $conf );
//cerber_diag_log( 'Create shadow completed' );
return false;
}
foreach ( $to_do as $user_id ) {
self::update_user_shadow( $user_id, null, null, self::is_meta_preserve() );
//wp_cache_delete( $user_id, 'user_meta' );
}
return true;
}
private static function get_user_shadow( $user_id ) {
if ( ! $user_id || ! $conf = self::get_config( 1 ) ) {
return false;
}
$um = get_user_meta( $user_id, $conf[5], true );
if ( ! $um ) {
return array();
}
$val = self::decode( $um );
$ret = crb_unserialize( $val );
if ( ! $ret || ! is_array( $ret ) ) {
$ret = array();
}
return $ret;
}
private static function update_user_shadow( $user_id, $fields = array(), $meta_data = array(), $meta_keys = array() ) {
if ( ! $user_id || ! $conf = self::get_config( 1 ) ) {
return false;
}
if ( ! $data = get_userdata( $user_id ) ) {
return false; // Not a valid user
}
$sh = self::get_user_shadow( $user_id );
$sh[0] = $user_id;
if ( empty( $sh[1] ) ) {
$sh[1] = array();
}
if ( $fields ) {
$list = array_intersect_key( self::$user_fields, array_flip( $fields ) );
}
else {
$list = self::$user_fields;
}
foreach ( $list as $user_field => $key ) {
$sh[1][ $key ] = $data->data->$user_field;
}
if ( empty( $sh[2] ) ) {
$sh[2] = array();
}
/*if ( ! $fields ) { // We use $fields only for updating password
if ( empty( $sh[2] ) ) { // New user
foreach ( self::is_meta_preserve() as $key ) {
$sh[2][ $key ] = get_user_meta( $user_id, $key, true );
}
}
}*/
if ( ! empty( $meta_keys ) ) {
foreach ( $meta_keys as $key ) {
$sh[2][ $key ] = get_user_meta( $user_id, $key, true );
}
}
if ( $meta_data ) {
$sh[2] = array_merge( $sh[2], $meta_data );
}
return update_user_meta( $user_id, $conf[5], self::encode( serialize( $sh ) ) );
}
static function is_user_valid( $user_id = null ) {
if ( ! self::is_ready( 1 ) ) {
return true;
}
if ( ! $user_id ) {
$user_id = get_current_user_id();
}
if ( ( $sh = self::get_user_shadow( $user_id ) )
&& $sh[0] == $user_id ) {
return true;
}
return false;
}
/**
* Return the password hash of a given user.
* Make sure that CRB_DS::is_ready() returns true before using result
*
* @param null $user_id
*
* @return string
*/
static function get_user_pass( $user_id ) {
if ( ! $user_id ) {
return '';
}
if ( ! ( $sh = self::get_user_shadow( $user_id ) )
|| $sh[0] != $user_id
|| ! ( $ret = crb_array_get( $sh[1], self::$user_fields['user_pass'] ) ) ) {
return '';
}
return $ret;
}
/**
* @param $mode
* @param $user_id
* @param null $data User data from 'wp_pre_insert_user_data' filter
*/
static function acc_processor( $mode, $user_id, $data = null ) {
if ( $mode == 'pass' ) {
self::update_user_shadow( $user_id, array( 'user_pass' ) );
return;
}
//$update_permitted = self::acc_update_permitted_by_ip();
$update_permitted = ( crb_get_settings( 'ds_4acc_acl' ) && crb_acl_is_allowed() );
switch ( $mode ) {
case 'new':
self::$update_user = null;
if ( ! $update_permitted ) {
$update_permitted = self::acc_new( $user_id );
}
if ( $update_permitted ) {
self::update_user_shadow( $user_id );
}
break;
case 'update':
self::$update_user = $user_id;
if ( ! $update_permitted ) {
$update_permitted = self::acc_update( $user_id, $data );
}
if ( $update_permitted ) {
// Must be deferred till user's data is saved to DB
add_action( 'profile_update', function ( $user_id ) {
CRB_DS::update_helper( $user_id );
} );
}
break;
}
}
static function update_helper( $user_id ) {
if ( ( self::$update_user != $user_id )
|| ( self::$user_blocked && ! self::$acc_owner ) ) {
return;
}
self::update_user_shadow( $user_id );
}
/**
* Protect DB from an unauthorized user creation
*
* @param $user_id
*
* @return bool true if this operation is permitted
*/
private static function acc_new( $user_id ) {
$set = crb_get_settings();
self::$user_blocked = false;
// Due to lack of a hook in the wp_insert_user() we are forced to check permissions and use wp_delete_user() after the user was created
if ( ! is_user_logged_in() ) {
if ( ! crb_user_has_role_strict( $set['ds_regs_roles'], $user_id ) ) {
CRB_Globals::set_act_status( 32, 'ds_regs_roles' );
self::$user_blocked = true;
}
}
else {
if ( ! crb_wp_user_has_role( $set['ds_add_acc'] ) ) {
CRB_Globals::set_act_status( 33, 'ds_add_acc' );
self::$user_blocked = true;
}
}
if ( self::$user_blocked ) {
require_once( ABSPATH . 'wp-admin/includes/user.php' );
wp_delete_user( $user_id );
cerber_log( 72 );
remove_action( 'register_new_user', 'wp_send_new_user_notifications' );
remove_action( 'edit_user_created_user', 'wp_send_new_user_notifications', 10 );
}
elseif ( ! has_filter( 'register_new_user', 'wp_send_new_user_notifications' ) ) {
// this is needed in the case of a bulk user import
add_action( 'register_new_user', 'wp_send_new_user_notifications' );
add_action( 'edit_user_created_user', 'wp_send_new_user_notifications', 10 );
}
return ( ! self::$user_blocked );
}
/**
* Protect user's data from non-authorized modification
*
* @param int $user_id
* @param array $data User data from 'wp_pre_insert_user_data' filter
*
* @return bool true if this operation is permitted
*/
private static function acc_update( $user_id, $data ) {
global $wpdb;
$cid = get_current_user_id();
self::$acc_owner = ( $user_id == $cid );
self::$user_blocked = false;
if ( ! crb_wp_user_has_role( crb_get_settings( 'ds_edit_acc' ) ) ) {
// An exception: password reset requested (since WP 5.3)
if ( ! empty( $data['user_activation_key'] ) && cerber_is_http_post() ) {
// These fields cannot be changed during a normal password reset process
$protected = array('user_pass','user_nicename','user_email','user_url','user_registered','display_name');
$ok = true;
if ( $row = cerber_db_get_row( 'SELECT * FROM ' . $wpdb->users . ' WHERE ID = ' . $user_id ) ) {
foreach ( $protected as $field ) {
if ( $row[ $field ] != $data[ $field ] ) {
$ok = false;
break;
}
}
}
if ( $ok ) {
return true;
}
}
self::$user_blocked = true;
self::$setting_id = 'ds_edit_acc';
if ( ! self::$acc_owner ) {
// Protect the user's row in the users table
add_filter( 'query', 'crb_empty_query', PHP_INT_MAX );
add_filter( 'pre_get_col_charset', 'crb_return_wp_error', PHP_INT_MAX );
CRB_Globals::set_act_status( ( ! $cid ) ? 34 : 33, 'ds_edit_acc' );
cerber_log( 73 );
}
if ( ! has_filter( 'insert_user_meta', array( 'CRB_DS', 'user_meta' ) ) ) {
add_filter( 'insert_user_meta', array( 'CRB_DS', 'user_meta' ), 0, 3 );
}
}
return ( ! self::$user_blocked );
}
static function user_meta( $meta, $user, $update ) {
self::$the_user = $user;
if ( self::$user_blocked == true ) {
if ( ! self::$acc_owner ) {
// Must be removed after a single use for a given user
remove_filter( 'query', 'crb_empty_query', PHP_INT_MAX );
remove_filter( 'pre_get_col_charset', 'crb_return_wp_error', PHP_INT_MAX );
}
//return array(); // No user meta to update
}
return $meta;
}
/**
* Restricts updating if not allowed.
* Updates shadow of user meta (and roles) if allowed.
*
* @param $user_id
* @param $meta_key
* @param $meta_value
*
* @return bool
*/
static function update_user_meta( $user_id, $meta_key, $meta_value ) {
// A user is not permitted to be created or updated?
if ( self::$user_blocked ) {
if ( self::is_meta_protected( $meta_key ) ) { // User roles are here
CRB_Globals::set_act_status( is_user_logged_in() ? 33 : 34, self::$setting_id );
cerber_log( 76 );
self::$no_user_meta_shadow = '';
return false;
}
}
if ( true === self::is_meta_preserve( $meta_key ) ) {
$ok = false;
if ( crb_wp_user_has_role( crb_get_settings( 'ds_edit_acc' ) ) ) {
$ok = true;
}
// Makes sense for user's role meta ONLY
elseif ( is_array( $meta_value )
&& ( $reg_roles = (array) crb_get_settings( 'ds_regs_roles' ) )
&& ! array_diff_key( $meta_value, array_flip( $reg_roles ) ) ) {
$ok = true;
}
if ( $ok ) {
self::$no_user_meta_shadow = $meta_key;
self::update_user_shadow( $user_id, null, array( $meta_key => $meta_value ) );
}
}
return true;
}
private static function is_meta_preserve( $meta_key = null ) {
global $wpdb;
// TODO: add support for multisite via $wpdb->get_blog_prefix()
$list = array( $wpdb->base_prefix . 'capabilities', $wpdb->base_prefix . 'user_level' );
if ( $meta_key && in_array( $meta_key, $list ) ) {
return true;
}
return $list;
}
private static function is_meta_protected( $meta_key ) {
global $wpdb;
if ( ( isset( self::$the_user ) && ( $meta_key == self::$the_user->cap_key ) ) // User roles are here
|| $meta_key == $wpdb->get_blog_prefix() . 'user_level' ) {
return true;
}
/*
$metas = array();
if ( in_array( $meta_key, $metas ) ) {
return true;
}*/
return false;
}
static function get_shadow_user_meta( $user_id, $meta_key, $single ) {
if ( self::$no_user_meta_shadow == $meta_key
|| ( ( $conf = self::get_config( 1 ) ) && $conf[5] == $meta_key ) ) {
return false; // Skip use shadow meta (infinite loop protection)
}
$sh = self::get_user_shadow( $user_id );
if ( isset( $sh[2][ $meta_key ] ) ) {
return array( $sh[2][ $meta_key ] );
}
return false;
}
/**
* Process settings updates. Updates shadow if permitted.
*
* @param $value
* @param $option
* @param $old_value
*
* @return mixed The old value if update is not permitted
*/
static function setting_processor( &$value, $option, &$old_value ) {
if ( empty( self::get_protected_settings()[3][ $option ] ) ) {
return $value;
}
if ( $value == $old_value
|| ( is_array( $value ) && is_array( $old_value )
&& ( serialize( $value ) === serialize( $old_value ) ) ) ) {
return $value;
}
if ( crb_get_settings( 'ds_4opts_acl' ) && crb_acl_is_allowed() ) {
self::update_setting_shadow( $option, $value );
return $value;
}
if ( ! cerber_is_ip_allowed() ) {
cerber_log( 75 );
return $old_value;
}
$roles = crb_get_settings( 'ds_4opts_roles' );
if ( ! $roles || ! crb_wp_user_has_role( $roles ) ) {
CRB_Globals::set_act_status( is_user_logged_in() ? 33 : 34, 'ds_4opts_roles' );
cerber_log( 75 );
return $old_value;
}
self::update_setting_shadow( $option, $value );
return $value;
}
/**
* Restrict access to updating roles data
*
* @param mixed $value Normally, it's an array containing all roles data
* @param string $option
* @param mixed $old_value Normally, it's an array containing all roles data
*
* @return array|mixed
*/
static function role_processor( &$value, $option, &$old_value ) {
$role_key = wp_roles()->role_key;
if ( $option !== $role_key ) {
return $value;
}
if ( is_array( $value ) && is_array( $old_value )
&& serialize( $value ) === serialize( $old_value ) ) {
return $value;
}
CRB_Globals::set_act_status( 0 );
if ( ! self::role_update_permitted( $value, $old_value ) ) {
CRB_Globals::set_act_status_if( is_user_logged_in() ? 33 : 34, self::$setting_id );
cerber_log( 74 );
return $old_value;
}
self::update_setting_shadow( $option, $value );
return $value;
}
/**
* Check if role data can be updated
*
* @param array $value
* @param array $old_value
*
* @return bool True if update is permitted
*/
static function role_update_permitted( &$value, &$old_value ): bool {
if ( crb_get_settings( 'ds_4roles_acl' ) && crb_acl_is_allowed() ) {
return true;
}
if ( ! cerber_is_ip_allowed() ) {
return false;
}
$add = crb_get_settings( 'ds_add_role' );
$edit = crb_get_settings( 'ds_edit_role' );
// Are there new or deleted roles?
if ( crb_array_diff_keys( $value, $old_value ) ) {
if ( ! $add || ! crb_wp_user_has_role( $add ) ) {
self::$setting_id = 'ds_add_role';
return false;
}
return true;
}
// There are some changes in capabilities or names
if ( ! $edit || ! crb_wp_user_has_role( $edit ) ) {
self::$setting_id = 'ds_edit_role';
return false;
}
return true;
}
/*static function acc_update_permitted_by_ip() {
if ( crb_get_settings( 'ds_4acc_acl' ) && crb_acl_is_allowed() ) {
return true;
}
return false;
}*/
/**
* Install hooks for retrieving data of protected settings
*
*/
static function settings_hooks( $type ) {
if ( ! self::is_ready( $type ) ) {
return;
}
$list = self::get_protected_settings()[ $type ];
foreach ( $list as $option ) {
add_filter( "pre_option_{$option}", function ( $var, $option, $default ) {
$value = CRB_DS::get_setting_shadow( $option );
if ( $value ) {
return $value;
}
/*add_filter( "option_{$option}", function ( $value, $option ) {
CRB_DS::update_setting_shadow( $option, $value );
return $value;
}, 10, 2 );*/
return $var;
}, PHP_INT_MAX, 3 );
}
}
static function get_setting_shadow( $option ) {
// TODO: implement WP caching via wp_cache_add() / wp_cache_set()?
if ( ! isset( self::$opt_cache[ $option ] ) ) {
self::$opt_cache[ $option ] = cerber_get_set( self::get_setting_key( $option ) );
}
return self::$opt_cache[ $option ];
}
private static function update_setting_shadow( $option, $value ) {
self::$opt_cache[ $option ] = $value;
return cerber_update_set( self::get_setting_key( $option ), $value );
}
private static function get_setting_key( $option ) {
global $wpdb;
if ( $conf = self::get_config( 2 ) ) {
return $conf[5] . sha1( $option . $conf[6] . $wpdb->get_blog_prefix() );
}
return '';
}
/**
* @return array
*/
private static function get_protected_settings() {
global $wpdb;
$list = array();
$list[2] = array( $wpdb->get_blog_prefix() . 'user_roles' );
if ( $set = crb_get_settings( 'ds_4opts_list' ) ) {
$list[3] = $set;
}
else {
$list[3] = array();
}
return $list;
}
/**
* A list of settings to protect
*
* @param bool $ui_labels
*
* @return array
*/
static function get_settings_list( $ui_labels = true ) {
$set = array(
'admin_email' => __( 'Administration Email Address' ),
'default_role' => __( 'New User Default Role' ),
'home' => __( 'Site Address (URL)' ),
'siteurl' => __( 'WordPress Address (URL)' ),
'users_can_register' => __( 'Anyone can register' ),
'active_plugins' => __( 'Active Plugins' ),
'template' => __( 'Active Theme' ),
);
if ( $ui_labels ) {
return $set;
}
array_walk( $set, function ( &$e ) {
$e = 1; // Default value is ON
} );
return $set;
}
private static function encode( $str ) {
$str = base64_encode( $str );
$s = strlen( $str );
$str = rtrim( $str, '=' );
$num = $s - strlen( $str );
$ret = $num . $str;
return $ret;
}
private static function decode( $str ) {
static $equs = array( '', '=', '==' );
$num = substr( $str, 0, 1 );
$str = ltrim( $str, (string) $num );
return base64_decode( $str . $equs[ $num ] );
}
static function get_status() {
$ret = array();
if ( crb_get_settings( 'ds_4acc' ) ) {
self::get_type_status( 1, $msg );
$ret [] = 'Enabled for user accounts. ' . $msg;
}
if ( crb_get_settings( 'ds_4roles' ) ) {
self::get_type_status( 2, $msg );
$ret [] = 'Enabled for user roles. ' . $msg;
}
if ( crb_get_settings( 'ds_4opts' ) ) {
self::get_type_status( 3, $msg );
$ret [] = 'Enabled for site settings. ' . $msg;
}
return $ret;
}
private static function get_type_status( $n, &$msg = '' ) {
if ( $conf = self::get_config( $n ) ) {
if ( $conf[1] ) {
$msg = 'Active since ' . cerber_date( $conf[1] ) . '.';
return true;
}
else {
$msg = 'Creating shadow data in progress. ';
return true;
}
}
$msg = 'Configuration has been corrupted. Please re-enable protection in the Data Shield settings.';
return false;
}
// TODO: implement error notification
/**
* @return WP_Error|false
*/
static function check_errors() {
/*if () {
return new WP_Error();
}*/
return false;
}
}
if ( crb_get_settings( 'ds_4acc' ) && CRB_DS::is_ready( 1 ) ) {
add_action( 'user_register', function ( $user_id ) {
CRB_DS::acc_processor( 'new', $user_id );
}, 0 );
add_filter( 'wp_pre_insert_user_data', function ( $data, $update, $user_id ) {
if ( $update ) {
CRB_DS::acc_processor( 'update', $user_id, $data );
}
return $data;
}, PHP_INT_MAX, 3 );
add_filter( 'update_user_metadata', function ( $var, $object_id, $meta_key, $meta_value ) {
// apply_filters( "update_{$meta_type}_metadata", null, $object_id, $meta_key, $meta_value, $prev_value );
$allowed = CRB_DS::update_user_meta( $object_id, $meta_key, $meta_value );
if ( ! $allowed ) {
return true;
}
return $var;
}, PHP_INT_MAX, 4 );
add_filter( 'get_user_metadata', function ( $var, $object_id, $meta_key, $single ) {
//$check = apply_filters( "get_{$meta_type}_metadata", null, $object_id, $meta_key, $single );
if ( $meta = CRB_DS::get_shadow_user_meta( $object_id, $meta_key, $single ) ) {
return $meta;
}
return $var;
}, PHP_INT_MAX, 4 );
add_action( 'crb_after_reset', function ( $null, $user_id ) {
CRB_DS::acc_processor( 'pass', $user_id );
}, 10, 2 );
}
if ( crb_get_settings( 'ds_4roles' ) && CRB_DS::is_ready( 2 ) ) {
CRB_DS::settings_hooks( 2 );
add_filter( 'pre_update_option', function ( $value, $option, $old_value ) {
return CRB_DS::role_processor( $value, $option, $old_value );
}, PHP_INT_MAX, 3 );
}
if ( crb_get_settings( 'ds_4opts' ) && CRB_DS::is_ready( 3 ) ) {
CRB_DS::settings_hooks( 3 );
add_filter( 'pre_update_option', function ( $value, $option, $old_value ) {
return CRB_DS::setting_processor( $value, $option, $old_value );
}, PHP_INT_MAX, 3 );
}
/**
* A special SQL clause that produces empty result
*
* @return string
*/
function crb_empty_query() {
global $wpdb;
return 'SELECT 0 FROM ' . $wpdb->users;
}
/**
* This helps to get rid of PHP warnings
*
* @return WP_Error
*/
function crb_return_wp_error() {
return new WP_Error();
}
function _crb_ds_background() {
if ( ! CRB_DS::iterate_users() ) {
return 'done';
}
return 1;
}
Home - Capital GMC Buick Regina
Skip to content
{{ $t(category) }}
Error
{{vehicle.modelData.year}} {{vehicle.modelData.make}} {{vehicle.modelData.model}}
Starting from {{vehicle.modelData.startingPrice | moneyFormat(lang)}}
Welcome to Capital GMC BUICK – REGINA
Thank you for choosing Capital GMC Buick | Regina, your premier certified Buick and GMC dealership proudly serving drivers in Regina and the surrounding communities. Whether you’re searching for a brand-new Buick or GMC vehicle or a meticulously inspected pre-owned model, we have a diverse selection to match your needs and lifestyle.
Beyond our impressive inventory, we offer a seamless and stress-free financing experience through our well-connected finance centre, where our team of experts is dedicated to securing the best loan or lease options for you, quickly, transparently, and hassle-free.
But our commitment to you doesn’t stop at the sale. Our state-of-the-art service centre is staffed with skilled Buick and GMC technicians who use the latest equipment and genuine OEM parts to keep your vehicle running at its best. From routine maintenance to complex repairs, we’ve got you covered.
Experience top-tier customer service, quality vehicles, and expert care, all in one place. Visit Capital GMC Buick | Regina today or call us at 306-205-8072 with any questions. We’re here to help!
Ask a Question
Capital GMC Buick – Regina
Contact Us
Have a question or need assistance? Fill out the form and we will reach out to you as soon as possible.
Notice: JavaScript is required for this content.
CLOSE
Schedule a Visit
Let us know when you are coming and how we can assist you. We can ensure someone will be on hand to help you out at the desired date and time.
Notice: JavaScript is required for this content.
CLOSE
Find a Career
Have a look at our list of available positions and apply online today to join our team!
×
Opportunities to Grow
The auto industry is constantly changing and we want to continue to grow. We offer growth, leadership & mentorship programs to allow our staff to grow with us.
×
Competitive Salary
We have a significant earning potential with incentive-based pay in most roles. We also offer an employee referral bonus with paid bonuses.
×
Health & Dental
We offer a comprehensive benefits package including extended health, dental, and vision care. We also include paramedical, life insurance, paid sick leave, short & long-term disability coverages.
×
Vacation
We value our employees and want everyone to take their vacation time. We offer a minimum of 2 weeks vacation each year.
×
Training & Development
We have many opportunities for paid education and training in-house as well as training from the Manufacturer.
×
$10,000 Cash Giveaway – Terms & Conditions
All October long, stop by Capital GMC Buick Cadillac, to enter for your chance to win $10,000 cash. No purchase is required, but entries must be made in-store.
The contest is open to residents of Saskatchewan who are 18+. Dealership employees and their households are not eligible. Entries will be accepted from October 1 to October 31, 2025. A random draw will take place on November 1, 2025.
The prize is one $10,000 award, paid by cheque, and must be accepted as awarded. Winner will be contacted by phone or email and must respond within 7 days or another entry may be drawn. Odds of winning depend on the number of entries received.By entering, you agree that Capital Automotive Group may use your name and photo for winner announcements. The contest is governed by the laws of Saskatchewan.
Notice: JavaScript is required for this content.
CLOSE