Issues (2963)

includes/html/pages/device/edit/snmp.inc.php (1 issue)

1
<?php
2
3
use LibreNMS\Config;
4
5
if ($_POST['editing']) {
6
    if (Auth::user()->hasGlobalAdmin()) {
7
        $force_save = ($_POST['force_save'] == 'on');
8
        $poller_group = isset($_POST['poller_group']) ? $_POST['poller_group'] : 0;
9
        $snmp_enabled = ($_POST['snmp'] == 'on');
10
11
        if ($snmp_enabled) {
12
            $max_repeaters = $_POST['max_repeaters'];
13
            $max_oid = $_POST['max_oid'];
14
            $port = $_POST['port'] ? $_POST['port'] : Config::get('snmp.port');
15
            $port_assoc_mode = $_POST['port_assoc_mode'];
16
            $retries = $_POST['retries'];
17
            $snmpver = $_POST['snmpver'];
18
            $transport = $_POST['transport'] ? $_POST['transport'] : $transport = 'udp';
19
            $timeout = $_POST['timeout'];
20
21
            $update = [
22
                'poller_group' => $poller_group,
23
                'port' => $port,
24
                'port_association_mode' => $port_assoc_mode,
25
                'snmp_disable' => 0,
26
                'snmpver' => $snmpver,
27
                'transport' => $transport,
28
            ];
29
30
            if ($retries) {
31
                $update['retries'] = $retries;
32
            } else {
33
                $update['retries'] = ['NULL'];
34
            }
35
36
            if ($snmpver != 'v3') {
37
                $community = $_POST['community'];
38
                $update['community'] = $community;
39
            }
40
41
            if ($timeout) {
42
                $update['timeout'] = $timeout;
43
            } else {
44
                $update['timeout'] = ['NULL'];
45
            }
46
47
            $v3 = [];
48
            if ($snmpver == 'v3') {
49
                $community = ''; // if v3 works, we don't need a community
50
51
                $v3['authalgo'] = $_POST['authalgo'];
52
                $v3['authlevel'] = $_POST['authlevel'];
53
                $v3['authname'] = $_POST['authname'];
54
                $v3['authpass'] = $_POST['authpass'];
55
                $v3['cryptoalgo'] = $_POST['cryptoalgo'];
56
                $v3['cryptopass'] = $_POST['cryptopass'];
57
58
                $update = array_merge($update, $v3);
59
            }
60
        } else {
61
            // snmp is disabled
62
            $update['features'] = null;
63
            $update['hardware'] = $_POST['hardware'];
64
            $update['icon'] = null;
65
            $update['os'] = $_POST['os'] ? $_POST['os_id'] : 'ping';
66
            $update['poller_group'] = $poller_group;
67
            $update['snmp_disable'] = 1;
68
            $update['sysName'] = $_POST['sysName'] ? $_POST['sysName'] : null;
69
            $update['version'] = null;
70
        }
71
72
        $device_is_snmpable = false;
73
        $rows_updated = 0;
74
75
        if ($force_save !== true && $snmp_enabled) {
76
            $device_snmp_details = deviceArray($device['hostname'], $community, $snmpver, $port, $transport, $v3, $port_assoc_mode);
77
            $device_issnmpable = isSNMPable($device_snmp_details);
78
        }
79
80
        if ($force_save === true || ! $snmp_enabled || $device_issnmpable) {
81
            // update devices table
82
            $rows_updated = dbUpdate($update, 'devices', '`device_id` = ?', [$device['device_id']]);
83
        }
84
85
        if ($snmp_enabled && ($force_save === true || $device_issnmpable)) {
86
            // update devices_attribs table
87
88
            // note:
89
            // set_dev_attrib and del_dev_attrib *only* return (bool)
90
            // setAttrib() returns true if it was set and false if it was not (e.g. it didn't change)
91
            // forgetAttrib() returns true if it was deleted and false if it was not (e.g. it didn't exist)
92
            // Symfony throws FatalThrowableError on error
93
94
            $devices_attribs = ['snmp_max_repeaters', 'snmp_max_oid'];
95
96
            foreach ($devices_attribs as $devices_attrib) {
97
                // defaults
98
                $feedback_prefix = $devices_attrib;
99
                $form_value = null;
100
                $form_value_is_numeric = false; // does not need to be a number greater than zero
101
102
                if ($devices_attrib == 'snmp_max_repeaters') {
103
                    $feedback_prefix = 'SNMP Max Repeaters';
104
                    $form_value = $max_repeaters;
105
                    $form_value_is_numeric = true;
106
                }
107
108
                if ($devices_attrib == 'snmp_max_oid') {
109
                    $feedback_prefix = 'SNMP Max OID';
110
                    $form_value = $max_oid;
111
                    $form_value_is_numeric = true;
112
                }
113
114
                $get_devices_attrib = get_dev_attrib($device, $devices_attrib);
115
                $set_devices_attrib = false; // testing $set_devices_attrib === false is not a true indicator of a failure
116
117
                if ($form_value != $get_devices_attrib && $form_value_is_numeric && is_numeric($form_value) && $form_value != 0) {
118
                    $set_devices_attrib = set_dev_attrib($device, $devices_attrib, $form_value);
119
                }
120
121
                if ($form_value != $get_devices_attrib && ! $form_value_is_numeric) {
122
                    $set_devices_attrib = set_dev_attrib($device, $devices_attrib, $form_value);
123
                }
124
125
                if ($form_value != $get_devices_attrib && $form_value_is_numeric && ! is_numeric($form_value)) {
126
                    $set_devices_attrib = del_dev_attrib($device, $devices_attrib);
127
                }
128
129
                if ($form_value != $get_devices_attrib && ! $form_value_is_numeric && $form_value == '') {
130
                    $set_devices_attrib = del_dev_attrib($device, $devices_attrib);
131
                }
132
133
                if ($form_value != $get_devices_attrib && $set_devices_attrib) {
134
                    $set_devices_attrib = get_dev_attrib($device, $devices_attrib); // re-check the db value
135
                }
136
137
                if ($form_value != $get_devices_attrib && $form_value == $set_devices_attrib && (is_null($set_devices_attrib) || $set_devices_attrib == '')) {
138
                    $update_message[] = "$feedback_prefix deleted";
139
                }
140
141
                if ($form_value != $get_devices_attrib && $form_value == $set_devices_attrib && (! is_null($set_devices_attrib) && $set_devices_attrib != '')) {
142
                    $update_message[] = "$feedback_prefix updated to $set_devices_attrib";
143
                }
144
145
                if ($form_value != $get_devices_attrib && $form_value != $set_devices_attrib) {
146
                    $update_failed_message[] = "$feedback_prefix update failed.";
147
                }
148
149
                unset($get_devices_attrib, $set_devices_attrib);
150
            }
151
            unset($devices_attrib);
152
        }
153
154
        if ($rows_updated > 0) {
155
            $update_message[] = 'Device record updated';
156
        }
157
158
        if ($snmp_enabled && ($force_save !== true && ! $device_issnmpable)) {
159
            $update_failed_message[] = 'Could not connect to ' . htmlspecialchars($device['hostname']) . ' with those SNMP settings.  To save anyway, turn on Force Save.';
160
            $update_message[] = 'SNMP settings reverted';
161
        }
162
163
        if ($rows_updated == 0 && ! isset($update_message) && ! isset($update_failed_message)) {
164
            $update_message[] = 'SNMP settings did not change';
165
        }
166
    }//end if (Auth::user()->hasGlobalAdmin())
167
}//end if ($_POST['editing'])
168
169
// the following unsets are for security; the database is authoritative
170
// i.e. prevent unintentional artifacts from being saved or used (again), posting around the form, etc.
171
unset($_POST);
172
// these are only used for editing and should not be used as-is
173
unset($force_save, $poller_group, $snmp_enabled);
174
unset($community, $max_repeaters, $max_oid, $port, $port_assoc_mode, $retries, $snmpver, $transport, $timeout);
175
176
// get up-to-date database values for use on the form
177
$device = dbFetchRow('SELECT * FROM `devices` WHERE `device_id` = ?', [$device['device_id']]);
178
$max_oid = get_dev_attrib($device, 'snmp_max_oid');
179
$max_repeaters = get_dev_attrib($device, 'snmp_max_repeaters');
180
181
echo '<h3> SNMP Settings </h3>';
182
183
// use Toastr to print normal (success) messages, similar to Device Settings
184
if (isset($update_message)) {
185
    $toastr_options = [];
186
187
    if (is_array($update_message)) {
188
        foreach ($update_message as $message) {
189
            Toastr::success($message, null, $toastr_options);
190
        }
191
    }
192
193
    if (is_string($update_message)) {
194
        Toastr::success($update_message, null, $toastr_options);
195
    }
196
197
    unset($message, $toastr_options, $update_message);
198
}
199
200
// use Toastr:error to call attention to the problem; don't let it time out
201
if (isset($update_failed_message)) {
202
    $toastr_options = [];
203
    $toastr_options['closeButton'] = true;
204
    $toastr_options['extendedTimeOut'] = 0;
205
    $toastr_options['timeOut'] = 0;
206
207
    if (is_array($update_failed_message)) {
208
        foreach ($update_failed_message as $error) {
209
            Toastr::error($error, null, $toastr_options);
210
        }
211
    }
212
213
    if (is_string($update_failed_message)) {
214
        Toastr::error($update_failed_message, null, $toastr_options);
215
    }
216
217
    unset($error, $update_failed_message);
218
}
219
220
echo "
221
    <form id='edit' name='edit' method='post' action='' role='form' class='form-horizontal'>
