1<?php declare(strict_types = 1); 2/* 3** Zabbix 4** Copyright (C) 2001-2021 Zabbix SIA 5** 6** This program is free software; you can redistribute it and/or modify 7** it under the terms of the GNU General Public License as published by 8** the Free Software Foundation; either version 2 of the License, or 9** (at your option) any later version. 10** 11** This program is distributed in the hope that it will be useful, 12** but WITHOUT ANY WARRANTY; without even the implied warranty of 13** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14** GNU General Public License for more details. 15** 16** You should have received a copy of the GNU General Public License 17** along with this program; if not, write to the Free Software 18** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19**/ 20 21 22/** 23 * Class containing methods for operations with authentication parameters. 24 */ 25class CAuthentication extends CApiService { 26 27 public const ACCESS_RULES = [ 28 'get' => ['min_user_type' => USER_TYPE_SUPER_ADMIN], 29 'update' => ['min_user_type' => USER_TYPE_SUPER_ADMIN] 30 ]; 31 32 /** 33 * @var string 34 */ 35 protected $tableName = 'config'; 36 37 /** 38 * @var string 39 */ 40 protected $tableAlias = 'c'; 41 42 /** 43 * @var array 44 */ 45 private $output_fields = ['authentication_type', 'http_auth_enabled', 'http_login_form', 'http_strip_domains', 46 'http_case_sensitive', 'ldap_configured', 'ldap_host', 'ldap_port', 'ldap_base_dn', 'ldap_search_attribute', 47 'ldap_bind_dn', 'ldap_case_sensitive', 'ldap_bind_password', 'saml_auth_enabled', 'saml_idp_entityid', 48 'saml_sso_url', 'saml_slo_url', 'saml_username_attribute', 'saml_sp_entityid', 'saml_nameid_format', 49 'saml_sign_messages', 'saml_sign_assertions', 'saml_sign_authn_requests', 'saml_sign_logout_requests', 50 'saml_sign_logout_responses', 'saml_encrypt_nameid', 'saml_encrypt_assertions', 'saml_case_sensitive' 51 ]; 52 53 /** 54 * Get authentication parameters. 55 * 56 * @param array $options 57 * 58 * @throws APIException if the input is invalid. 59 * 60 * @return array 61 */ 62 public function get(array $options): array { 63 $api_input_rules = ['type' => API_OBJECT, 'fields' => [ 64 'output' => ['type' => API_OUTPUT, 'in' => implode(',', $this->output_fields), 65 'default' => API_OUTPUT_EXTEND] 66 ]]; 67 if (!CApiInputValidator::validate($api_input_rules, $options, '/', $error)) { 68 self::exception(ZBX_API_ERROR_PARAMETERS, $error); 69 } 70 71 if ($options['output'] === API_OUTPUT_EXTEND) { 72 $options['output'] = $this->output_fields; 73 } 74 75 $db_auth = []; 76 77 $result = DBselect($this->createSelectQuery($this->tableName(), $options)); 78 while ($row = DBfetch($result)) { 79 $db_auth[] = $row; 80 } 81 $db_auth = $this->unsetExtraFields($db_auth, ['configid'], []); 82 83 return $db_auth[0]; 84 } 85 86 /** 87 * Update authentication parameters. 88 * 89 * @param array $auth 90 * 91 * @return array 92 */ 93 public function update(array $auth): array { 94 $db_auth = $this->validateUpdate($auth); 95 96 $upd_config = []; 97 98 // strings 99 $field_names = ['http_strip_domains', 'ldap_host', 'ldap_base_dn', 'ldap_search_attribute', 'ldap_bind_dn', 100 'ldap_bind_password' 101 ]; 102 foreach ($field_names as $field_name) { 103 if (array_key_exists($field_name, $auth) && $auth[$field_name] !== $db_auth[$field_name]) { 104 $upd_config[$field_name] = $auth[$field_name]; 105 } 106 } 107 108 // integers 109 $field_names = ['authentication_type', 'http_auth_enabled', 'http_login_form', 'http_case_sensitive', 110 'ldap_configured', 'ldap_port', 'ldap_case_sensitive', 'saml_auth_enabled', 'saml_idp_entityid', 111 'saml_sso_url', 'saml_slo_url', 'saml_username_attribute', 'saml_sp_entityid', 'saml_nameid_format', 112 'saml_sign_messages', 'saml_sign_assertions', 'saml_sign_authn_requests', 'saml_sign_logout_requests', 113 'saml_sign_logout_responses', 'saml_encrypt_nameid', 'saml_encrypt_assertions', 'saml_case_sensitive' 114 ]; 115 foreach ($field_names as $field_name) { 116 if (array_key_exists($field_name, $auth) && $auth[$field_name] != $db_auth[$field_name]) { 117 $upd_config[$field_name] = $auth[$field_name]; 118 } 119 } 120 121 if ($upd_config) { 122 DB::update('config', [ 123 'values' => $upd_config, 124 'where' => ['configid' => $db_auth['configid']] 125 ]); 126 } 127 128 $this->addAuditBulk(AUDIT_ACTION_UPDATE, AUDIT_RESOURCE_AUTHENTICATION, 129 [['configid' => $db_auth['configid']] + $auth], [$db_auth['configid'] => $db_auth] 130 ); 131 132 return array_keys($auth); 133 } 134 135 /** 136 * Validate updated authentication parameters. 137 * 138 * @param array $auth 139 * 140 * @throws APIException if the input is invalid. 141 * 142 * @return array 143 */ 144 protected function validateUpdate(array $auth): array { 145 $api_input_rules = ['type' => API_OBJECT, 'flags' => API_NOT_EMPTY, 'fields' => [ 146 'authentication_type' => ['type' => API_INT32, 'in' => ZBX_AUTH_INTERNAL.','.ZBX_AUTH_LDAP], 147 'http_auth_enabled' => ['type' => API_INT32, 'in' => ZBX_AUTH_HTTP_DISABLED.','.ZBX_AUTH_HTTP_ENABLED], 148 'http_login_form' => ['type' => API_INT32, 'in' => ZBX_AUTH_FORM_ZABBIX.','.ZBX_AUTH_FORM_HTTP], 149 'http_strip_domains' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('config', 'http_strip_domains')], 150 'http_case_sensitive' => ['type' => API_INT32, 'in' => ZBX_AUTH_CASE_INSENSITIVE.','.ZBX_AUTH_CASE_SENSITIVE], 151 'ldap_configured' => ['type' => API_INT32, 'in' => ZBX_AUTH_LDAP_DISABLED.','.ZBX_AUTH_LDAP_ENABLED], 152 'ldap_host' => ['type' => API_STRING_UTF8, 'flags' => API_NOT_EMPTY, 'length' => DB::getFieldLength('config', 'ldap_host')], 153 'ldap_port' => ['type' => API_INT32, 'in' => '0:65535'], 154 'ldap_base_dn' => ['type' => API_STRING_UTF8, 'flags' => API_NOT_EMPTY, 'length' => DB::getFieldLength('config', 'ldap_base_dn')], 155 'ldap_search_attribute' => ['type' => API_STRING_UTF8, 'flags' => API_NOT_EMPTY, 'length' => DB::getFieldLength('config', 'ldap_search_attribute')], 156 'ldap_bind_dn' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('config', 'ldap_bind_dn')], 157 'ldap_case_sensitive' => ['type' => API_INT32, 'in' => ZBX_AUTH_CASE_INSENSITIVE.','.ZBX_AUTH_CASE_SENSITIVE], 158 'ldap_bind_password' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('config', 'ldap_bind_password')], 159 'saml_auth_enabled' => ['type' => API_INT32, 'in' => ZBX_AUTH_HTTP_DISABLED.','.ZBX_AUTH_HTTP_ENABLED], 160 'saml_idp_entityid' => ['type' => API_STRING_UTF8, 'flags' => API_NOT_EMPTY, 'length' => DB::getFieldLength('config', 'saml_idp_entityid')], 161 'saml_sso_url' => ['type' => API_STRING_UTF8, 'flags' => API_NOT_EMPTY, 'length' => DB::getFieldLength('config', 'saml_sso_url')], 162 'saml_slo_url' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('config', 'saml_slo_url')], 163 'saml_username_attribute' => ['type' => API_STRING_UTF8, 'flags' => API_NOT_EMPTY, 'length' => DB::getFieldLength('config', 'saml_username_attribute')], 164 'saml_sp_entityid' => ['type' => API_STRING_UTF8, 'flags' => API_NOT_EMPTY, 'length' => DB::getFieldLength('config', 'saml_sp_entityid')], 165 'saml_nameid_format' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('config', 'saml_nameid_format')], 166 'saml_sign_messages' => ['type' => API_INT32, 'in' => '0,1'], 167 'saml_sign_assertions' => ['type' => API_INT32, 'in' => '0,1'], 168 'saml_sign_authn_requests' => ['type' => API_INT32, 'in' => '0,1'], 169 'saml_sign_logout_requests' => ['type' => API_INT32, 'in' => '0,1'], 170 'saml_sign_logout_responses' => ['type' => API_INT32, 'in' => '0,1'], 171 'saml_encrypt_nameid' => ['type' => API_INT32, 'in' => '0,1'], 172 'saml_encrypt_assertions' => ['type' => API_INT32, 'in' => '0,1'], 173 'saml_case_sensitive' => ['type' => API_INT32, 'in' => ZBX_AUTH_CASE_INSENSITIVE.','.ZBX_AUTH_CASE_SENSITIVE] 174 ]]; 175 if (!CApiInputValidator::validate($api_input_rules, $auth, '/', $error)) { 176 self::exception(ZBX_API_ERROR_PARAMETERS, $error); 177 } 178 179 // Check permissions. 180 if (self::$userData['type'] != USER_TYPE_SUPER_ADMIN) { 181 self::exception(ZBX_API_ERROR_PERMISSIONS, _('No permissions to referred object or it does not exist!')); 182 } 183 184 $output_fields = $this->output_fields; 185 $output_fields[] = 'configid'; 186 187 return DB::select('config', ['output' => $output_fields])[0]; 188 } 189} 190