Projet

Général

Profil

Paste
Télécharger (8,58 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / security_review / security_review.drush.inc @ 503b3f7b

1
<?php
2

    
3
/**
4
 * @file
5
 * Drush commands for Security Review module.
6
 */
7

    
8
// Include security_review.inc file for when invoked from outside the site.
9
require_once __DIR__ . '/security_review.inc';
10

    
11
/**
12
 * Implementation of hook_drush_command().
13
 */
14
function security_review_drush_command() {
15
  $items = array();
16

    
17
  $items['security-review'] = array(
18
    'callback' => 'security_review_drush',
19
    'aliases' => array('secrev'),
20
    'description' => "Run the Security Review checklist",
21
    'options' => array(
22
      'store' => 'Write results to the database',
23
      'log' => 'Log results of each check to watchdog, defaults to off',
24
      'lastrun' => 'Do not run the checklist, just print last results',
25
      'check' => 'Comma-separated list of specified checks to run. See README.txt for list of options',
26
      'short' => "Short result messages instead of full description (e.g. 'Text formats').",
27
      'results' => 'Show the incorrect settings for failed checks.',
28
    ),
29
    'examples' => array(
30
      'secrev' => 'Run the checklist and output the results',
31
      'secrev --store' => 'Run the checklist, store, and output the results',
32
      'secrev --lastrun' => 'Output the stored results from the last run of the checklist'
33
    ),
34
  );
35
  $items['password-check-setup'] = array(
36
    'callback' => 'security_review_drush_hash_setup',
37
    'aliases' => array('passset'),
38
    'description' => "Create and load a rainbow table for password checking",
39
  );
40

    
41
  return $items;
42
}
43

    
44
/**
45
 * Implementation of hook_drush_help().
46
 */
47
function security_review_drush_help($section) {
48
  switch ($section) {
49
    case 'drush:security-review':
50
      return dt("Run configuration security checks on your Drupal site.");
51
    case 'drush:password-check-setup':
52
      return dt("Creates a table and fills it with dictionary words for rainbow testing.");
53
  }
54
}
55

    
56
/**
57
 * Run checklist and display results command.
58
 */
59
function security_review_drush() {
60
  // Retrieve the checklist.
61
  $checklist = security_review_get_checklist();
62

    
63
  $store = drush_get_option('store');
64
  $log = drush_get_option('log');
65
  $lastrun = drush_get_option('lastrun');
66
  if (!function_exists('security_review_menu')) {
67
    // Checklist is being executed when module is disabled . Deny these
68
    // features.
69
    $store = $log = $lastrun = FALSE;
70
  }
71
  $specific_checks = drush_get_option_list('check');
72
  $short_titles = drush_get_option('short');
73
  if (!empty($short_titles)) {
74
    $short_titles = TRUE;
75
  }
76
  else {
77
    $short_titles = FALSE;
78
  }
79
  // Show failed check results only if security_review.help.inc exists.
80
  $show_results = drush_get_option('results');
81
  if ($show_results && file_exists(__DIR__ . '/security_review.help.inc')) {
82
    include_once __DIR__ . '/security_review.help.inc';
83
  }
84
  else {
85
    $show_results = FALSE;
86
  }
87

    
88
  if (!$lastrun) {
89
    if (!empty($specific_checks)) {
90
      // Run specified checks only.
91
      $new_checklist = array();
92
      foreach ($specific_checks as $check_name) {
93
        if (empty($check_name)) {
94
          continue; // Can happen if user puts space after comma.
95
        }
96
        if (strpos($check_name, ':') !== FALSE) {
97
          list($module, $check_name) = explode(':', $check_name);
98
        }
99
        else {
100
          $module = 'security_review';
101
        }
102
        if (isset($checklist[$module][$check_name])) {
103
          $new_checklist[$module][$check_name] = $checklist[$module][$check_name];
104
        }
105
      }
106
      $checklist = $new_checklist;
107
    }
108
    else {
109
      // Unset file_perms of security_review because drush is running as a
110
      // different user.
111
      unset($checklist['security_review']['file_perms']);
112
    }
113
    // Remove checks that are being skipped if storing.
114
    if ($store) {
115
      $skipped = security_review_skipped_checks();
116
      if (!empty($skipped)) {
117
        foreach ($skipped as $module => $checks) {
118
          foreach ($checks as $check_name => $check) {
119
            unset($checklist[$module][$check_name]);
120
          }
121
          if (empty($checklist[$module])) {
122
            unset($checklist[$module]);
123
          }
124
        }
125
      }
126
    }
127
    if (empty($checklist)) {
128
      return drush_set_error('EMPTY_CHECKLIST', dt("No checks to run. Run 'drush help secrev' for option use or consult the drush section of README.txt for further help."));
129
    }
130
    // Run the checklist.
131
    $checklist_results = security_review_run($checklist, $log ? TRUE : NULL);
132
    if ($store) {
133
      security_review_store_results($checklist_results);
134
    }
135
    // Print results.
136
    foreach ($checklist_results as $module => $checks) {
137
      foreach ($checks as $check_name => $check) {
138
        _security_review_drush_print_result($check, $short_titles, $show_results);
139
      }
140
    }
141
  }
142
  elseif ($lastrun) {
143
    // Retrieve results from last run of the checklist.
144
    $results = db_query("SELECT namespace, reviewcheck, result, lastrun, skip, skiptime, skipuid FROM {security_review}");
145
    while($record = $results->fetchAssoc()) {
146
      $checks[] = $record;
147
    }
148
    // Print results.
149
    if (!empty($checks)) {
150
      foreach ($checks as $check) {
151
        _security_review_drush_print_result($checklist[$check['namespace']][$check['reviewcheck']], $short_titles, $show_results);
152
      }
153
    }
154
  }
155
}
156

    
157
/**
158
 * Helper function to print Security Review results using drush_log().
159
 *
160
 * @param array $check
161
 *   Check array with keys 'title', 'success', 'failure', 'result'
162
 * @param boolean $short_titles
163
 *   Whether to use short message (check title) or full check success or failure
164
 *   message.
165
 * @param boolean $show_results
166
 *   Whether to print failed check results.
167
 * @return NULL
168
 */
169
function _security_review_drush_print_result($check, $short_titles = FALSE, $show_results = FALSE) {
170
  if (is_null($check['result'])) {
171
    // Do nothing if result is NULL.
172
    return;
173
  }
174
  elseif ($check['result']) {
175
    $element = $short_titles ? 'title' : 'success';
176
    $message = $check[$element];
177
    $status = 'success';
178
  }
179
  else {
180
    $element = $short_titles ? 'title' : 'failure';
181
    $message = $check[$element];
182
    if ($show_results) {
183
      $results = _security_review_drush_findings_output($check);
184
      if (!empty($results)) {
185
        $message .= "\n";
186
        foreach ($results as $item) {
187
          $message .= "\t" . $item . "\n";
188
        }
189
      }
190
    }
191
    $status = 'error';
192
  }
193
  drush_log($message, $status);
194
}
195

    
196
function _security_review_drush_findings_output($check) {
197
  $findings = array();
198
  if (isset($check['help'])) {
199
    $findings[] = $check['help'];
200
  }
201
  elseif (isset($check['callback'])) {
202
    if (isset($check['file'])) {
203
      // Handle Security Review defining checks for other modules.
204
      if (isset($check['module'])) {
205
        $module = $check['module'];
206
      }
207
      module_load_include('inc', $module, $check['file']);
208
    }
209
    $function = $check['callback'] . '_help';
210
    if (function_exists($function)) {
211
      $element = $function($check);
212
      if (is_array($element['findings']['items'])) {
213
        foreach ($element['findings']['items'] as $item) {
214
          if (is_array($item) && isset($item['raw'])) {
215
            $findings[] = $item['raw'];
216
          }
217
        }
218
      }
219

    
220
    }
221
  }
222
  return $findings;
223
}
224

    
225
function security_review_drush_hash_setup() {
226
  $args = func_get_args();
227
  if (empty($args)) {
228
    drush_set_error('SECURITY_REVIEW_ERROR', dt('Dictionary filename required'));
229
    return FALSE;
230
  }
231
  if (file_exists($args[0])) {
232
    $ret = array();
233
    // Create the rainbow table.
234
    if (!db_table_exists('security_review_rainbow')) {
235
      $schema = array(
236
        'fields' => array(
237
          'hash_id' => array(
238
            'type' => 'serial',
239
          ),
240
          'hash_word' => array(
241
            'type' => 'varchar',
242
            'length' => 20,
243
          ),
244
          'hash_hash' => array(
245
            'type' => 'varchar',
246
            'length' => 32,
247
          ),
248
        ),
249
        'primary key' => array('hash_id'),
250
        'indexes' => array('hash_hash' => array('hash_hash')),
251
      );
252
      db_create_table($ret, 'security_review_rainbow', $schema);
253
    }
254
    // Put an index on users.pass.
255
    db_drop_index($ret, 'users', 'pass'); // Drop in case this has already run.
256
    db_add_index($ret, 'users', 'pass', array('pass'));
257

    
258
    $handle = fopen($args[0], 'r');
259
    if ($handle) {
260
      $count = 0;
261
      while (!feof($handle)) {
262
        $buffer = fgets($handle, 4096);
263
        $word = trim($buffer);
264
        $hash = md5($hash);
265
        $sql = "INSERT INTO {security_review_rainbow} (hash_word, hash_hash) VALUES ('%s', '%s')";
266
        db_query($sql, $word, $hash);
267
        $count++;
268
      }
269
      fclose($handle);
270
      drush_log(dt('!count records inserted into rainbow table', array('!count' => $count)), 'success');
271
    }
272
  }
273
  else {
274
    drush_die('File not found');
275
  }
276
}