| @@ -115,10 +115,10 @@ | ||
| 115 | 115 | |
| 116 | 116 | public function process_input() { |
| 117 | 117 | $this->request = array(); |
| 118 | 118 | |
| 119 | - if ( !empty( $_REQUEST ) ) { | |
| 120 | - $this->request = $_REQUEST; | |
| 119 | + if ( ! empty( $_REQUEST ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Custom troubleshooter API authenticated via PDT_Auth nonce; runs standalone when the WP REST API is unavailable. | |
| 120 | + $this->request = $_REQUEST; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- See above; params validated downstream in process_params(). | |
| 121 | 121 | } |
| 122 | 122 | |
| 123 | 123 | $json = file_get_contents("php://input"); |
| 124 | 124 | if ( empty( $json ) ) { |
| @@ -163,26 +163,18 @@ | ||
| 163 | 163 | } |
| 164 | 164 | |
| 165 | 165 | // Authentication Request |
| 166 | 166 | if ( $this->params['action'] == 'authenticate' ) { |
| 167 | - $auth_response = $this->plugin->auth->get_nonce( $this->params['username'], $this->params['password'], 'pd_api' ); | |
| 167 | + $user = $this->plugin->auth->authenticate( $this->params['username'], $this->params['password'] ); | |
| 168 | 168 | |
| 169 | - if ( is_a( $auth_response, 'WP_Error' ) ) { | |
| 170 | - $this->errors['authentication'] = array_keys( $auth_response->errors ); | |
| 171 | - $this->errors['authentication'] = $this->errors['authentication']['0']; | |
| 169 | + if ( is_a( $user, 'WP_Error' ) ) { | |
| 170 | + // Single, fixed error code for every failure mode — never echo a | |
| 171 | + // code that distinguishes a valid username from an invalid one. | |
| 172 | + $this->errors['authentication'] = $user->get_error_code(); | |
| 172 | 173 | } else { |
| 173 | - $this->data['nonce'] = $auth_response; | |
| 174 | + $this->data['nonce'] = $this->plugin->auth->create_nonce( 'pd_api', $user->ID ); | |
| 174 | 175 | } |
| 175 | 176 | |
| 176 | - $user_response = $this->plugin->auth->get_user( $this->params['username'], $this->params['password'], 'pd_api' ); | |
| 177 | - | |
| 178 | - if ( is_a( $user_response, 'WP_Error' ) ) { | |
| 179 | - $this->errors['authentication'] = array_keys( $user_response->errors ); | |
| 180 | - $this->errors['authentication'] = $this->errors['authentication']['0']; | |
| 181 | - } else { | |
| 182 | - $this->data['user'] = $user_response; | |
| 183 | - } | |
| 184 | - | |
| 185 | 177 | $this->return_response(); |
| 186 | 178 | } |
| 187 | 179 | |
| 188 | 180 | |
| @@ -191,10 +183,19 @@ | ||
| 191 | 183 | $this->errors['nonce'] = 'Required for authenticated requests'; |
| 192 | 184 | $this->return_response(); |
| 193 | 185 | } |
| 194 | 186 | |
| 195 | - if ( ! $this->plugin->auth->verify_nonce( $this->params['nonce'], 'pd_api' ) ) { | |
| 187 | + $nonce_user_id = $this->plugin->auth->verify_nonce( $this->params['nonce'], 'pd_api' ); | |
| 188 | + if ( empty( $nonce_user_id ) ) { | |
| 196 | 189 | $this->errors['nonce'] = 'Invalid'; |
| 190 | + $this->return_response(); | |
| 191 | + } | |
| 192 | + | |
| 193 | + // The nonce is bound to the user it was issued for. Re-check that user still | |
| 194 | + // has plugin-management rights so a token can never authorize more than its | |
| 195 | + // owner, even if it leaks or the user's role is later downgraded. | |
| 196 | + if ( ! user_can( $nonce_user_id, 'activate_plugins' ) ) { | |
| 197 | + $this->errors['permission'] = 'You do not have permission to perform this action'; | |
| 197 | 198 | $this->return_response(); |
| 198 | 199 | } |
| 199 | 200 | |
| 200 | 201 | |