1 /*-
2 * Copyright (c) 2010,2018 The FreeBSD Foundation
3 * All rights reserved.
4 *
5 * This software was developed by Shteryana Sotirova Shopova under
6 * sponsorship from the FreeBSD Foundation.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $FreeBSD$
30 */
31 #include <sys/queue.h>
32 #include <sys/types.h>
33
34 #include <errno.h>
35 #include <stdarg.h>
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <stdint.h>
39 #include <string.h>
40 #include <syslog.h>
41
42 #include "asn1.h"
43 #include "snmp.h"
44 #include "snmpmod.h"
45
46 #define SNMPTREE_TYPES
47 #include "usm_tree.h"
48 #include "usm_oid.h"
49
50 static struct lmodule *usm_module;
51 /* For the registration. */
52 static const struct asn_oid oid_usm = OIDX_snmpUsmMIB;
53
54 static const struct asn_oid oid_usmNoAuthProtocol = OIDX_usmNoAuthProtocol;
55 static const struct asn_oid oid_usmHMACMD5AuthProtocol = \
56 OIDX_usmHMACMD5AuthProtocol;
57 static const struct asn_oid oid_usmHMACSHAAuthProtocol = \
58 OIDX_usmHMACSHAAuthProtocol;
59
60 static const struct asn_oid oid_usmNoPrivProtocol = OIDX_usmNoPrivProtocol;
61 static const struct asn_oid oid_usmDESPrivProtocol = OIDX_usmDESPrivProtocol;
62 static const struct asn_oid oid_usmAesCfb128Protocol = OIDX_usmAesCfb128Protocol;
63
64 static const struct asn_oid oid_usmUserSecurityName = OIDX_usmUserSecurityName;
65
66 /* The registration. */
67 static uint reg_usm;
68
69 static int32_t usm_lock;
70
71 static struct usm_user * usm_get_user(const struct asn_oid *, uint);
72 static struct usm_user * usm_get_next_user(const struct asn_oid *, uint);
73 static void usm_append_userindex(struct asn_oid *, uint,
74 const struct usm_user *);
75 static int usm_user_index_decode(const struct asn_oid *, uint, uint8_t *,
76 uint32_t *, char *);
77
78 int
op_usm_stats(struct snmp_context * ctx __unused,struct snmp_value * val,uint32_t sub __unused,uint32_t iidx __unused,enum snmp_op op)79 op_usm_stats(struct snmp_context *ctx __unused, struct snmp_value *val,
80 uint32_t sub __unused, uint32_t iidx __unused, enum snmp_op op)
81 {
82 struct snmpd_usmstat *usmstats;
83
84 if (op == SNMP_OP_SET)
85 return (SNMP_ERR_NOT_WRITEABLE);
86
87 if ((usmstats = bsnmpd_get_usm_stats()) == NULL)
88 return (SNMP_ERR_GENERR);
89
90 if (op == SNMP_OP_GET) {
91 switch (val->var.subs[sub - 1]) {
92 case LEAF_usmStatsUnsupportedSecLevels:
93 val->v.uint32 = usmstats->unsupported_seclevels;
94 break;
95 case LEAF_usmStatsNotInTimeWindows:
96 val->v.uint32 = usmstats->not_in_time_windows;
97 break;
98 case LEAF_usmStatsUnknownUserNames:
99 val->v.uint32 = usmstats->unknown_users;
100 break;
101 case LEAF_usmStatsUnknownEngineIDs:
102 val->v.uint32 = usmstats->unknown_engine_ids;
103 break;
104 case LEAF_usmStatsWrongDigests:
105 val->v.uint32 = usmstats->wrong_digests;
106 break;
107 case LEAF_usmStatsDecryptionErrors:
108 val->v.uint32 = usmstats->decrypt_errors;
109 break;
110 default:
111 return (SNMP_ERR_NOSUCHNAME);
112 }
113 return (SNMP_ERR_NOERROR);
114 }
115 abort();
116 }
117
118 int
op_usm_lock(struct snmp_context * ctx __unused,struct snmp_value * val,uint32_t sub,uint32_t iidx __unused,enum snmp_op op)119 op_usm_lock(struct snmp_context *ctx __unused, struct snmp_value *val,
120 uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
121 {
122 if (val->var.subs[sub - 1] != LEAF_usmUserSpinLock)
123 return (SNMP_ERR_NOSUCHNAME);
124
125 switch (op) {
126 case SNMP_OP_GET:
127 if (++usm_lock == INT32_MAX)
128 usm_lock = 0;
129 val->v.integer = usm_lock;
130 break;
131 case SNMP_OP_GETNEXT:
132 abort();
133 case SNMP_OP_SET:
134 if (val->v.integer != usm_lock)
135 return (SNMP_ERR_INCONS_VALUE);
136 break;
137 case SNMP_OP_ROLLBACK:
138 /* FALLTHROUGH */
139 case SNMP_OP_COMMIT:
140 break;
141 }
142
143 return (SNMP_ERR_NOERROR);
144 }
145
146 int
op_usm_users(struct snmp_context * ctx,struct snmp_value * val,uint32_t sub,uint32_t iidx __unused,enum snmp_op op)147 op_usm_users(struct snmp_context *ctx, struct snmp_value *val,
148 uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
149 {
150 uint32_t elen;
151 struct usm_user *uuser, *clone;
152 char uname[SNMP_ADM_STR32_SIZ];
153 uint8_t eid[SNMP_ENGINE_ID_SIZ];
154
155 switch (op) {
156 case SNMP_OP_GET:
157 if ((uuser = usm_get_user(&val->var, sub)) == NULL)
158 return (SNMP_ERR_NOSUCHNAME);
159 break;
160
161 case SNMP_OP_GETNEXT:
162 if ((uuser = usm_get_next_user(&val->var, sub)) == NULL)
163 return (SNMP_ERR_NOSUCHNAME);
164 usm_append_userindex(&val->var, sub, uuser);
165 break;
166
167 case SNMP_OP_SET:
168 if ((uuser = usm_get_user(&val->var, sub)) == NULL &&
169 val->var.subs[sub - 1] != LEAF_usmUserStatus &&
170 val->var.subs[sub - 1] != LEAF_usmUserCloneFrom)
171 return (SNMP_ERR_NOSUCHNAME);
172
173 /*
174 * XXX (ngie): need to investigate the MIB to determine how
175 * this is possible given some of the transitions below.
176 */
177 if (community != COMM_INITIALIZE &&
178 uuser != NULL && uuser->type == StorageType_readOnly)
179 return (SNMP_ERR_NOT_WRITEABLE);
180
181 switch (val->var.subs[sub - 1]) {
182 case LEAF_usmUserSecurityName:
183 return (SNMP_ERR_NOT_WRITEABLE);
184
185 case LEAF_usmUserCloneFrom:
186 if (uuser != NULL || usm_user_index_decode(&val->var,
187 sub, eid, &elen, uname) < 0 ||
188 !(asn_is_suboid(&oid_usmUserSecurityName, &val->v.oid)))
189 return (SNMP_ERR_WRONG_VALUE);
190 if ((clone = usm_get_user(&val->v.oid, sub)) == NULL)
191 return (SNMP_ERR_INCONS_VALUE);
192 if ((uuser = usm_new_user(eid, elen, uname)) == NULL)
193 return (SNMP_ERR_GENERR);
194 uuser->status = RowStatus_notReady;
195 if (community != COMM_INITIALIZE)
196 uuser->type = StorageType_volatile;
197 else
198 uuser->type = StorageType_readOnly;
199
200 uuser->suser.auth_proto = clone->suser.auth_proto;
201 uuser->suser.priv_proto = clone->suser.priv_proto;
202 memcpy(uuser->suser.auth_key, clone->suser.auth_key,
203 sizeof(uuser->suser.auth_key));
204 memcpy(uuser->suser.priv_key, clone->suser.priv_key,
205 sizeof(uuser->suser.priv_key));
206 ctx->scratch->int1 = RowStatus_createAndWait;
207 break;
208
209 case LEAF_usmUserAuthProtocol:
210 ctx->scratch->int1 = uuser->suser.auth_proto;
211 if (asn_compare_oid(&oid_usmNoAuthProtocol,
212 &val->v.oid) == 0)
213 uuser->suser.auth_proto = SNMP_AUTH_NOAUTH;
214 else if (asn_compare_oid(&oid_usmHMACMD5AuthProtocol,
215 &val->v.oid) == 0)
216 uuser->suser.auth_proto = SNMP_AUTH_HMAC_MD5;
217 else if (asn_compare_oid(&oid_usmHMACSHAAuthProtocol,
218 &val->v.oid) == 0)
219 uuser->suser.auth_proto = SNMP_AUTH_HMAC_SHA;
220 else
221 return (SNMP_ERR_WRONG_VALUE);
222 break;
223
224 case LEAF_usmUserAuthKeyChange:
225 case LEAF_usmUserOwnAuthKeyChange:
226 if (val->var.subs[sub - 1] ==
227 LEAF_usmUserOwnAuthKeyChange &&
228 (usm_user == NULL || strcmp(uuser->suser.sec_name,
229 usm_user->suser.sec_name) != 0))
230 return (SNMP_ERR_NO_ACCESS);
231 if (val->v.octetstring.len > SNMP_AUTH_KEY_SIZ)
232 return (SNMP_ERR_INCONS_VALUE);
233 ctx->scratch->ptr1 = malloc(SNMP_AUTH_KEY_SIZ);
234 if (ctx->scratch->ptr1 == NULL)
235 return (SNMP_ERR_GENERR);
236 memcpy(ctx->scratch->ptr1, uuser->suser.auth_key,
237 SNMP_AUTH_KEY_SIZ);
238 memcpy(uuser->suser.auth_key, val->v.octetstring.octets,
239 val->v.octetstring.len);
240 break;
241
242 case LEAF_usmUserPrivProtocol:
243 ctx->scratch->int1 = uuser->suser.priv_proto;
244 if (asn_compare_oid(&oid_usmNoPrivProtocol,
245 &val->v.oid) == 0)
246 uuser->suser.priv_proto = SNMP_PRIV_NOPRIV;
247 else if (asn_compare_oid(&oid_usmDESPrivProtocol,
248 &val->v.oid) == 0)
249 uuser->suser.priv_proto = SNMP_PRIV_DES;
250 else if (asn_compare_oid(&oid_usmAesCfb128Protocol,
251 &val->v.oid) == 0)
252 uuser->suser.priv_proto = SNMP_PRIV_AES;
253 else
254 return (SNMP_ERR_WRONG_VALUE);
255 break;
256
257 case LEAF_usmUserPrivKeyChange:
258 case LEAF_usmUserOwnPrivKeyChange:
259 if (val->var.subs[sub - 1] ==
260 LEAF_usmUserOwnPrivKeyChange &&
261 (usm_user == NULL || strcmp(uuser->suser.sec_name,
262 usm_user->suser.sec_name) != 0))
263 return (SNMP_ERR_NO_ACCESS);
264 if (val->v.octetstring.len > SNMP_PRIV_KEY_SIZ)
265 return (SNMP_ERR_INCONS_VALUE);
266 ctx->scratch->ptr1 = malloc(SNMP_PRIV_KEY_SIZ);
267 if (ctx->scratch->ptr1 == NULL)
268 return (SNMP_ERR_GENERR);
269 memcpy(ctx->scratch->ptr1, uuser->suser.priv_key,
270 sizeof(uuser->suser.priv_key));
271 memcpy(uuser->suser.priv_key, val->v.octetstring.octets,
272 val->v.octetstring.len);
273 break;
274
275 case LEAF_usmUserPublic:
276 if (val->v.octetstring.len > SNMP_ADM_STR32_SIZ)
277 return (SNMP_ERR_INCONS_VALUE);
278 if (uuser->user_public_len > 0) {
279 ctx->scratch->ptr2 =
280 malloc(uuser->user_public_len);
281 if (ctx->scratch->ptr2 == NULL)
282 return (SNMP_ERR_GENERR);
283 memcpy(ctx->scratch->ptr2, uuser->user_public,
284 uuser->user_public_len);
285 ctx->scratch->int2 = uuser->user_public_len;
286 }
287 if (val->v.octetstring.len > 0) {
288 memcpy(uuser->user_public,
289 val->v.octetstring.octets,
290 val->v.octetstring.len);
291 uuser->user_public_len = val->v.octetstring.len;
292 } else {
293 memset(uuser->user_public, 0,
294 sizeof(uuser->user_public));
295 uuser->user_public_len = 0;
296 }
297 break;
298
299 case LEAF_usmUserStorageType:
300 return (SNMP_ERR_INCONS_VALUE);
301
302 case LEAF_usmUserStatus:
303 if (uuser == NULL) {
304 if (val->v.integer != RowStatus_createAndWait ||
305 usm_user_index_decode(&val->var, sub, eid,
306 &elen, uname) < 0)
307 return (SNMP_ERR_INCONS_VALUE);
308 uuser = usm_new_user(eid, elen, uname);
309 if (uuser == NULL)
310 return (SNMP_ERR_GENERR);
311 uuser->status = RowStatus_notReady;
312 if (community != COMM_INITIALIZE)
313 uuser->type = StorageType_volatile;
314 else
315 uuser->type = StorageType_readOnly;
316 } else if (val->v.integer != RowStatus_active &&
317 val->v.integer != RowStatus_destroy)
318 return (SNMP_ERR_INCONS_VALUE);
319
320 uuser->status = val->v.integer;
321 break;
322 }
323 return (SNMP_ERR_NOERROR);
324
325 case SNMP_OP_COMMIT:
326 switch (val->var.subs[sub - 1]) {
327 case LEAF_usmUserAuthKeyChange:
328 case LEAF_usmUserOwnAuthKeyChange:
329 case LEAF_usmUserPrivKeyChange:
330 case LEAF_usmUserOwnPrivKeyChange:
331 free(ctx->scratch->ptr1);
332 break;
333 case LEAF_usmUserPublic:
334 if (ctx->scratch->ptr2 != NULL)
335 free(ctx->scratch->ptr2);
336 break;
337 case LEAF_usmUserStatus:
338 if (val->v.integer != RowStatus_destroy)
339 break;
340 if ((uuser = usm_get_user(&val->var, sub)) == NULL)
341 return (SNMP_ERR_GENERR);
342 usm_delete_user(uuser);
343 break;
344 default:
345 break;
346 }
347 return (SNMP_ERR_NOERROR);
348
349 case SNMP_OP_ROLLBACK:
350 if ((uuser = usm_get_user(&val->var, sub)) == NULL)
351 return (SNMP_ERR_GENERR);
352 switch (val->var.subs[sub - 1]) {
353 case LEAF_usmUserAuthProtocol:
354 uuser->suser.auth_proto = ctx->scratch->int1;
355 break;
356 case LEAF_usmUserAuthKeyChange:
357 case LEAF_usmUserOwnAuthKeyChange:
358 memcpy(uuser->suser.auth_key, ctx->scratch->ptr1,
359 sizeof(uuser->suser.auth_key));
360 free(ctx->scratch->ptr1);
361 break;
362 case LEAF_usmUserPrivProtocol:
363 uuser->suser.priv_proto = ctx->scratch->int1;
364 break;
365 case LEAF_usmUserPrivKeyChange:
366 case LEAF_usmUserOwnPrivKeyChange:
367 memcpy(uuser->suser.priv_key, ctx->scratch->ptr1,
368 sizeof(uuser->suser.priv_key));
369 free(ctx->scratch->ptr1);
370 break;
371 case LEAF_usmUserPublic:
372 if (ctx->scratch->ptr2 != NULL) {
373 memcpy(uuser->user_public, ctx->scratch->ptr2,
374 ctx->scratch->int2);
375 uuser->user_public_len = ctx->scratch->int2;
376 free(ctx->scratch->ptr2);
377 } else {
378 memset(uuser->user_public, 0,
379 sizeof(uuser->user_public));
380 uuser->user_public_len = 0;
381 }
382 break;
383 case LEAF_usmUserCloneFrom:
384 case LEAF_usmUserStatus:
385 if (ctx->scratch->int1 == RowStatus_createAndWait)
386 usm_delete_user(uuser);
387 break;
388 default:
389 break;
390 }
391 return (SNMP_ERR_NOERROR);
392
393 default:
394 abort();
395 }
396
397 switch (val->var.subs[sub - 1]) {
398 case LEAF_usmUserSecurityName:
399 return (string_get(val, uuser->suser.sec_name, -1));
400 case LEAF_usmUserCloneFrom:
401 memcpy(&val->v.oid, &oid_zeroDotZero, sizeof(oid_zeroDotZero));
402 break;
403 case LEAF_usmUserAuthProtocol:
404 switch (uuser->suser.auth_proto) {
405 case SNMP_AUTH_HMAC_MD5:
406 memcpy(&val->v.oid, &oid_usmHMACMD5AuthProtocol,
407 sizeof(oid_usmHMACMD5AuthProtocol));
408 break;
409 case SNMP_AUTH_HMAC_SHA:
410 memcpy(&val->v.oid, &oid_usmHMACSHAAuthProtocol,
411 sizeof(oid_usmHMACSHAAuthProtocol));
412 break;
413 default:
414 memcpy(&val->v.oid, &oid_usmNoAuthProtocol,
415 sizeof(oid_usmNoAuthProtocol));
416 break;
417 }
418 break;
419 case LEAF_usmUserAuthKeyChange:
420 case LEAF_usmUserOwnAuthKeyChange:
421 return (string_get(val, (char *)uuser->suser.auth_key, 0));
422 case LEAF_usmUserPrivProtocol:
423 switch (uuser->suser.priv_proto) {
424 case SNMP_PRIV_DES:
425 memcpy(&val->v.oid, &oid_usmDESPrivProtocol,
426 sizeof(oid_usmDESPrivProtocol));
427 break;
428 case SNMP_PRIV_AES:
429 memcpy(&val->v.oid, &oid_usmAesCfb128Protocol,
430 sizeof(oid_usmAesCfb128Protocol));
431 break;
432 default:
433 memcpy(&val->v.oid, &oid_usmNoPrivProtocol,
434 sizeof(oid_usmNoPrivProtocol));
435 break;
436 }
437 break;
438 case LEAF_usmUserPrivKeyChange:
439 case LEAF_usmUserOwnPrivKeyChange:
440 return (string_get(val, (char *)uuser->suser.priv_key, 0));
441 case LEAF_usmUserPublic:
442 return (string_get(val, uuser->user_public,
443 uuser->user_public_len));
444 case LEAF_usmUserStorageType:
445 val->v.integer = uuser->type;
446 break;
447 case LEAF_usmUserStatus:
448 val->v.integer = uuser->status;
449 break;
450 }
451
452 return (SNMP_ERR_NOERROR);
453 }
454
455 static int
usm_user_index_decode(const struct asn_oid * oid,uint sub,uint8_t * engine,uint32_t * elen,char * uname)456 usm_user_index_decode(const struct asn_oid *oid, uint sub, uint8_t *engine,
457 uint32_t *elen, char *uname)
458 {
459 uint32_t i, nlen;
460 int uname_off;
461
462 if (oid->subs[sub] > SNMP_ENGINE_ID_SIZ)
463 return (-1);
464
465 for (i = 0; i < oid->subs[sub]; i++)
466 engine[i] = oid->subs[sub + i + 1];
467 *elen = i;
468
469 uname_off = sub + oid->subs[sub] + 1;
470 if ((nlen = oid->subs[uname_off]) >= SNMP_ADM_STR32_SIZ)
471 return (-1);
472
473 for (i = 0; i < nlen; i++)
474 uname[i] = oid->subs[uname_off + i + 1];
475 uname[nlen] = '\0';
476
477 return (0);
478 }
479
480 static void
usm_append_userindex(struct asn_oid * oid,uint sub,const struct usm_user * uuser)481 usm_append_userindex(struct asn_oid *oid, uint sub,
482 const struct usm_user *uuser)
483 {
484 uint32_t i;
485
486 oid->len = sub + uuser->user_engine_len + strlen(uuser->suser.sec_name);
487 oid->len += 2;
488 oid->subs[sub] = uuser->user_engine_len;
489 for (i = 1; i < uuser->user_engine_len + 1; i++)
490 oid->subs[sub + i] = uuser->user_engine_id[i - 1];
491
492 sub += uuser->user_engine_len + 1;
493 oid->subs[sub] = strlen(uuser->suser.sec_name);
494 for (i = 1; i <= oid->subs[sub]; i++)
495 oid->subs[sub + i] = uuser->suser.sec_name[i - 1];
496 }
497
498 static struct usm_user *
usm_get_user(const struct asn_oid * oid,uint sub)499 usm_get_user(const struct asn_oid *oid, uint sub)
500 {
501 uint32_t enginelen;
502 char username[SNMP_ADM_STR32_SIZ];
503 uint8_t engineid[SNMP_ENGINE_ID_SIZ];
504
505 if (usm_user_index_decode(oid, sub, engineid, &enginelen, username) < 0)
506 return (NULL);
507
508 return (usm_find_user(engineid, enginelen, username));
509 }
510
511 static struct usm_user *
usm_get_next_user(const struct asn_oid * oid,uint sub)512 usm_get_next_user(const struct asn_oid *oid, uint sub)
513 {
514 uint32_t enginelen;
515 char username[SNMP_ADM_STR32_SIZ];
516 uint8_t engineid[SNMP_ENGINE_ID_SIZ];
517 struct usm_user *uuser;
518
519 if (oid->len - sub == 0)
520 return (usm_first_user());
521
522 if (usm_user_index_decode(oid, sub, engineid, &enginelen, username) < 0)
523 return (NULL);
524
525 if ((uuser = usm_find_user(engineid, enginelen, username)) != NULL)
526 return (usm_next_user(uuser));
527
528 return (NULL);
529 }
530
531 /*
532 * USM snmp module initialization hook.
533 * Returns 0 on success, < 0 on error.
534 */
535 static int
usm_init(struct lmodule * mod,int argc __unused,char * argv[]__unused)536 usm_init(struct lmodule * mod, int argc __unused, char *argv[] __unused)
537 {
538 usm_module = mod;
539 usm_lock = random();
540 bsnmpd_reset_usm_stats();
541 return (0);
542 }
543
544 /*
545 * USM snmp module finalization hook.
546 */
547 static int
usm_fini(void)548 usm_fini(void)
549 {
550 usm_flush_users();
551 or_unregister(reg_usm);
552
553 return (0);
554 }
555
556 /*
557 * USM snmp module start operation.
558 */
559 static void
usm_start(void)560 usm_start(void)
561 {
562 reg_usm = or_register(&oid_usm,
563 "The MIB module for managing SNMP User-Based Security Model.",
564 usm_module);
565 }
566
567 static void
usm_dump(void)568 usm_dump(void)
569 {
570 struct usm_user *uuser;
571 struct snmpd_usmstat *usmstats;
572 const char *const authstr[] = {
573 "noauth",
574 "md5",
575 "sha",
576 NULL
577 };
578 const char *const privstr[] = {
579 "nopriv",
580 "des",
581 "aes",
582 NULL
583 };
584
585 if ((usmstats = bsnmpd_get_usm_stats()) != NULL) {
586 syslog(LOG_ERR, "UnsupportedSecLevels\t\t%u",
587 usmstats->unsupported_seclevels);
588 syslog(LOG_ERR, "NotInTimeWindows\t\t%u",
589 usmstats->not_in_time_windows);
590 syslog(LOG_ERR, "UnknownUserNames\t\t%u",
591 usmstats->unknown_users);
592 syslog(LOG_ERR, "UnknownEngineIDs\t\t%u",
593 usmstats->unknown_engine_ids);
594 syslog(LOG_ERR, "WrongDigests\t\t%u",
595 usmstats->wrong_digests);
596 syslog(LOG_ERR, "DecryptionErrors\t\t%u",
597 usmstats->decrypt_errors);
598 }
599
600 syslog(LOG_ERR, "USM users");
601 for (uuser = usm_first_user(); uuser != NULL;
602 (uuser = usm_next_user(uuser)))
603 syslog(LOG_ERR, "user %s\t\t%s, %s", uuser->suser.sec_name,
604 authstr[uuser->suser.auth_proto],
605 privstr[uuser->suser.priv_proto]);
606 }
607
608 static const char usm_comment[] =
609 "This module implements SNMP User-based Security Model defined in RFC 3414.";
610
611 extern const struct snmp_module config;
612 const struct snmp_module config = {
613 .comment = usm_comment,
614 .init = usm_init,
615 .fini = usm_fini,
616 .start = usm_start,
617 .tree = usm_ctree,
618 .dump = usm_dump,
619 .tree_size = usm_CTREE_SIZE,
620 };
621