222
    " . csrf_field() . "
223
    <div class='form-group'>
224
    <label for='hardware' class='col-sm-2 control-label'>SNMP</label>
225
    <div class='col-sm-4'>
226
    <input type='checkbox' id='snmp' name='snmp' data-size='small' onChange='disableSnmp(this);'" . ($device['snmp_disable'] ? '' : ' checked') . ">
227
    </div>
228
    </div>
229
    <div id='snmp_override' style='display: " . ($device['snmp_disable'] ? 'block' : 'none') . ";'>
230
    <div class='form-group'>
231
    <label for='sysName' class='col-sm-2 control-label'>sysName (optional)</label>
232
    <div class='col-sm-4'>
233
    <input id='sysName' class='form-control' name='sysName' value='" . htmlspecialchars($device['sysName']) . "'/>
234
    </div>
235
    </div>
236
    <div class='form-group'>
237
    <label for='hardware' class='col-sm-2 control-label'>Hardware (optional)</label>
238
    <div class='col-sm-4'>
239
    <input id='hardware' class='form-control' name='hardware' value='" . htmlspecialchars($device['hardware']) . "'/>
240
    </div>
241
    </div>
242
    <div class='form-group'>
243
    <label for='os' class='col-sm-2 control-label'>OS (optional)</label>
244
    <div class='col-sm-4'>
245
    <input id='os' class='form-control' name='os' value='" . htmlspecialchars(Config::get("os.{$device['os']}.text")) . "'/>
0 ignored issues
show
It seems like LibreNMS\Config::get('os.'.$device['os'].'.text') can also be of type null; however, parameter $string of htmlspecialchars() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

245
    <input id='os' class='form-control' name='os' value='" . htmlspecialchars(/** @scrutinizer ignore-type */ Config::get("os.{$device['os']}.text")) . "'/>
Loading history...
246
    <input type='hidden' id='os_id' class='form-control' name='os_id' value='" . $device['os'] . "'/>
247
    </div>
248
    </div>
249
    </div>
250
    <div id='snmp_conf' style='display: " . ($device['snmp_disable'] ? 'none' : 'block') . ";'>
251
    <input type=hidden name='editing' value='yes'>
252
    <div class='form-group'>
253
    <label for='snmpver' class='col-sm-2 control-label'>SNMP Details</label>
254
    <div class='col-sm-1'>
255
    <select id='snmpver' name='snmpver' class='form-control input-sm' onChange='changeForm();'>
256
    <option value='v1'>v1</option>
257
    <option value='v2c' " . ($device['snmpver'] == 'v2c' ? 'selected' : '') . ">v2c</option>
258
    <option value='v3' " . ($device['snmpver'] == 'v3' ? 'selected' : '') . ">v3</option>
259
    </select>
260
    </div>
261
    <div class='col-sm-2'>
262
    <input type='number' name='port' placeholder='port' class='form-control input-sm' value='" . htmlspecialchars($device['port'] == Config::get('snmp.port') ? '' : $device['port']) . "'>
263
    </div>
264
    <div class='col-sm-1'>
265
    <select name='transport' id='transport' class='form-control input-sm'>";
266
foreach (Config::get('snmp.transports') as $transport) {
267
    echo "<option value='" . $transport . "'";
268
    if ($transport == $device['transport']) {
269
        echo " selected='selected'";
270
    }
271
272
    echo '>' . $transport . '</option>';
273
}
274
275
echo "      </select>
276
    </div>
277
    </div>
278
    <div class='form-group'>
279
    <div class='col-sm-2'>
280
    </div>
281
    <div class='col-sm-1'>
282
    <input type='number' id='timeout' name='timeout' class='form-control input-sm' value='" . htmlspecialchars($device['timeout'] ? $device['timeout'] : '') . "' placeholder='seconds' />
283
    </div>
284
    <div class='col-sm-1'>
285
    <input type='number' id='retries' name='retries' class='form-control input-sm' value='" . htmlspecialchars($device['timeout'] ? $device['retries'] : '') . "' placeholder='retries' />
286
    </div>
287
    </div>
288
    <div class='form-group'>
289
      <label for='port_assoc_mode' class='col-sm-2 control-label'>Port Association Mode</label>
290
      <div class='col-sm-1'>
291
        <select name='port_assoc_mode' id='port_assoc_mode' class='form-control input-sm'>
292
";
293
294
foreach (get_port_assoc_modes() as $pam_id => $pam) {
295
    echo "           <option value='$pam_id'";
296
297
    if ($pam_id == $device['port_association_mode']) {
298
        echo " selected='selected'";
299
    }
300
301
    echo ">$pam</option>\n";
302
}
303
304
['sha2' => $snmpv3_sha2, 'aes256' => $snmpv3_aes256] = snmpv3_capabilities();
305
echo "        </select>
306
      </div>
307
    </div>
308
    <div class='form-group'>
309
        <label for='max_repeaters' class='col-sm-2 control-label'>Max Repeaters</label>
310
        <div class='col-sm-1'>
311
            <input type='number' id='max_repeaters' name='max_repeaters' class='form-control input-sm' value='" . htmlspecialchars($max_repeaters) . "' placeholder='max repeaters' />
312
        </div>
313
    </div>
314
    <div class='form-group'>
315
        <label for='max_oid' class='col-sm-2 control-label'>Max OIDs</label>
316
        <div class='col-sm-1'>
317
            <input type='number' id='max_oid' name='max_oid' class='form-control input-sm' value='" . htmlspecialchars($max_oid) . "' placeholder='max oids' />
318
        </div>
319
    </div>
320
    <div id='snmpv1_2'>
321
    <div class='form-group'>
322
    <label class='col-sm-3 control-label text-left'><h4><strong>SNMPv1/v2c Configuration</strong></h4></label>
323
    </div>
324
    <div class='form-group'>
325
    <label for='community' class='col-sm-2 control-label'>SNMP Community</label>
326
    <div class='col-sm-4'>
327
    <input id='community' class='form-control' name='community' value='" . htmlspecialchars($device['community']) . "'/>
328
    </div>
329
    </div>
330
    </div>
331
    <div id='snmpv3'>
332
    <div class='form-group'>
333
    <label class='col-sm-3 control-label'><h4><strong>SNMPv3 Configuration</strong></h4></label>
334
    </div>
335
    <div class='form-group'>
336
    <label for='authlevel' class='col-sm-2 control-label'>Auth Level</label>
337
    <div class='col-sm-4'>
338
    <select id='authlevel' name='authlevel' class='form-control'>
339
    <option value='noAuthNoPriv'>noAuthNoPriv</option>
340
    <option value='authNoPriv' " . ($device['authlevel'] == 'authNoPriv' ? 'selected' : '') . ">authNoPriv</option>
341
    <option value='authPriv' " . ($device['authlevel'] == 'authPriv' ? 'selected' : '') . ">authPriv</option>
342
    </select>
343
    </div>
344
    </div>
345
    <div class='form-group'>
346
    <label for='authname' class='col-sm-2 control-label'>Auth User Name</label>
347
    <div class='col-sm-4'>
348
    <input type='text' id='authname' name='authname' class='form-control' value='" . htmlspecialchars($device['authname']) . "' autocomplete='off'>
349
    </div>
350
    </div>
351
    <div class='form-group'>
352
    <label for='authpass' class='col-sm-2 control-label'>Auth Password</label>
353
    <div class='col-sm-4'>
354
    <input type='password' id='authpass' name='authpass' class='form-control' value='" . htmlspecialchars($device['authpass']) . "' autocomplete='off'>
355
    </div>
356
    </div>
357
    <div class='form-group'>
358
    <label for='authalgo' class='col-sm-2 control-label'>Auth Algorithm</label>
359
    <div class='col-sm-4'>
360
    <select id='authalgo' name='authalgo' class='form-control'>
361
    <option value='MD5'>MD5</option>
362
    <option value='SHA' " . ($device['authalgo'] === 'SHA' ? 'selected' : '') . ">SHA</option>
363
    <option value='SHA-224' " . ($device['authalgo'] === 'SHA-224' ? 'selected' : '') . ($snmpv3_sha2 ? '' : ' disabled') . ">SHA-224</option>
364
    <option value='SHA-256' " . ($device['authalgo'] === 'SHA-256' ? 'selected' : '') . ($snmpv3_sha2 ? '' : ' disabled') . ">SHA-256</option>
365
    <option value='SHA-384' " . ($device['authalgo'] === 'SHA-384' ? 'selected' : '') . ($snmpv3_sha2 ? '' : ' disabled') . ">SHA-384</option>
366
    <option value='SHA-512' " . ($device['authalgo'] === 'SHA-512' ? 'selected' : '') . ($snmpv3_sha2 ? '' : ' disabled') . '>SHA-512</option>
367
    </select>
368
    ';
369
if (! $snmpv3_sha2) {
370
    echo '<label class="text-left"><small>Some options are disabled. <a href="https://docs.librenms.org/Support/FAQ/#optional-requirements-for-snmpv3-sha2-auth">Read more here</a></small></label>';
371
}
372
    echo "
373
    </div>
374
    </div>
375
    <div class='form-group'>
376
    <label for='cryptopass' class='col-sm-2 control-label'>Crypto Password</label>
377
    <div class='col-sm-4'>
378
    <input type='password' id='cryptopass' name='cryptopass' class='form-control' value='" . htmlspecialchars($device['cryptopass']) . "' autocomplete='off'>
379
    </div>
380
    </div>
381
    <div class='form-group'>
382
    <label for='cryptoalgo' class='col-sm-2 control-label'>Crypto Algorithm</label>
383
    <div class='col-sm-4'>
384
    <select id='cryptoalgo' name='cryptoalgo' class='form-control'>
385
    <option value='AES' " . ($device['cryptoalgo'] === 'AES' ? 'selected' : '') . ">AES</option>
386
    <option value='AES-192' " . ($device['cryptoalgo'] === 'AES-192' ? 'selected' : '') . ($snmpv3_aes256 ? '' : ' disabled') . ">AES-192</option>
387
    <option value='AES-256' " . ($device['cryptoalgo'] === 'AES-256' ? 'selected' : '') . ($snmpv3_aes256 ? '' : ' disabled') . ">AES-256</option>
388
    <option value='AES-256-C' " . ($device['cryptoalgo'] === 'AES-256-C' ? 'selected' : '') . ($snmpv3_aes256 ? '' : ' disabled') . ">AES-256 Cisco</option>
389
    <option value='DES' " . ($device['cryptoalgo'] === 'DES' ? 'selected' : '') . '>DES</option>
390
    </select>
391
    ';
392
if (! $snmpv3_aes256) {
393
    echo '<label class="text-left"><small>Some options are disabled. <a href="https://docs.librenms.org/Support/FAQ/#optional-requirements-for-snmpv3-sha2-auth">Read more here</a></small></label>';
394
}
395
    echo '
396
    </div>
397
    </div>
398
    </div>';
399
?>
400
401
</div>
402
<?php
403
404
if (Config::get('distributed_poller') === true) {
405
    echo '
406
        <div class="form-group">
407
        <label for="poller_group" class="col-sm-2 control-label">Poller Group</label>
408
        <div class="col-sm-4">
409
        <select name="poller_group" id="poller_group" class="form-control input-sm">
410
        <option value="0"> Default poller group</option>
411
        ';
412
413
    foreach (dbFetchRows('SELECT `id`,`group_name` FROM `poller_groups`') as $group) {
414
        echo '<option value="' . $group['id'] . '"';
415
        if ($device['poller_group'] == $group['id']) {
416
            echo ' selected';
417
        }
418
419
        echo '>' . htmlspecialchars($group['group_name']) . '</option>';
420
    }
421
422
    echo '
423
        </select>
424
        </div>
425
        </div>
426
        ';
427
}//end if
428
?>
429
430
<div class="form-group">
431
    <label for="force_save" class="control-label col-sm-2">Force Save</label>
432
    <div class="col-sm-9">
433
         <input type="checkbox" name="force_save" id="force_save" data-size="small">
434
    </div>
435
</div>
436
437
<div class="row">
438
    <div class="col-md-1 col-md-offset-2">
439
        <button type="submit" name="Submit"  class="btn btn-success"><i class="fa fa-check"></i> Save</button>
440
    </div>
441
</div>
442
</form>
443
444
<script>
445
$('[name="force_save"]').bootstrapSwitch();
446
447
function changeForm() {
448
    snmpVersion = $("#snmpver").val();
449
    if(snmpVersion == 'v1' || snmpVersion == 'v2c') {
450
        $('#snmpv1_2').show();
451
        $('#snmpv3').hide();
452
    }
453
    else if(snmpVersion == 'v3') {
454
        $('#snmpv1_2').hide();
455
        $('#snmpv3').show();
456
    }
457
}
458
function disableSnmp(e) {
459
    if(e.checked) {
460
        $('#snmp_conf').show();
461
        $('#snmp_override').hide();
462
    } else {
463
        $('#snmp_conf').hide();
464
        $('#snmp_override').show();
465
    }
466
}
467
468
var os_suggestions = new Bloodhound({
469
    datumTokenizer: Bloodhound.tokenizers.obj.whitespace('text'),
470
    queryTokenizer: Bloodhound.tokenizers.whitespace,
471
    remote: {
472
        url: "ajax_ossuggest.php?term=%QUERY",
473
        filter: function (output) {
474
            return $.map(output, function (item) {
475
                return {
476
                    text: item.text,
477
                    os: item.os,
478
                };
479
            });
480
        },
481
        wildcard: "%QUERY"
482
    }
483
});
484
os_suggestions.initialize();
485
$('#os').typeahead({
486
        hint: true,
487
        highlight: true,
488
        minLength: 1,
489
        classNames: {
490
            menu: 'typeahead-left'
491
        }
492
    },
493
    {
494
        source: os_suggestions.ttAdapter(),
495
        async: true,
496
        displayKey: 'text',
497
        valueKey: 'os',
498
        templates: {
499
            suggestion: Handlebars.compile('<p>&nbsp;{{text}}</p>')
500
        },
501
        limit: 20
502
    });
503
504
$("#os").on("typeahead:selected typeahead:autocompleted", function(e,datum) {
505
    $("#os_id").val(datum.os);
506
    $("#os").html('<mark>' + datum.text + '</mark>');
507
});
508
509
$("[name='snmp']").bootstrapSwitch('offColor','danger');
510
511
<?php
512
if ($device['snmpver'] == 'v3') {
513
    echo "$('#snmpv1_2').hide();";
514
    echo "$('#snmpv3').show();";
515
} else {
516
    echo "$('#snmpv1_2').show();";
517
    echo "$('#snmpv3').hide();";
518
}
519
520
?>
521
</script>
522