Coverage Report

Created: 2025-07-23 06:49

/src/net-snmp/snmplib/snmpusm.c
Line
Count
Source (jump to first uncovered line)
1
/* Portions of this file are subject to the following copyright(s).  See
2
 * the Net-SNMP's COPYING file for more details and other copyrights
3
 * that may apply:
4
 */
5
/*
6
 * Portions of this file are copyrighted by:
7
 * Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
8
 * Use is subject to license terms specified in the COPYING file
9
 * distributed with the Net-SNMP package.
10
 *
11
 * Portions of this file are copyrighted by:
12
 * Copyright (c) 2016 VMware, Inc. All rights reserved.
13
 * Use is subject to license terms specified in the COPYING file
14
 * distributed with the Net-SNMP package.
15
 */
16
/*
17
 * snmpusm.c
18
 *
19
 * Routines to manipulate a information about a "user" as
20
 * defined by the SNMP-USER-BASED-SM-MIB MIB.
21
 *
22
 * All functions usm_set_usmStateReference_*() return 0 on success, -1
23
 * otherwise.
24
 *
25
 * !! Tab stops set to 4 in some parts of this file. !!
26
 *    (Designated on a per function.)
27
 */
28
29
#include <net-snmp/net-snmp-config.h>
30
#include <net-snmp/net-snmp-features.h>
31
32
#include <sys/types.h>
33
#include <stdio.h>
34
#ifdef HAVE_STDLIB_H
35
#include <stdlib.h>
36
#endif
37
#ifdef HAVE_STDINT_H
38
#include <stdint.h>
39
#endif
40
#ifdef TIME_WITH_SYS_TIME
41
# include <sys/time.h>
42
# include <time.h>
43
#else
44
# ifdef HAVE_SYS_TIME_H
45
#  include <sys/time.h>
46
# else
47
#  include <time.h>
48
# endif
49
#endif
50
#ifdef HAVE_STRING_H
51
#include <string.h>
52
#else
53
#include <strings.h>
54
#endif
55
#ifdef HAVE_NETINET_IN_H
56
#include <netinet/in.h>
57
#endif
58
59
#ifdef HAVE_UNISTD_H
60
#include <unistd.h>
61
#endif
62
63
#include <net-snmp/types.h>
64
#include <net-snmp/output_api.h>
65
#include <net-snmp/config_api.h>
66
#include <net-snmp/utilities.h>
67
68
#include <net-snmp/library/openssl_config.h>
69
#include <net-snmp/library/asn1.h>
70
#include <net-snmp/library/snmp_api.h>
71
#include <net-snmp/library/callback.h>
72
#include <net-snmp/library/tools.h>
73
#include <net-snmp/library/keytools.h>
74
#include <net-snmp/library/snmpv3.h>
75
#include <net-snmp/library/lcd_time.h>
76
#include <net-snmp/library/scapi.h>
77
#include <net-snmp/library/callback.h>
78
#include <net-snmp/library/snmp_secmod.h>
79
#include <net-snmp/library/snmpusm.h>
80
#include <net-snmp/library/transform_oids.h>
81
#include <net-snmp/library/snmp_enum.h>
82
83
#ifdef HAVE_OPENSSL_DH_H
84
#include <openssl/dh.h>
85
#endif
86
87
netsnmp_feature_child_of(usm_all, libnetsnmp);
88
netsnmp_feature_child_of(usm_support, usm_all);
89
90
netsnmp_feature_require(usm_support);
91
92
struct usmStateReference {
93
    int             refcnt;
94
    char           *usr_name;
95
    size_t          usr_name_length;
96
    u_char         *usr_engine_id;
97
    size_t          usr_engine_id_length;
98
    oid            *usr_auth_protocol;
99
    size_t          usr_auth_protocol_length;
100
    u_char         *usr_auth_key;
101
    size_t          usr_auth_key_length;
102
    oid            *usr_priv_protocol;
103
    size_t          usr_priv_protocol_length;
104
    u_char         *usr_priv_key;
105
    size_t          usr_priv_key_length;
106
    u_int           usr_sec_level;
107
};
108
109
const oid usmNoAuthProtocol[10] = { NETSNMP_USMAUTH_BASE_OID,
110
                                 NETSNMP_USMAUTH_NOAUTH };
111
#ifndef NETSNMP_DISABLE_MD5
112
const oid usmHMACMD5AuthProtocol[10] = { NETSNMP_USMAUTH_BASE_OID,
113
                                      NETSNMP_USMAUTH_HMACMD5 };
114
#endif
115
const oid usmHMACSHA1AuthProtocol[10] = { NETSNMP_USMAUTH_BASE_OID,
116
                                       NETSNMP_USMAUTH_HMACSHA1 };
117
118
#ifdef HAVE_EVP_SHA384
119
const oid usmHMAC384SHA512AuthProtocol[10] = { NETSNMP_USMAUTH_BASE_OID,
120
                                            NETSNMP_USMAUTH_HMAC384SHA512 };
121
const oid usmHMAC256SHA384AuthProtocol[10] = { NETSNMP_USMAUTH_BASE_OID,
122
                                            NETSNMP_USMAUTH_HMAC256SHA384 };
123
#endif /* HAVE_EVP_SHA384 */
124
125
#ifdef HAVE_EVP_SHA224
126
const oid usmHMAC192SHA256AuthProtocol[10] = { NETSNMP_USMAUTH_BASE_OID,
127
                                            NETSNMP_USMAUTH_HMAC192SHA256 };
128
const oid usmHMAC128SHA224AuthProtocol[10] = { NETSNMP_USMAUTH_BASE_OID,
129
                                            NETSNMP_USMAUTH_HMAC128SHA224 };
130
#endif /* HAVE_EVP_SHA384 */
131
132
const oid usmNoPrivProtocol[10] = { 1, 3, 6, 1, 6, 3, 10, 1, 2, 1 };
133
134
#ifndef NETSNMP_DISABLE_DES
135
const oid usmDESPrivProtocol[10] = { 1, 3, 6, 1, 6, 3, 10, 1, 2, 2 };
136
#endif
137
138
139
const oid usmAESPrivProtocol[10] = { 1, 3, 6, 1, 6, 3, 10, 1, 2, 4 };
140
/* backwards compat */
141
const oid *usmAES128PrivProtocol = usmAESPrivProtocol;
142
143
#ifdef NETSNMP_DRAFT_BLUMENTHAL_AES_04
144
    /* OIDs from http://www.snmp.com/eso/esoConsortiumMIB.txt */
145
const oid usmAES192PrivProtocol[9] = { 1,3,6,1,4,1,14832,1,3 };
146
const oid usmAES256PrivProtocol[9] = { 1,3,6,1,4,1,14832,1,4 };
147
    /* OIDs from CISCO MIB */
148
const oid usmAES192CiscoPrivProtocol[11]  = { 1,3,6,1,4,1,9,12,6,1,1 };
149
const oid usmAES256CiscoPrivProtocol[11]  = { 1,3,6,1,4,1,9,12,6,1,2 };
150
/*
151
 * these OIDs are in pySNMP source as OIDs for AES+Reeder. We'll just
152
 * use OIDS from CISCO-SNMP-USM-OIDS-MIB
153
 *
154
const oid usmAES192Cisco2PrivProtocol[11]  = { 1,3,6,1,4,1,9,12,6,1,101 };
155
const oid usmAES256Cisco2PrivProtocol[11]  = { 1,3,6,1,4,1,9,12,6,1,102 };
156
 */
157
#endif /* NETSNMP_DRAFT_BLUMENTHAL_AES_04 */
158
159
typedef struct usm_alg_type_s {
160
    const char *label;
161
    int         value;
162
} usm_alg_type_t;
163
164
static const usm_alg_type_t usm_auth_type[] = {
165
    { "NOAUTH", NETSNMP_USMAUTH_NOAUTH },
166
    { "SHA", NETSNMP_USMAUTH_HMACSHA1 },
167
    { "SHA-1", NETSNMP_USMAUTH_HMACSHA1 },
168
    { "SHA1", NETSNMP_USMAUTH_HMACSHA1 },
169
#ifndef NETSNMP_DISABLE_MD5
170
    { "MD5", NETSNMP_USMAUTH_HMACMD5 },
171
#endif
172
#ifdef HAVE_EVP_SHA224
173
    { "SHA-224", NETSNMP_USMAUTH_HMAC128SHA224 },
174
    { "SHA224", NETSNMP_USMAUTH_HMAC128SHA224 },
175
    { "SHA-256", NETSNMP_USMAUTH_HMAC192SHA256 },
176
    { "SHA256", NETSNMP_USMAUTH_HMAC192SHA256 },
177
#endif
178
#ifdef HAVE_EVP_SHA384
179
    { "SHA-384", NETSNMP_USMAUTH_HMAC256SHA384 },
180
    { "SHA384", NETSNMP_USMAUTH_HMAC256SHA384 },
181
    { "SHA-512",  NETSNMP_USMAUTH_HMAC384SHA512 },
182
    { "SHA512",  NETSNMP_USMAUTH_HMAC384SHA512 },
183
#endif
184
    { NULL, -1 }
185
};
186
187
static const usm_alg_type_t usm_priv_type[] = {
188
    { "NOPRIV", USM_CREATE_USER_PRIV_NONE },
189
#ifndef NETSNMP_DISABLE_DES
190
    { "DES", USM_CREATE_USER_PRIV_DES },
191
#endif
192
#ifdef HAVE_AES
193
    { "AES", USM_CREATE_USER_PRIV_AES },
194
    { "AES-128", USM_CREATE_USER_PRIV_AES },
195
    { "AES128", USM_CREATE_USER_PRIV_AES },
196
#ifdef NETSNMP_DRAFT_BLUMENTHAL_AES_04
197
    { "AES-192", USM_CREATE_USER_PRIV_AES192 },
198
    { "AES192", USM_CREATE_USER_PRIV_AES192 },
199
    { "AES-256", USM_CREATE_USER_PRIV_AES256 },
200
    { "AES256", USM_CREATE_USER_PRIV_AES256 },
201
    /** cisco / pysnmp variations */
202
    { "AES-192-C", USM_CREATE_USER_PRIV_AES192_CISCO },
203
    { "AES192C", USM_CREATE_USER_PRIV_AES192_CISCO },
204
    { "AES-256-C", USM_CREATE_USER_PRIV_AES256_CISCO },
205
    { "AES256C", USM_CREATE_USER_PRIV_AES256_CISCO },
206
#endif
207
#endif
208
    { NULL, -1 },
209
};
210
211
static u_int    dummy_etime, dummy_eboot;       /* For ISENGINEKNOWN(). */
212
213
/*
214
 * Set up default snmpv3 parameter value storage.
215
 */
216
#ifdef NETSNMP_SECMOD_USM
217
static const oid *defaultAuthType = NULL;
218
static size_t   defaultAuthTypeLen = 0;
219
static const oid *defaultPrivType = NULL;
220
static size_t   defaultPrivTypeLen = 0;
221
#endif /* NETSNMP_SECMOD_USM */
222
223
/*
224
 * Globals.
225
 */
226
static u_int    salt_integer;
227
#ifdef HAVE_AES
228
static u_int    salt_integer64_1, salt_integer64_2;
229
#endif
230
        /*
231
         * 1/2 of seed for the salt.   Cf. RFC2274, Sect 8.1.1.1.
232
         */
233
234
static struct usmUser *noNameUser = NULL;
235
/*
236
 * Local storage (LCD) of the default user list.
237
 */
238
static struct usmUser *userList = NULL;
239
240
/*
241
 * Set a given field of the secStateRef.
242
 *
243
 * Allocate <len> bytes for type <type> pointed to by ref-><field>.
244
 * Then copy in <item> and record its length in ref-><field_len>.
245
 *
246
 * Return 0 on success, -1 otherwise.
247
 */
248
0
#define MAKE_ENTRY(ref, type, item, len, field, field_len)      \
249
0
do {                                                            \
250
0
  if (ref == NULL)                                        \
251
0
    return -1;                                      \
252
0
  if (ref->field != NULL) {                               \
253
0
    SNMP_ZERO(ref->field, ref->field_len);          \
254
0
    SNMP_FREE(ref->field);                          \
255
0
  }                                                       \
256
0
  ref->field_len = 0;                                     \
257
0
        if (len == 0 || item == NULL)                           \
258
0
    return 0;                                       \
259
0
  ref->field = netsnmp_memdup(item, len * sizeof(type));  \
260
0
        if (ref->field == NULL)                                 \
261
0
    return -1;                                      \
262
0
                                                                \
263
0
  ref->field_len = len;                                   \
264
0
  return 0;                                               \
265
0
} while (0)
266
267
static int
268
usm_clone_usmStateReference(struct usmStateReference *from,
269
                            struct usmStateReference **to);
270
271
static int
272
free_enginetime_on_shutdown(int majorid, int minorid, void *serverarg,
273
          void *clientarg)
274
3.39k
{
275
3.39k
    u_char engineID[SNMP_MAX_ENG_SIZE];
276
3.39k
    size_t engineID_len = sizeof(engineID);
277
278
3.39k
    DEBUGMSGTL(("snmpv3", "free enginetime callback called\n"));
279
280
3.39k
    engineID_len = snmpv3_get_engineID(engineID, engineID_len);
281
3.39k
    if (engineID_len > 0)
282
0
  free_enginetime(engineID, engineID_len);
283
3.39k
    return 0;
284
3.39k
}
285
286
static struct usmStateReference *
287
usm_malloc_usmStateReference(void)
288
0
{
289
0
    struct usmStateReference *retval;
290
291
0
    retval = calloc(1, sizeof(struct usmStateReference));
292
0
    if (retval)
293
0
        retval->refcnt = 1;
294
295
0
    return retval;
296
0
}                               /* end usm_malloc_usmStateReference() */
297
298
static int
299
usm_clone(netsnmp_pdu *pdu, netsnmp_pdu *new_pdu)
300
0
{
301
0
    struct usmStateReference *ref = pdu->securityStateRef;
302
0
    struct usmStateReference **new_ref =
303
0
        (struct usmStateReference **)&new_pdu->securityStateRef;
304
0
    int ret = 0;
305
306
0
    if (!ref)
307
0
        return ret;
308
309
0
    if (pdu->command == SNMP_MSG_TRAP2) {
310
0
        ret = usm_clone_usmStateReference(ref, new_ref);
311
0
    } else {
312
0
        netsnmp_assert(ref == *new_ref);
313
0
        ref->refcnt++;
314
0
    }
315
316
0
    return ret;
317
0
}
318
319
static void
320
usm_free_usmStateReference(void *old)
321
0
{
322
0
    struct usmStateReference *ref = old;
323
324
0
    if (!ref)
325
0
        return;
326
327
0
    if (--ref->refcnt > 0)
328
0
        return;
329
330
0
    SNMP_FREE(ref->usr_name);
331
0
    SNMP_FREE(ref->usr_engine_id);
332
0
    SNMP_FREE(ref->usr_auth_protocol);
333
0
    SNMP_FREE(ref->usr_priv_protocol);
334
335
0
    if (ref->usr_auth_key_length && ref->usr_auth_key) {
336
0
        SNMP_ZERO(ref->usr_auth_key, ref->usr_auth_key_length);
337
0
        SNMP_FREE(ref->usr_auth_key);
338
0
    }
339
0
    if (ref->usr_priv_key_length && ref->usr_priv_key) {
340
0
        SNMP_ZERO(ref->usr_priv_key, ref->usr_priv_key_length);
341
0
        SNMP_FREE(ref->usr_priv_key);
342
0
    }
343
344
0
    SNMP_FREE(ref);
345
0
}                               /* end usm_free_usmStateReference() */
346
347
struct usmUser *
348
usm_get_userList(void)
349
0
{
350
0
    return userList;
351
0
}
352
353
static int
354
usm_set_usmStateReference_name(struct usmStateReference *ref,
355
                               char *name, size_t name_len)
356
0
{
357
0
    MAKE_ENTRY(ref, char, name, name_len, usr_name, usr_name_length);
358
0
}
359
360
static int
361
usm_set_usmStateReference_engine_id(struct usmStateReference *ref,
362
                                    u_char * engine_id,
363
                                    size_t engine_id_len)
364
0
{
365
0
    MAKE_ENTRY(ref, u_char, engine_id, engine_id_len,
366
0
               usr_engine_id, usr_engine_id_length);
367
0
}
368
369
static int
370
usm_set_usmStateReference_auth_protocol(struct usmStateReference *ref,
371
                                        oid * auth_protocol,
372
                                        size_t auth_protocol_len)
373
0
{
374
0
    MAKE_ENTRY(ref, oid, auth_protocol, auth_protocol_len,
375
0
               usr_auth_protocol, usr_auth_protocol_length);
376
0
}
377
378
static int
379
usm_set_usmStateReference_auth_key(struct usmStateReference *ref,
380
                                   u_char * auth_key, size_t auth_key_len)
381
0
{
382
0
    MAKE_ENTRY(ref, u_char, auth_key, auth_key_len,
383
0
               usr_auth_key, usr_auth_key_length);
384
0
}
385
386
static int
387
usm_set_usmStateReference_priv_protocol(struct usmStateReference *ref,
388
                                        oid * priv_protocol,
389
                                        size_t priv_protocol_len)
390
0
{
391
0
    MAKE_ENTRY(ref, oid, priv_protocol, priv_protocol_len,
392
0
               usr_priv_protocol, usr_priv_protocol_length);
393
0
}
394
395
static int
396
usm_set_usmStateReference_priv_key(struct usmStateReference *ref,
397
                                   u_char * priv_key, size_t priv_key_len)
398
0
{
399
0
    MAKE_ENTRY(ref, u_char, priv_key, priv_key_len,
400
0
               usr_priv_key, usr_priv_key_length);
401
0
}
402
403
static int
404
usm_set_usmStateReference_sec_level(struct usmStateReference *ref,
405
                                    int sec_level)
406
0
{
407
0
    if (ref == NULL)
408
0
        return -1;
409
0
    ref->usr_sec_level = sec_level;
410
0
    return 0;
411
0
}
412
413
static int
414
usm_clone_usmStateReference(struct usmStateReference *from,
415
                            struct usmStateReference **to)
416
0
{
417
0
    struct usmStateReference *cloned_usmStateRef;
418
419
0
    if (from == NULL || to == NULL)
420
0
        return -1;
421
422
0
    *to = usm_malloc_usmStateReference();
423
0
    cloned_usmStateRef = *to;
424
425
0
    if (usm_set_usmStateReference_name(cloned_usmStateRef, from->usr_name, from->usr_name_length) ||
426
0
        usm_set_usmStateReference_engine_id(cloned_usmStateRef, from->usr_engine_id, from->usr_engine_id_length) ||
427
0
        usm_set_usmStateReference_auth_protocol(cloned_usmStateRef, from->usr_auth_protocol, from->usr_auth_protocol_length) ||
428
0
        usm_set_usmStateReference_auth_key(cloned_usmStateRef, from->usr_auth_key, from->usr_auth_key_length) ||
429
0
        usm_set_usmStateReference_priv_protocol(cloned_usmStateRef, from->usr_priv_protocol, from->usr_priv_protocol_length) ||
430
0
        usm_set_usmStateReference_priv_key(cloned_usmStateRef, from->usr_priv_key, from->usr_priv_key_length) ||
431
0
        usm_set_usmStateReference_sec_level(cloned_usmStateRef, from->usr_sec_level))
432
0
    {
433
0
        usm_free_usmStateReference(*to);
434
0
        *to = NULL;
435
0
        return -1;
436
0
    }
437
438
0
    return 0;
439
440
0
}
441
442
#ifdef NETSNMP_ENABLE_TESTING_CODE
443
/*******************************************************************-o-******
444
 * emergency_print
445
 *
446
 * Parameters:
447
 *  *field
448
 *   length
449
 *      
450
 *  This is a print routine that is solely included so that it can be
451
 *  used in gdb.  Don't use it as a function, it will be pulled before
452
 *  a real release of the code.
453
 *
454
 *  tab stop 4
455
 *
456
 *  XXX fflush() only works on FreeBSD; core dumps on Sun OS's
457
 */
458
void
459
emergency_print(u_char * field, u_int length)
460
{
461
    int             iindex;
462
    int             start = 0;
463
    int             stop = 25;
464
465
    while (start < stop) {
466
        for (iindex = start; iindex < stop; iindex++)
467
            printf("%02X ", field[iindex]);
468
469
        printf("\n");
470
        start = stop;
471
        stop = stop + 25 < length ? stop + 25 : length;
472
    }
473
    fflush(0);
474
475
}                               /* end emergency_print() */
476
#endif                          /* NETSNMP_ENABLE_TESTING_CODE */
477
478
static struct usmUser *
479
usm_get_user_from_list(const u_char *engineID, size_t engineIDLen,
480
                       const char *name, size_t nameLen,
481
                       struct usmUser *puserList, int use_default)
482
631
{
483
631
    struct usmUser *ptr;
484
485
631
    for (ptr = puserList; ptr != NULL; ptr = ptr->next) {
486
0
        if (ptr->name && strlen(ptr->name) == nameLen &&
487
0
            memcmp(ptr->name, name, nameLen) == 0) {
488
0
          DEBUGMSGTL(("usm", "match on user %s\n", ptr->name));
489
0
          if (ptr->engineIDLen == engineIDLen &&
490
0
            ((ptr->engineID == NULL && engineID == NULL) ||
491
0
             (ptr->engineID != NULL && engineID != NULL &&
492
0
              memcmp(ptr->engineID, engineID, engineIDLen) == 0)))
493
0
            return ptr;
494
0
          DEBUGMSGTL(("usm", "no match on engineID ("));
495
0
          if (engineID) {
496
0
              DEBUGMSGHEX(("usm", engineID, engineIDLen));
497
0
          } else {
498
0
              DEBUGMSGTL(("usm", "Empty EngineID"));
499
0
          }
500
0
          DEBUGMSG(("usm", ")\n"));
501
0
        }
502
0
    }
503
504
    /*
505
     * return "" user used to facilitate engineID discovery
506
     */
507
631
    if (use_default && !strcmp(name, "")) {
508
571
        DEBUGMSGTL(("usm", "return noNameUser\n"));
509
571
        return noNameUser;
510
571
    }
511
60
    return NULL;
512
631
}
513
514
struct usmUser *
515
usm_get_user2(const u_char *engineID, size_t engineIDLen, const void *name,
516
              size_t nameLen)
517
631
{
518
631
    DEBUGMSGTL(("usm", "getting user %.*s\n", (int)nameLen,
519
631
                (const char *)name));
520
631
    return usm_get_user_from_list(engineID, engineIDLen, name, nameLen,
521
631
                                  userList, 1);
522
631
}
523
524
/*
525
 * usm_get_user(): Returns a user from userList based on the engineID,
526
 * engineIDLen and name of the requested user.
527
 */
528
struct usmUser *
529
usm_get_user(const u_char *engineID, size_t engineIDLen, const char *name)
530
631
{
531
631
    return usm_get_user2(engineID, engineIDLen, name, strlen(name));
532
631
}
533
534
static struct usmUser *
535
usm_add_user_to_list(struct usmUser *user, struct usmUser *puserList)
536
0
{
537
0
    struct usmUser *nptr, *pptr, *optr;
538
539
    /*
540
     * loop through puserList till we find the proper, sorted place to
541
     * insert the new user
542
     */
543
    /* XXX - how to handle a NULL user->name ?? */
544
    /* XXX - similarly for a NULL nptr->name ?? */
545
0
    for (nptr = puserList, pptr = NULL; nptr != NULL;
546
0
         pptr = nptr, nptr = nptr->next) {
547
0
        if (nptr->engineIDLen > user->engineIDLen)
548
0
            break;
549
550
0
        if (user->engineID == NULL && nptr->engineID != NULL)
551
0
            break;
552
553
0
        if (nptr->engineIDLen == user->engineIDLen &&
554
0
            (nptr->engineID != NULL && user->engineID != NULL &&
555
0
             memcmp(nptr->engineID, user->engineID,
556
0
                    user->engineIDLen) > 0))
557
0
            break;
558
559
0
        if (!(nptr->engineID == NULL && user->engineID != NULL)) {
560
0
            if (nptr->engineIDLen == user->engineIDLen &&
561
0
                ((nptr->engineID == NULL && user->engineID == NULL) ||
562
0
                 memcmp(nptr->engineID, user->engineID,
563
0
                        user->engineIDLen) == 0)
564
0
                && strlen(nptr->name) > strlen(user->name))
565
0
                break;
566
567
0
            if (nptr->engineIDLen == user->engineIDLen &&
568
0
                ((nptr->engineID == NULL && user->engineID == NULL) ||
569
0
                 memcmp(nptr->engineID, user->engineID,
570
0
                        user->engineIDLen) == 0)
571
0
                && strlen(nptr->name) == strlen(user->name)
572
0
                && strcmp(nptr->name, user->name) > 0)
573
0
                break;
574
575
0
            if (nptr->engineIDLen == user->engineIDLen &&
576
0
                ((nptr->engineID == NULL && user->engineID == NULL) ||
577
0
                 memcmp(nptr->engineID, user->engineID,
578
0
                        user->engineIDLen) == 0)
579
0
                && strlen(nptr->name) == strlen(user->name)
580
0
                && strcmp(nptr->name, user->name) == 0) {
581
                /*
582
                 * the user is an exact match of a previous entry.
583
                 * Credentials may be different, though, so remove
584
                 * the old entry (and add the new one)!
585
                 */
586
0
                if (pptr) { /* change prev's next pointer */
587
0
                  pptr->next = nptr->next;
588
0
                }
589
0
                if (nptr->next) { /* change next's prev pointer */
590
0
                  nptr->next->prev = pptr;
591
0
                }
592
0
                optr = nptr;
593
0
                nptr = optr->next; /* add new user at this position */
594
                /* free the old user */
595
0
                optr->next=NULL;
596
0
                optr->prev=NULL;
597
0
                usm_free_user(optr);
598
0
                break; /* new user will be added below */
599
0
            }
600
0
        }
601
0
    }
602
603
    /*
604
     * nptr should now point to the user that we need to add ourselves
605
     * in front of, and pptr should be our new 'prev'.
606
     */
607
608
    /*
609
     * change our pointers
610
     */
611
0
    user->prev = pptr;
612
0
    user->next = nptr;
613
614
    /*
615
     * change the next's prev pointer
616
     */
617
0
    if (user->next)
618
0
        user->next->prev = user;
619
620
    /*
621
     * change the prev's next pointer
622
     */
623
0
    if (user->prev)
624
0
        user->prev->next = user;
625
626
    /*
627
     * rewind to the head of the list and return it (since the new head
628
     * could be us, we need to notify the above routine who the head now is.
629
     */
630
0
    for (pptr = user; pptr->prev != NULL; pptr = pptr->prev);
631
0
    return pptr;
632
0
}
633
634
/*
635
 * usm_add_user(): Add's a user to the userList, sorted by the
636
 * engineIDLength then the engineID then the name length then the name
637
 * to facilitate getNext calls on a usmUser table which is indexed by
638
 * these values.
639
 *
640
 * returns the head of the list (which could change due to this add).
641
 */
642
643
struct usmUser *
644
usm_add_user(struct usmUser *user)
645
0
{
646
0
    struct usmUser *uptr;
647
0
    uptr = usm_add_user_to_list(user, userList);
648
0
    if (uptr != NULL)
649
0
        userList = uptr;
650
0
    return uptr;
651
0
}
652
653
/*
654
 * usm_remove_usmUser_from_list remove user from (optional) list
655
 *
656
 * if list is not specified, defaults to global userList.
657
 *
658
 * returns SNMPERR_SUCCESS or SNMPERR_USM_UNKNOWNSECURITYNAME
659
 */
660
static int
661
usm_remove_usmUser_from_list(struct usmUser *user, struct usmUser **ppuserList)
662
0
{
663
0
    struct usmUser *nptr, *pptr;
664
665
    /*
666
     * NULL pointers aren't allowed
667
     */
668
0
    if (ppuserList == NULL)
669
0
        ppuserList = &userList;
670
671
0
    if (*ppuserList == NULL)
672
0
        return SNMPERR_USM_UNKNOWNSECURITYNAME;
673
674
    /*
675
     * find the user in the list
676
     */
677
0
    for (nptr = *ppuserList, pptr = NULL; nptr != NULL;
678
0
         pptr = nptr, nptr = nptr->next) {
679
0
        if (nptr == user)
680
0
            break;
681
0
    }
682
683
0
    if (nptr) {
684
        /*
685
         * remove the user from the linked list
686
         */
687
0
        if (pptr) {
688
0
            pptr->next = nptr->next;
689
0
        }
690
0
        if (nptr->next) {
691
0
            nptr->next->prev = pptr;
692
0
        }
693
0
    } else {
694
        /*
695
         * user didn't exist
696
         */
697
0
        return SNMPERR_USM_UNKNOWNSECURITYNAME;
698
0
    }
699
0
    if (nptr == *ppuserList)    /* we're the head of the list, need to change
700
                                 * * the head to the next user */
701
0
        *ppuserList = nptr->next;
702
0
    return SNMPERR_SUCCESS;
703
0
}                               /* end usm_remove_usmUser_from_list() */
704
705
/*
706
 * usm_remove_user_from_list
707
 *
708
 * removes user from list.
709
 *
710
 * returns new list head on success, or NULL on error.
711
 *
712
 * NOTE: if there was only one user in the list, list head will be NULL.
713
 *       So NULL can also mean success. Use the newer usm_remove_usmUser() for
714
 *       more specific return codes. This function is kept for backwards
715
 *       compatibility with this ambiguous behaviour.
716
 */
717
static struct usmUser *
718
usm_remove_user_from_list(struct usmUser *user,
719
                          struct usmUser **ppuserList)
720
0
{
721
0
    int rc = usm_remove_usmUser_from_list(user, ppuserList);
722
0
    if (rc != SNMPERR_SUCCESS || NULL == ppuserList)
723
0
        return NULL;
724
725
0
    return *ppuserList;
726
0
}                               /* end usm_remove_user_from_list() */
727
728
/*
729
 * usm_remove_user(): finds and removes a user from a list
730
 */
731
struct usmUser *
732
usm_remove_user(struct usmUser *user)
733
0
{
734
0
    return usm_remove_user_from_list(user, &userList);
735
0
}
736
737
/*
738
 * usm_free_user():  calls free() on all needed parts of struct usmUser and
739
 * the user himself.
740
 *
741
 * Note: This should *not* be called on an object in a list (IE,
742
 * remove it from the list first, and set next and prev to NULL), but
743
 * will try to reconnect the list pieces again if it is called this
744
 * way.  If called on the head of the list, the entire list will be
745
 * lost.
746
 */
747
struct usmUser *
748
usm_free_user(struct usmUser *user)
749
21.7k
{
750
21.7k
    if (user == NULL)
751
18.3k
        return NULL;
752
753
3.39k
    SNMP_FREE(user->engineID);
754
3.39k
    SNMP_FREE(user->name);
755
3.39k
    SNMP_FREE(user->secName);
756
3.39k
    SNMP_FREE(user->cloneFrom);
757
3.39k
    SNMP_FREE(user->userPublicString);
758
3.39k
    SNMP_FREE(user->authProtocol);
759
3.39k
    SNMP_FREE(user->privProtocol);
760
761
3.39k
    if (user->authKey != NULL) {
762
0
        SNMP_ZERO(user->authKey, user->authKeyLen);
763
0
        SNMP_FREE(user->authKey);
764
0
    }
765
766
3.39k
    if (user->privKey != NULL) {
767
0
        SNMP_ZERO(user->privKey, user->privKeyLen);
768
0
        SNMP_FREE(user->privKey);
769
0
    }
770
771
3.39k
    if (user->authKeyKu != NULL) {
772
0
        SNMP_ZERO(user->authKeyKu, user->authKeyKuLen);
773
0
        SNMP_FREE(user->authKeyKu);
774
0
    }
775
776
3.39k
    if (user->privKeyKu != NULL) {
777
0
        SNMP_ZERO(user->privKeyKu, user->privKeyKuLen);
778
0
        SNMP_FREE(user->privKeyKu);
779
0
    }
780
781
3.39k
#ifdef NETSNMP_USE_OPENSSL
782
3.39k
    if (user->usmDHUserAuthKeyChange)
783
0
    {
784
0
        DH_free(user->usmDHUserAuthKeyChange);
785
0
        user->usmDHUserAuthKeyChange = NULL;
786
0
    }
787
788
3.39k
    if (user->usmDHUserPrivKeyChange)
789
0
    {
790
0
        DH_free(user->usmDHUserPrivKeyChange);
791
0
        user->usmDHUserPrivKeyChange = NULL;
792
0
    }
793
3.39k
#endif
794
795
    /*
796
     * FIX  Why not put this check *first?*
797
     */
798
3.39k
    if (user->prev != NULL && user->prev != (struct usmUser *)-1) {   /* ack, this shouldn't happen */
799
0
        user->prev->next = user->next;
800
0
    }
801
3.39k
    if (user->next != NULL && user->next != (struct usmUser *)-1) {
802
0
        user->next->prev = user->prev;
803
0
        if (user->prev != NULL) /* ack this is really bad, because it means
804
                                 * * we'll loose the head of some structure tree */
805
0
            DEBUGMSGTL(("usm",
806
0
                        "Severe: Asked to free the head of a usmUser tree somewhere."));
807
0
    }
808
809
810
3.39k
    SNMP_ZERO(user, sizeof(*user));
811
3.39k
    SNMP_FREE(user);
812
813
3.39k
    return NULL;                /* for convenience to returns from calling functions */
814
815
21.7k
}                               /* end usm_free_user() */
816
817
int usm_set_priv_key(struct usmUser *user, const char *fname,
818
                     u_char **old_key, size_t *old_key_len,
819
                     const u_char *new_key, u_int new_key_len)
820
0
{
821
0
    u_char buf[SNMP_MAXBUF_SMALL], buf2[SNMP_MAXBUF_SMALL];
822
0
    size_t buflen = sizeof(buf);
823
0
    int plen, res;
824
825
0
    plen = sc_get_proper_priv_length(user->privProtocol,
826
0
                                     user->privProtocolLen);
827
0
    DEBUGMSGTL(("usmUser", "plen %d\n", plen));
828
    /*
829
     * extend key as needed
830
     */
831
0
    DEBUGMSGTL(("9:usmUser", "%s: new_key_len %d\n", fname, new_key_len));
832
0
    if (new_key_len < 2 * plen) {
833
0
        struct usmUser dummy;
834
835
0
        memset(&dummy, 0x0, sizeof(dummy));
836
0
        dummy.engineID = user->engineID;
837
0
        dummy.engineIDLen = user->engineIDLen;
838
0
        dummy.authProtocol = user->authProtocol;
839
0
        dummy.authProtocolLen = user->authProtocolLen;
840
0
        dummy.privProtocol = user->privProtocol;
841
0
        dummy.privProtocolLen = user->privProtocolLen;
842
0
        memcpy(buf2, new_key, new_key_len);
843
0
        dummy.privKey = buf2;
844
0
        dummy.privKeyLen = new_key_len;
845
0
        res = usm_extend_user_kul(&dummy, sizeof(buf2));
846
0
        if (res != SNMP_ERR_NOERROR) {
847
0
            DEBUGMSGTL(("usmUser", "%s: extend kul failed\n", fname));
848
0
            return SNMP_ERR_GENERR;
849
0
        }
850
0
        DEBUGMSGTL(("9:usmUser", "%s: extend kul OK\n", fname));
851
0
        new_key = dummy.privKey;
852
0
        new_key_len = dummy.privKeyLen;
853
        /*
854
         * make sure no reallocation happened; buf2 must be large enough
855
         */
856
0
        netsnmp_assert(dummy.privKey == buf2);
857
0
    }
858
859
    /*
860
     * Change the key. 
861
     */
862
0
    DEBUGMSGTL(("usmUser", "%s: changing priv key for user %s\n",
863
0
                fname, user->secName));
864
865
0
    res = decode_keychange(user->authProtocol, user->authProtocolLen,
866
0
                           user->privKey, user->privKeyLen, new_key,
867
0
                           new_key_len, buf, &buflen);
868
0
    if (res != SNMPERR_SUCCESS) {
869
0
        DEBUGMSGTL(("usmUser", "%s failed\n", fname));
870
0
        return SNMP_ERR_GENERR;
871
0
    }
872
0
    DEBUGMSGTL(("usmUser", "%s succeeded\n", fname));
873
0
    *old_key = user->privKey;
874
0
    *old_key_len = user->privKeyLen;
875
0
    user->privKey = netsnmp_memdup(buf, buflen);
876
0
    if (user->privKey == NULL)
877
0
        return SNMP_ERR_RESOURCEUNAVAILABLE;
878
0
    user->privKeyLen = buflen;
879
0
    return SNMP_ERR_NOERROR;
880
0
}
881
882
/*******************************************************************-o-******
883
 * usm_generate_OID
884
 *
885
 * Parameters:
886
 *  *prefix   (I) OID prefix to the usmUser table entry.
887
 *   prefixLen  (I)
888
 *  *uptr   (I) Pointer to a user in the user list.
889
 *  *length   (O) Length of generated index OID.
890
 *      
891
 * Returns:
892
 *  Pointer to the OID index for the user (uptr)  -OR-
893
 *  NULL on failure.
894
 *
895
 *
896
 * Generate the index OID for a given usmUser name.  'length' is set to
897
 * the length of the index OID.
898
 *
899
 * Index OID format is:
900
 *
901
 *    <...prefix>.<engineID_length>.<engineID>.<user_name_length>.<user_name>
902
 */
903
oid            *
904
usm_generate_OID(const oid *prefix, size_t prefixLen,
905
                 const struct usmUser *uptr, size_t *length)
906
0
{
907
0
    oid            *indexOid;
908
0
    int             i;
909
910
0
    *length = 2 + uptr->engineIDLen + strlen(uptr->name) + prefixLen;
911
0
    indexOid = malloc(*length * sizeof(oid));
912
0
    if (!indexOid)
913
0
        return indexOid;
914
915
0
    memmove(indexOid, prefix, prefixLen * sizeof(oid));
916
917
0
    indexOid[prefixLen] = uptr->engineIDLen;
918
0
    for (i = 0; i < uptr->engineIDLen; i++)
919
0
        indexOid[prefixLen + 1 + i] = (oid) uptr->engineID[i];
920
921
0
    indexOid[prefixLen + uptr->engineIDLen + 1] = strlen(uptr->name);
922
0
    for (i = 0; i < strlen(uptr->name); i++)
923
0
        indexOid[prefixLen + uptr->engineIDLen + 2 + i] = (oid) uptr->name[i];
924
925
0
    return indexOid;
926
0
}                               /* end usm_generate_OID() */
927
928
/*******************************************************************-o-******
929
 * asn_predict_int_length
930
 *
931
 * Parameters:
932
 *  type  (UNUSED)
933
 *  number
934
 *  len
935
 *      
936
 * Returns:
937
 *  Number of bytes necessary to store the ASN.1 encoded value of 'number'.
938
 *
939
 *
940
 *  This gives the number of bytes that the ASN.1 encoder (in asn1.c) will
941
 *  use to encode a particular integer value.
942
 *
943
 *  Returns the length of the integer -- NOT THE HEADER!
944
 *
945
 *  Do this the same way as asn_build_int()...
946
 */
947
static int
948
asn_predict_int_length(int type, long number, size_t len)
949
0
{
950
0
    register u_long mask;
951
952
953
0
    if (len != sizeof(long))
954
0
        return -1;
955
956
0
    mask = ((u_long) 0x1FF) << ((8 * (sizeof(long) - 1)) - 1);
957
    /*
958
     * mask is 0xFF800000 on a big-endian machine 
959
     */
960
961
0
    while ((((number & mask) == 0) || ((number & mask) == mask))
962
0
           && len > 1) {
963
0
        len--;
964
0
        number <<= 8;
965
0
    }
966
967
0
    return len;
968
969
0
}                               /* end asn_predict_length() */
970
971
/*******************************************************************-o-******
972
 * asn_predict_length
973
 *
974
 * Parameters:
975
 *   type
976
 *  *ptr
977
 *   u_char_len
978
 *      
979
 * Returns:
980
 *  Length in bytes:  1 + <n> + <u_char_len>, where
981
 *
982
 *    1   For the ASN.1 type.
983
 *    <n>   # of bytes to store length of data.
984
 *    <u_char_len>  Length of data associated with ASN.1 type.
985
 *
986
 *  This gives the number of bytes that the ASN.1 encoder (in asn1.c) will
987
 *  use to encode a particular integer value.  This is as broken as the
988
 *  currently used encoder.
989
 *
990
 * XXX  How is <n> chosen, exactly??
991
 */
992
static int
993
asn_predict_length(int type, u_char * ptr, size_t u_char_len)
994
0
{
995
    /* Check for integer overflow. */
996
0
    if (u_char_len > SIZE_MAX - (1 + 3))
997
0
        return -1;
998
999
0
    if (type & ASN_SEQUENCE)
1000
0
        return 1 + 3 + u_char_len;
1001
1002
0
    if (type & ASN_INTEGER) {
1003
0
        u_long          value;
1004
0
        memcpy(&value, ptr, u_char_len);
1005
0
        u_char_len = asn_predict_int_length(type, value, u_char_len);
1006
0
    }
1007
1008
    /* Check for integer overflow. */
1009
0
    if (u_char_len > SIZE_MAX - (1 + 3))
1010
0
        return -1;
1011
1012
0
    if (u_char_len < 0x80)
1013
0
        return 1 + 1 + u_char_len;
1014
0
    else if (u_char_len < 0xFF)
1015
0
        return 1 + 2 + u_char_len;
1016
0
    else
1017
0
        return 1 + 3 + u_char_len;
1018
1019
0
}                               /* end asn_predict_length() */
1020
1021
/*******************************************************************-o-******
1022
 * usm_calc_offsets
1023
 *
1024
 * Parameters:
1025
 *  (See list below...)
1026
 *      
1027
 * Returns:
1028
 *  0 On success,
1029
 *  -1  Otherwise.
1030
 *
1031
 *
1032
 *  This routine calculates the offsets into an outgoing message buffer
1033
 *  for the necessary values.  The outgoing buffer will generically
1034
 *  look like this:
1035
 *
1036
 *  SNMPv3 Message
1037
 *  SEQ len[11]
1038
 *    INT len version
1039
 *  Header
1040
 *    SEQ len
1041
 *      INT len MsgID
1042
 *      INT len msgMaxSize
1043
 *      OST len msgFlags (OST = OCTET STRING)
1044
 *      INT len msgSecurityModel
1045
 *  MsgSecurityParameters
1046
 *    [1] OST len[2]
1047
 *      SEQ len[3]
1048
 *        OST len msgAuthoritativeEngineID
1049
 *        INT len msgAuthoritativeEngineBoots
1050
 *        INT len msgAuthoritativeEngineTime
1051
 *        OST len msgUserName
1052
 *        OST len[4] [5] msgAuthenticationParameters
1053
 *        OST len[6] [7] msgPrivacyParameters
1054
 *  MsgData
1055
 *    [8] OST len[9] [10] encryptedPDU
1056
 *    or
1057
 *    [8,10] SEQUENCE len[9] scopedPDU
1058
 *  [12]
1059
 *
1060
 *  The bracketed points will be needed to be identified ([x] is an index
1061
 *  value, len[x] means a length value).  Here is a semantic guide to them:
1062
 *
1063
 *  [1] = globalDataLen (input)
1064
 *  [2] = otstlen
1065
 *  [3] = seq_len
1066
 *  [4] = msgAuthParmLen (may be 0 or 12)
1067
 *  [5] = authParamsOffset
1068
 *  [6] = msgPrivParmLen (may be 0 or 8)
1069
 *  [7] = privParamsOffset
1070
 *  [8] = globalDataLen + msgSecParmLen
1071
 *  [9] = datalen
1072
 *  [10] = dataOffset
1073
 *  [11] = theTotalLength - the length of the header itself
1074
 *  [12] = theTotalLength
1075
 */
1076
static int
1077
usm_calc_offsets(size_t globalDataLen,  /* SNMPv3Message + HeaderData */
1078
                 int secLevel, size_t secEngineIDLen, size_t secNameLen, size_t scopedPduLen,   /* An BER encoded sequence. */
1079
                 u_long engineboots,    /* XXX (asn1.c works in long, not int.) */
1080
                 long engine_time,      /* XXX (asn1.c works in long, not int.) */
1081
                 size_t * theTotalLength,       /* globalDataLen + msgSecurityP. + msgData */
1082
                 size_t * authParamsOffset,     /* Distance to auth bytes.                 */
1083
                 size_t * privParamsOffset,     /* Distance to priv bytes.                 */
1084
                 size_t * dataOffset,   /* Distance to scopedPdu SEQ  -or-  the
1085
                                         *   crypted (data) portion of msgData.    */
1086
                 size_t * datalen,      /* Size of msgData OCTET STRING encoding.  */
1087
                 size_t * msgAuthParmLen,       /* Size of msgAuthenticationParameters.    */
1088
                 size_t * msgPrivParmLen,       /* Size of msgPrivacyParameters.           */
1089
                 size_t * otstlen,      /* Size of msgSecurityP. O.S. encoding.    */
1090
                 size_t * seq_len,      /* Size of msgSecurityP. SEQ data.         */
1091
                 size_t * msgSecParmLen)
1092
0
{                               /* Size of msgSecurityP. SEQ.              */
1093
0
    int             engIDlen,   /* Sizes of OCTET STRING and SEQ encodings */
1094
0
                    engBtlen,   /*   for fields within                     */
1095
0
                    engTmlen,   /*   msgSecurityParameters portion of      */
1096
0
                    namelen,    /*   SNMPv3Message.                        */
1097
0
                    authlen, privlen, ret;
1098
1099
    /*
1100
     * If doing authentication, msgAuthParmLen = 12 else msgAuthParmLen = 0.
1101
     * If doing encryption,     msgPrivParmLen = 8  else msgPrivParmLen = 0.
1102
     */
1103
0
    *msgAuthParmLen = (secLevel == SNMP_SEC_LEVEL_AUTHNOPRIV
1104
0
                       || secLevel == SNMP_SEC_LEVEL_AUTHPRIV) ? 12 : 0;
1105
1106
0
    *msgPrivParmLen = (secLevel == SNMP_SEC_LEVEL_AUTHPRIV) ? 8 : 0;
1107
1108
1109
    /*
1110
     * Calculate lengths.
1111
     */
1112
0
    if ((engIDlen = asn_predict_length(ASN_OCTET_STR,
1113
0
                                       NULL, secEngineIDLen)) == -1) {
1114
0
        return -1;
1115
0
    }
1116
1117
0
    if ((engBtlen = asn_predict_length(ASN_INTEGER,
1118
0
                                       (u_char *) & engineboots,
1119
0
                                       sizeof(long))) == -1) {
1120
0
        return -1;
1121
0
    }
1122
1123
0
    if ((engTmlen = asn_predict_length(ASN_INTEGER,
1124
0
                                       (u_char *) & engine_time,
1125
0
                                       sizeof(long))) == -1) {
1126
0
        return -1;
1127
0
    }
1128
1129
0
    if ((namelen = asn_predict_length(ASN_OCTET_STR,
1130
0
                                      NULL, secNameLen)) == -1) {
1131
0
        return -1;
1132
0
    }
1133
1134
0
    if ((authlen = asn_predict_length(ASN_OCTET_STR,
1135
0
                                      NULL, *msgAuthParmLen)) == -1) {
1136
0
        return -1;
1137
0
    }
1138
1139
0
    if ((privlen = asn_predict_length(ASN_OCTET_STR,
1140
0
                                      NULL, *msgPrivParmLen)) == -1) {
1141
0
        return -1;
1142
0
    }
1143
1144
0
    *seq_len =
1145
0
        engIDlen + engBtlen + engTmlen + namelen + authlen + privlen;
1146
1147
0
    if ((ret = asn_predict_length(ASN_SEQUENCE,
1148
0
                                      NULL, *seq_len)) == -1) {
1149
0
        return -1;
1150
0
    }
1151
0
    *otstlen = (size_t)ret;
1152
1153
0
    if ((ret = asn_predict_length(ASN_OCTET_STR,
1154
0
                                      NULL, *otstlen)) == -1) {
1155
0
        return -1;
1156
0
    }
1157
0
    *msgSecParmLen = (size_t)ret;
1158
1159
0
    *authParamsOffset = globalDataLen + +(*msgSecParmLen - *seq_len)
1160
0
        + engIDlen + engBtlen + engTmlen + namelen
1161
0
        + (authlen - *msgAuthParmLen);
1162
1163
0
    *privParamsOffset = *authParamsOffset + *msgAuthParmLen
1164
0
        + (privlen - *msgPrivParmLen);
1165
1166
1167
    /*
1168
     * Compute the size of the plaintext.  Round up to account for cipher
1169
     * block size, if necessary.
1170
     *
1171
     * XXX  This is hardwired for 1DES... If scopedPduLen is already
1172
     *      a multiple of 8, then *add* 8 more; otherwise, round up
1173
     *      to the next multiple of 8.
1174
     *
1175
     * FIX  Calculation of encrypted portion of msgData and consequent
1176
     *      setting and sanity checking of theTotalLength, et al. should
1177
     *      occur *after* encryption has taken place.
1178
     */
1179
0
    if (secLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
1180
0
        scopedPduLen = ROUNDUP8(scopedPduLen);
1181
1182
0
        if ((ret = asn_predict_length(ASN_OCTET_STR, NULL, scopedPduLen)) == -1) {
1183
0
            return -1;
1184
0
        }
1185
0
        *datalen = (size_t)ret;
1186
0
    } else {
1187
0
        *datalen = scopedPduLen;
1188
0
    }
1189
1190
0
    *dataOffset = globalDataLen + *msgSecParmLen +
1191
0
        (*datalen - scopedPduLen);
1192
0
    *theTotalLength = globalDataLen + *msgSecParmLen + *datalen;
1193
1194
0
    return 0;
1195
1196
0
}                               /* end usm_calc_offsets() */
1197
1198
#ifndef NETSNMP_DISABLE_DES
1199
/*******************************************************************-o-******
1200
 * usm_set_salt
1201
 *
1202
 * Parameters:
1203
 *  *iv     (O)   Buffer to contain IV.
1204
 *  *iv_length    (O)   Length of iv.
1205
 *  *priv_salt    (I)   Salt portion of private key.
1206
 *   priv_salt_length (I)   Length of priv_salt.
1207
 *  *msgSalt    (I/O) Pointer salt portion of outgoing msg buffer.
1208
 *      
1209
 * Returns:
1210
 *  0 On success,
1211
 *  -1  Otherwise.
1212
 *
1213
 *  Determine the initialization vector for the DES-CBC encryption.
1214
 *  (Cf. RFC 2274, 8.1.1.1.)
1215
 *
1216
 *  iv is defined as the concatenation of engineBoots and the
1217
 *    salt integer.
1218
 *  The salt integer is incremented.
1219
 *  The resulting salt is copied into the msgSalt buffer.
1220
 *  The result of the concatenation is then XORed with the salt
1221
 *    portion of the private key (last 8 bytes).
1222
 *  The IV result is returned individually for further use.
1223
 */
1224
static int
1225
usm_set_salt(u_char * iv,
1226
             size_t * iv_length,
1227
             u_char * priv_salt, size_t priv_salt_length, u_char * msgSalt)
1228
0
{
1229
0
    size_t          propersize_salt = BYTESIZE(USM_DES_SALT_LENGTH);
1230
0
    int             net_boots;
1231
0
    int             net_salt_int;
1232
    /*
1233
     * net_* should be encoded in network byte order.  XXX  Why?
1234
     */
1235
0
    int             iindex;
1236
1237
1238
    /*
1239
     * Sanity check.
1240
     */
1241
0
    if (!iv || !iv_length || !priv_salt || (*iv_length != propersize_salt)
1242
0
        || (priv_salt_length < propersize_salt)) {
1243
0
        return -1;
1244
0
    }
1245
1246
1247
0
    net_boots = htonl(snmpv3_local_snmpEngineBoots());
1248
0
    net_salt_int = htonl(salt_integer);
1249
1250
0
    salt_integer += 1;
1251
1252
0
    memcpy(iv, &net_boots, propersize_salt / 2);
1253
0
    memcpy(iv + (propersize_salt / 2), &net_salt_int, propersize_salt / 2);
1254
1255
0
    if (msgSalt)
1256
0
        memcpy(msgSalt, iv, propersize_salt);
1257
1258
1259
    /*
1260
     * Turn the salt into an IV: XOR <boots, salt_int> with salt
1261
     * portion of priv_key.
1262
     */
1263
0
    for (iindex = 0; iindex < (int) propersize_salt; iindex++)
1264
0
        iv[iindex] ^= priv_salt[iindex];
1265
1266
1267
0
    return 0;
1268
1269
0
}                               /* end usm_set_salt() */
1270
#endif
1271
1272
#ifdef HAVE_AES
1273
/*******************************************************************-o-******
1274
 * usm_set_aes_iv
1275
 *
1276
 * Parameters:
1277
 *  *iv     (O)   Buffer to contain IV.
1278
 *  *iv_length    (O)   Length of iv.
1279
 *      net_boots         (I)   the network byte order of the authEng boots val
1280
 *      net_time         (I)   the network byte order of the authEng time val
1281
 *      *salt             (O)   A buffer for the outgoing salt (= 8 bytes of iv)
1282
 *      
1283
 * Returns:
1284
 *  0 On success,
1285
 *  -1  Otherwise.
1286
 *
1287
 *  Determine the initialization vector for AES encryption.
1288
 *  (draft-blumenthal-aes-usm-03.txt, 3.1.2.2)
1289
 *
1290
 *  iv is defined as the concatenation of engineBoots, engineTime
1291
    and a 64 bit salt-integer.
1292
 *  The 64 bit salt integer is incremented.
1293
 *  The resulting salt is copied into the salt buffer.
1294
 *  The IV result is returned individually for further use.
1295
 */
1296
static int
1297
usm_set_aes_iv(u_char * iv,
1298
               size_t * iv_length,
1299
               u_int net_boots,
1300
               u_int net_time,
1301
               u_char * salt)
1302
0
{
1303
    /*
1304
     * net_* should be encoded in network byte order.
1305
     */
1306
0
    int             net_salt_int1, net_salt_int2;
1307
0
#define PROPER_AES_IV_SIZE 64
1308
1309
    /*
1310
     * Sanity check.
1311
     */
1312
0
    if (!iv || !iv_length) {
1313
0
        return -1;
1314
0
    }
1315
1316
0
    net_salt_int1 = htonl(salt_integer64_1);
1317
0
    net_salt_int2 = htonl(salt_integer64_2);
1318
1319
0
    if ((salt_integer64_2 += 1) == 0)
1320
0
        salt_integer64_2 += 1;
1321
    
1322
    /* XXX: warning: hard coded proper lengths */
1323
0
    memcpy(iv, &net_boots, 4);
1324
0
    memcpy(iv+4, &net_time, 4);
1325
0
    memcpy(iv+8, &net_salt_int1, 4);
1326
0
    memcpy(iv+12, &net_salt_int2, 4);
1327
1328
0
    memcpy(salt, iv+8, 8); /* only copy the needed portion */
1329
0
    return 0;
1330
0
}                               /* end usm_set_aes_iv() */
1331
#endif /* HAVE_AES */
1332
1333
/*******************************************************************-o-******
1334
 * usm_check_secLevel_vs_protocols
1335
 *
1336
 * Parameters:
1337
 *   level
1338
 *  *authProtocol
1339
 *   authProtocolLen
1340
 *  *privProtocol
1341
 *   privProtocolLen
1342
 *
1343
 * Returns:
1344
 *  0 On success,
1345
 *  1 Otherwise.
1346
 *
1347
 * Same as above but with explicitly named transform types instead of taking
1348
 * from the usmUser structure.
1349
 */
1350
static int
1351
usm_check_secLevel_vs_protocols(int level,
1352
                                const oid * authProtocol,
1353
                                u_int authProtocolLen,
1354
                                const oid * privProtocol,
1355
                                u_int privProtocolLen)
1356
0
{
1357
1358
0
    if (level == SNMP_SEC_LEVEL_AUTHPRIV
1359
0
        &&
1360
0
        (netsnmp_oid_equals
1361
0
         (privProtocol, privProtocolLen, usmNoPrivProtocol,
1362
0
          OID_LENGTH(usmNoPrivProtocol)) == 0)) {
1363
0
        DEBUGMSGTL(("usm", "Level: %d\n", level));
1364
0
        DEBUGMSGTL(("usm", "Auth Protocol: "));
1365
0
        DEBUGMSGOID(("usm", authProtocol, authProtocolLen));
1366
0
        DEBUGMSG(("usm", ", Priv Protocol: "));
1367
0
        DEBUGMSGOID(("usm", privProtocol, privProtocolLen));
1368
0
        DEBUGMSG(("usm", "\n"));
1369
0
        return 1;
1370
0
    }
1371
0
    if ((level == SNMP_SEC_LEVEL_AUTHPRIV
1372
0
         || level == SNMP_SEC_LEVEL_AUTHNOPRIV)
1373
0
        &&
1374
0
        (netsnmp_oid_equals
1375
0
         (authProtocol, authProtocolLen, usmNoAuthProtocol,
1376
0
          OID_LENGTH(usmNoAuthProtocol)) == 0)) {
1377
0
        DEBUGMSGTL(("usm", "Level: %d\n", level));
1378
0
        DEBUGMSGTL(("usm", "Auth Protocol: "));
1379
0
        DEBUGMSGOID(("usm", authProtocol, authProtocolLen));
1380
0
        DEBUGMSG(("usm", ", Priv Protocol: "));
1381
0
        DEBUGMSGOID(("usm", privProtocol, privProtocolLen));
1382
0
        DEBUGMSG(("usm", "\n"));
1383
0
        return 1;
1384
0
    }
1385
1386
0
    return 0;
1387
1388
0
}                               /* end usm_check_secLevel_vs_protocols() */
1389
1390
/*******************************************************************-o-******
1391
 * usm_generate_out_msg
1392
 *
1393
 * Parameters:
1394
 *  (See list below...)
1395
 *      
1396
 * Returns:
1397
 *  SNMPERR_SUCCESS     On success.
1398
 *  SNMPERR_USM_AUTHENTICATIONFAILURE
1399
 *  SNMPERR_USM_ENCRYPTIONERROR
1400
 *  SNMPERR_USM_GENERICERROR
1401
 *  SNMPERR_USM_UNKNOWNSECURITYNAME
1402
 *  SNMPERR_USM_GENERICERROR
1403
 *  SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL
1404
 *  
1405
 *
1406
 * Generates an outgoing message.
1407
 *
1408
 * XXX  Beware of misnomers!
1409
 */
1410
static int
1411
usm_generate_out_msg(int msgProcModel,  /* (UNUSED) */
1412
                     u_char * globalData,       /* IN */
1413
                     /*
1414
                      * Pointer to msg header data will point to the beginning
1415
                      * * of the entire packet buffer to be transmitted on wire,
1416
                      * * memory will be contiguous with secParams, typically
1417
                      * * this pointer will be passed back as beginning of
1418
                      * * wholeMsg below.  asn seq. length is updated w/ new length.
1419
                      * *
1420
                      * * While this points to a buffer that should be big enough
1421
                      * * for the whole message, only the first two parts
1422
                      * * of the message are completed, namely SNMPv3Message and
1423
                      * * HeaderData.  globalDataLen (next parameter) represents
1424
                      * * the length of these two completed parts.
1425
                      */
1426
                     size_t globalDataLen,      /* IN - Length of msg header data.      */
1427
                     int maxMsgSize,    /* (UNUSED) */
1428
                     int secModel,      /* (UNUSED) */
1429
                     const u_char *secEngineID, /* IN - Pointer snmpEngineID. */
1430
                     size_t secEngineIDLen,     /* IN - SnmpEngineID length.  */
1431
                     const char *secName,     /* IN - Pointer to securityName.*/
1432
                     size_t secNameLen, /* IN - SecurityName length.          */
1433
                     int secLevel,      /* IN - AuthNoPriv, authPriv etc.     */
1434
                     const u_char *scopedPdu, /* IN */
1435
                     /*
1436
                      * Pointer to scopedPdu will be encrypted by USM if needed
1437
                      * * and written to packet buffer immediately following
1438
                      * * securityParameters, entire msg will be authenticated by
1439
                      * * USM if needed.
1440
                      */
1441
                     size_t scopedPduLen,       /* IN - scopedPdu length. */
1442
                     const void *secStateRef, /* IN */
1443
                     /*
1444
                      * secStateRef, pointer to cached info provided only for
1445
                      * * Response, otherwise NULL.
1446
                      */
1447
                     struct usmUser *sessUser,  /* IN - pointer to current session user. */
1448
                     u_char * secParams,        /* OUT */
1449
                     /*
1450
                      * BER encoded securityParameters pointer to offset within
1451
                      * * packet buffer where secParams should be written, the
1452
                      * * entire BER encoded OCTET STRING (including header) is
1453
                      * * written here by USM secParams = globalData +
1454
                      * * globalDataLen.
1455
                      */
1456
                     size_t * secParamsLen,     /* IN/OUT - Len available, len returned. */
1457
                     u_char ** wholeMsg,        /* OUT */
1458
                     /*
1459
                      * Complete authenticated/encrypted message - typically
1460
                      * * the pointer to start of packet buffer provided in
1461
                      * * globalData is returned here, could also be a separate
1462
                      * * buffer.
1463
                      */
1464
                     size_t * wholeMsgLen)
1465
0
{                               /* IN/OUT - Len available, len returned. */
1466
0
    size_t          otstlen;
1467
0
    size_t          seq_len;
1468
0
    size_t          msgAuthParmLen;
1469
0
    size_t          msgPrivParmLen;
1470
0
    size_t          msgSecParmLen;
1471
0
    size_t          authParamsOffset;
1472
0
    size_t          privParamsOffset;
1473
0
    size_t          datalen;
1474
0
    size_t          dataOffset;
1475
0
    size_t          theTotalLength;
1476
1477
0
    u_char         *ptr;
1478
0
    size_t          ptr_len;
1479
0
    size_t          remaining;
1480
0
    size_t          offSet;
1481
0
    u_int           boots_uint;
1482
0
    u_int           time_uint;
1483
0
    long            boots_long;
1484
0
    long            time_long;
1485
1486
    /*
1487
     * Indirection because secStateRef values override parameters.
1488
     * 
1489
     * None of these are to be free'd - they are either pointing to
1490
     * what's in the secStateRef or to something either in the
1491
     * actual parameter list or the user list.
1492
     */
1493
1494
0
    const char     *theName = NULL;
1495
0
    u_int           theNameLength = 0;
1496
0
    const u_char   *theEngineID = NULL;
1497
0
    u_int           theEngineIDLength = 0;
1498
0
    u_char         *theAuthKey = NULL;
1499
0
    u_int           theAuthKeyLength = 0;
1500
0
    const oid      *theAuthProtocol = NULL;
1501
0
    u_int           theAuthProtocolLength = 0;
1502
0
    u_char         *thePrivKey = NULL;
1503
0
    u_int           thePrivKeyLength = 0;
1504
0
    const oid      *thePrivProtocol = NULL;
1505
0
    u_int           thePrivProtocolLength = 0;
1506
0
    int             theSecLevel = 0;    /* No defined const for bad
1507
                                         * value (other then err).
1508
                                         */
1509
1510
0
    DEBUGMSGTL(("usm", "USM processing has begun.\n"));
1511
1512
0
    if (secStateRef != NULL) {
1513
        /*
1514
         * To hush the compiler for now.  XXX 
1515
         */
1516
0
        const struct usmStateReference *ref = secStateRef;
1517
1518
0
        theName = ref->usr_name;
1519
0
        theNameLength = ref->usr_name_length;
1520
0
        theEngineID = ref->usr_engine_id;
1521
0
        theEngineIDLength = ref->usr_engine_id_length;
1522
1523
0
        if (!theEngineIDLength) {
1524
0
            theEngineID = secEngineID;
1525
0
            theEngineIDLength = secEngineIDLen;
1526
0
        }
1527
1528
0
        theAuthProtocol = ref->usr_auth_protocol;
1529
0
        theAuthProtocolLength = ref->usr_auth_protocol_length;
1530
0
        theAuthKey = ref->usr_auth_key;
1531
0
        theAuthKeyLength = ref->usr_auth_key_length;
1532
0
        thePrivProtocol = ref->usr_priv_protocol;
1533
0
        thePrivProtocolLength = ref->usr_priv_protocol_length;
1534
0
        thePrivKey = ref->usr_priv_key;
1535
0
        thePrivKeyLength = ref->usr_priv_key_length;
1536
0
        theSecLevel = ref->usr_sec_level;
1537
0
    }
1538
1539
    /*
1540
     * Identify the user record.
1541
     */
1542
0
    else {
1543
0
        struct usmUser *user;
1544
1545
        /*
1546
         * we do allow an unknown user name for
1547
         * unauthenticated requests. 
1548
         */
1549
0
        if (sessUser)
1550
0
            user = sessUser;
1551
0
        else
1552
0
            user = usm_get_user2(secEngineID, secEngineIDLen, secName, secNameLen);
1553
1554
0
        if (user == NULL && secLevel != SNMP_SEC_LEVEL_NOAUTH) {
1555
0
            DEBUGMSGTL(("usm", "Unknown User(%s)\n", secName));
1556
0
            return SNMPERR_USM_UNKNOWNSECURITYNAME;
1557
0
        }
1558
1559
0
        theName = secName;
1560
0
        theNameLength = secNameLen;
1561
0
        theEngineID = secEngineID;
1562
0
        theSecLevel = secLevel;
1563
0
        theEngineIDLength = secEngineIDLen;
1564
0
        if (user) {
1565
0
            theAuthProtocol = user->authProtocol;
1566
0
            theAuthProtocolLength = user->authProtocolLen;
1567
0
            theAuthKey = user->authKey;
1568
0
            theAuthKeyLength = user->authKeyLen;
1569
0
            thePrivProtocol = user->privProtocol;
1570
0
            thePrivProtocolLength = user->privProtocolLen;
1571
0
            thePrivKey = user->privKey;
1572
0
            thePrivKeyLength = user->privKeyLen;
1573
0
        } else {
1574
            /*
1575
             * unknown users can not do authentication (obviously) 
1576
             */
1577
0
            theAuthProtocol = usmNoAuthProtocol;
1578
0
            theAuthProtocolLength =
1579
0
                OID_LENGTH(usmNoAuthProtocol);
1580
0
            theAuthKey = NULL;
1581
0
            theAuthKeyLength = 0;
1582
0
            thePrivProtocol = usmNoPrivProtocol;
1583
0
            thePrivProtocolLength =
1584
0
                OID_LENGTH(usmNoPrivProtocol);
1585
0
            thePrivKey = NULL;
1586
0
            thePrivKeyLength = 0;
1587
0
        }
1588
0
    }                           /* endif -- secStateRef==NULL */
1589
1590
1591
    /*
1592
     * From here to the end of the function, avoid reference to
1593
     * secName, secEngineID, secLevel, and associated lengths.
1594
     */
1595
1596
1597
    /*
1598
     * Check to see if the user can use the requested sec services.
1599
     */
1600
0
    if (usm_check_secLevel_vs_protocols(theSecLevel,
1601
0
                                        theAuthProtocol,
1602
0
                                        theAuthProtocolLength,
1603
0
                                        thePrivProtocol,
1604
0
                                        thePrivProtocolLength) == 1) {
1605
0
        DEBUGMSGTL(("usm", "Unsupported Security Level (%d)\n",
1606
0
                    theSecLevel));
1607
0
        return SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL;
1608
0
    }
1609
1610
1611
    /*
1612
     * Retrieve the engine information.
1613
     *
1614
     * XXX  No error is declared in the EoP when sending messages to
1615
     *      unknown engines, processing continues w/ boots/time == (0,0).
1616
     */
1617
0
    if (get_enginetime(theEngineID, theEngineIDLength,
1618
0
                       &boots_uint, &time_uint, FALSE) == -1) {
1619
0
        DEBUGMSGTL(("usm", "%s\n", "Failed to find engine data."));
1620
0
    }
1621
1622
0
    boots_long = boots_uint;
1623
0
    time_long = time_uint;
1624
1625
1626
    /*
1627
     * Set up the Offsets.
1628
     */
1629
0
    if (usm_calc_offsets(globalDataLen, theSecLevel, theEngineIDLength,
1630
0
                         theNameLength, scopedPduLen, boots_long,
1631
0
                         time_long, &theTotalLength, &authParamsOffset,
1632
0
                         &privParamsOffset, &dataOffset, &datalen,
1633
0
                         &msgAuthParmLen, &msgPrivParmLen, &otstlen,
1634
0
                         &seq_len, &msgSecParmLen) == -1) {
1635
0
        DEBUGMSGTL(("usm", "Failed calculating offsets.\n"));
1636
0
        return SNMPERR_USM_GENERICERROR;
1637
0
    }
1638
1639
    /*
1640
     * So, we have the offsets for the three parts that need to be
1641
     * determined, and an overall length.  Now we need to make
1642
     * sure all of this would fit in the outgoing buffer, and
1643
     * whether or not we need to make a new buffer, etc.
1644
     */
1645
1646
1647
    /*
1648
     * Set wholeMsg as a pointer to globalData.  Sanity check for
1649
     * the proper size.
1650
     * 
1651
     * Mark workspace in the message with bytes of all 1's to make it
1652
     * easier to find mistakes in raw message dumps.
1653
     */
1654
0
    ptr = *wholeMsg = globalData;
1655
0
    if (theTotalLength > *wholeMsgLen) {
1656
0
        DEBUGMSGTL(("usm", "Message won't fit in buffer.\n"));
1657
0
        return SNMPERR_USM_GENERICERROR;
1658
0
    }
1659
1660
0
    ptr_len = *wholeMsgLen = theTotalLength;
1661
1662
#ifdef NETSNMP_ENABLE_TESTING_CODE
1663
    memset(&ptr[globalDataLen], 0xFF, theTotalLength - globalDataLen);
1664
#endif                          /* NETSNMP_ENABLE_TESTING_CODE */
1665
1666
    /*
1667
     * Do the encryption.
1668
     */
1669
0
    if (theSecLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
1670
0
        size_t          encrypted_length = theTotalLength - dataOffset;
1671
0
        size_t          salt_length = BYTESIZE(USM_MAX_SALT_LENGTH);
1672
0
        u_char          salt[BYTESIZE(USM_MAX_SALT_LENGTH)];
1673
0
        int             priv_type = sc_get_privtype(thePrivProtocol,
1674
0
                                                    thePrivProtocolLength);
1675
0
#ifdef HAVE_AES
1676
0
        if (USM_CREATE_USER_PRIV_AES == (priv_type & USM_PRIV_MASK_ALG)) {
1677
0
            if (!thePrivKey ||
1678
0
                usm_set_aes_iv(salt, &salt_length,
1679
0
                               htonl(boots_uint), htonl(time_uint),
1680
0
                               &ptr[privParamsOffset]) == -1) {
1681
0
                DEBUGMSGTL(("usm", "Can't set AES iv.\n"));
1682
0
                return SNMPERR_USM_GENERICERROR;
1683
0
            }
1684
0
        }
1685
0
#endif
1686
0
#ifndef NETSNMP_DISABLE_DES
1687
        /*
1688
         * XXX  Hardwired to seek into a 1DES private key!
1689
         */
1690
0
        if (USM_CREATE_USER_PRIV_DES == (priv_type & USM_PRIV_MASK_ALG)) {
1691
0
            if (!thePrivKey ||
1692
0
                (usm_set_salt(salt, &salt_length,
1693
0
                              thePrivKey + 8, thePrivKeyLength - 8,
1694
0
                              &ptr[privParamsOffset])
1695
0
                 == -1)) {
1696
0
                DEBUGMSGTL(("usm", "Can't set DES-CBC salt.\n"));
1697
0
                return SNMPERR_USM_GENERICERROR;
1698
0
            }
1699
0
        }
1700
0
#endif
1701
1702
0
        if (sc_encrypt(thePrivProtocol, thePrivProtocolLength,
1703
0
                       thePrivKey, thePrivKeyLength,
1704
0
                       salt, salt_length,
1705
0
                       scopedPdu, scopedPduLen,
1706
0
                       &ptr[dataOffset], &encrypted_length)
1707
0
            != SNMP_ERR_NOERROR) {
1708
0
            DEBUGMSGTL(("usm", "encryption error.\n"));
1709
0
            return SNMPERR_USM_ENCRYPTIONERROR;
1710
0
        }
1711
#ifdef NETSNMP_ENABLE_TESTING_CODE
1712
        if (debug_is_token_registered("usm/dump") == SNMPERR_SUCCESS) {
1713
            dump_chunk("usm/dump", "This data was encrypted:",
1714
                       scopedPdu, scopedPduLen);
1715
            dump_chunk("usm/dump", "salt + Encrypted form:",
1716
                       salt, salt_length);
1717
            dump_chunk("usm/dump", NULL,
1718
                       &ptr[dataOffset], encrypted_length);
1719
            dump_chunk("usm/dump", "*wholeMsg:",
1720
                       *wholeMsg, theTotalLength);
1721
        }
1722
#endif
1723
1724
1725
0
        ptr = *wholeMsg;
1726
0
        ptr_len = *wholeMsgLen = theTotalLength;
1727
1728
1729
        /*
1730
         * XXX  Sanity check for salt length should be moved up
1731
         *      under usm_calc_offsets() or tossed.
1732
         */
1733
0
        if ((encrypted_length != (theTotalLength - dataOffset))
1734
0
            || (salt_length != msgPrivParmLen)) {
1735
0
            DEBUGMSGTL(("usm", "encryption length error.\n"));
1736
0
            return SNMPERR_USM_ENCRYPTIONERROR;
1737
0
        }
1738
1739
0
        DEBUGMSGTL(("usm", "Encryption successful.\n"));
1740
0
    }
1741
1742
    /*
1743
     * No encryption for you!
1744
     */
1745
0
    else {
1746
0
        memcpy(&ptr[dataOffset], scopedPdu, scopedPduLen);
1747
0
    }
1748
1749
1750
1751
    /*
1752
     * Start filling in the other fields (in prep for authentication).
1753
     * 
1754
     * offSet is an octet string header, which is different from all
1755
     * the other headers.
1756
     */
1757
0
    remaining = ptr_len - globalDataLen;
1758
1759
0
    offSet = ptr_len - remaining;
1760
0
    asn_build_header(&ptr[offSet], &remaining,
1761
0
                     (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
1762
0
                               ASN_OCTET_STR), otstlen);
1763
1764
0
    offSet = ptr_len - remaining;
1765
0
    asn_build_sequence(&ptr[offSet], &remaining,
1766
0
                       (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), seq_len);
1767
1768
0
    offSet = ptr_len - remaining;
1769
0
    DEBUGDUMPHEADER("send", "msgAuthoritativeEngineID");
1770
0
    asn_build_string(&ptr[offSet], &remaining,
1771
0
                     (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
1772
0
                               ASN_OCTET_STR), theEngineID,
1773
0
                     theEngineIDLength);
1774
0
    DEBUGINDENTLESS();
1775
1776
0
    offSet = ptr_len - remaining;
1777
0
    DEBUGDUMPHEADER("send", "msgAuthoritativeEngineBoots");
1778
0
    asn_build_int(&ptr[offSet], &remaining,
1779
0
                  (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
1780
0
                  &boots_long, sizeof(long));
1781
0
    DEBUGINDENTLESS();
1782
1783
0
    offSet = ptr_len - remaining;
1784
0
    DEBUGDUMPHEADER("send", "msgAuthoritativeEngineTime");
1785
0
    asn_build_int(&ptr[offSet], &remaining,
1786
0
                  (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
1787
0
                  &time_long, sizeof(long));
1788
0
    DEBUGINDENTLESS();
1789
1790
0
    offSet = ptr_len - remaining;
1791
0
    DEBUGDUMPHEADER("send", "msgUserName");
1792
0
    asn_build_string(&ptr[offSet], &remaining,
1793
0
                     (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
1794
0
                               ASN_OCTET_STR), (const u_char *) theName,
1795
0
                     theNameLength);
1796
0
    DEBUGINDENTLESS();
1797
1798
1799
    /*
1800
     * Note: if there is no authentication being done,
1801
     * msgAuthParmLen is 0, and there is no effect (other than
1802
     * inserting a zero-length header) of the following
1803
     * statements.
1804
     */
1805
1806
0
    offSet = ptr_len - remaining;
1807
0
    asn_build_header(&ptr[offSet],
1808
0
                     &remaining,
1809
0
                     (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
1810
0
                               ASN_OCTET_STR), msgAuthParmLen);
1811
1812
0
    if (theSecLevel == SNMP_SEC_LEVEL_AUTHNOPRIV
1813
0
        || theSecLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
1814
0
        offSet = ptr_len - remaining;
1815
0
        memset(&ptr[offSet], 0, msgAuthParmLen);
1816
0
    }
1817
1818
0
    remaining -= msgAuthParmLen;
1819
1820
1821
    /*
1822
     * Note: if there is no encryption being done, msgPrivParmLen
1823
     * is 0, and there is no effect (other than inserting a
1824
     * zero-length header) of the following statements.
1825
     */
1826
1827
0
    offSet = ptr_len - remaining;
1828
0
    asn_build_header(&ptr[offSet],
1829
0
                     &remaining,
1830
0
                     (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
1831
0
                               ASN_OCTET_STR), msgPrivParmLen);
1832
1833
0
    remaining -= msgPrivParmLen;        /* Skipping the IV already there. */
1834
1835
1836
    /*
1837
     * For privacy, need to add the octet string header for it.
1838
     */
1839
0
    if (theSecLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
1840
0
        offSet = ptr_len - remaining;
1841
0
        asn_build_header(&ptr[offSet],
1842
0
                         &remaining,
1843
0
                         (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
1844
0
                                   ASN_OCTET_STR),
1845
0
                         theTotalLength - dataOffset);
1846
0
    }
1847
1848
1849
    /*
1850
     * Adjust overall length and store it as the first SEQ length
1851
     * of the SNMPv3Message.
1852
     *
1853
     * FIX  4 is a magic number!
1854
     */
1855
0
    remaining = theTotalLength;
1856
0
    asn_build_sequence(ptr, &remaining,
1857
0
                       (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
1858
0
                       theTotalLength - 4);
1859
1860
1861
    /*
1862
     * Now, time to consider / do authentication.
1863
     */
1864
0
    if (theSecLevel == SNMP_SEC_LEVEL_AUTHNOPRIV
1865
0
        || theSecLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
1866
0
        size_t          temp_sig_len = msgAuthParmLen;
1867
0
        u_char         *temp_sig = (u_char *) malloc(temp_sig_len);
1868
1869
0
        if (temp_sig == NULL) {
1870
0
            DEBUGMSGTL(("usm", "Out of memory.\n"));
1871
0
            return SNMPERR_USM_GENERICERROR;
1872
0
        }
1873
1874
0
        if (sc_generate_keyed_hash(theAuthProtocol, theAuthProtocolLength,
1875
0
                                   theAuthKey, theAuthKeyLength,
1876
0
                                   ptr, ptr_len, temp_sig, &temp_sig_len)
1877
0
            != SNMP_ERR_NOERROR) {
1878
            /*
1879
             * FIX temp_sig_len defined?!
1880
             */
1881
0
            SNMP_ZERO(temp_sig, temp_sig_len);
1882
0
            SNMP_FREE(temp_sig);
1883
0
            DEBUGMSGTL(("usm", "Signing failed.\n"));
1884
0
            return SNMPERR_USM_AUTHENTICATIONFAILURE;
1885
0
        }
1886
1887
0
        if (temp_sig_len != msgAuthParmLen) {
1888
0
            SNMP_ZERO(temp_sig, temp_sig_len);
1889
0
            SNMP_FREE(temp_sig);
1890
0
            DEBUGMSGTL(("usm", "Signing lengths failed.\n"));
1891
0
            return SNMPERR_USM_AUTHENTICATIONFAILURE;
1892
0
        }
1893
1894
0
        memcpy(&ptr[authParamsOffset], temp_sig, msgAuthParmLen);
1895
1896
0
        SNMP_ZERO(temp_sig, temp_sig_len);
1897
0
        SNMP_FREE(temp_sig);
1898
1899
0
    }
1900
1901
    /*
1902
     * endif -- create keyed hash 
1903
     */
1904
1905
0
    DEBUGMSGTL(("usm", "USM processing completed.\n"));
1906
1907
0
    return SNMPERR_SUCCESS;
1908
1909
0
}                               /* end usm_generate_out_msg() */
1910
1911
static int
1912
usm_secmod_generate_out_msg(struct snmp_secmod_outgoing_params *parms)
1913
0
{
1914
0
    if (!parms)
1915
0
        return SNMPERR_GENERR;
1916
1917
0
    return usm_generate_out_msg(parms->msgProcModel,
1918
0
                                parms->globalData, parms->globalDataLen,
1919
0
                                parms->maxMsgSize, parms->secModel,
1920
0
                                parms->secEngineID, parms->secEngineIDLen,
1921
0
                                parms->secName, parms->secNameLen,
1922
0
                                parms->secLevel,
1923
0
                                parms->scopedPdu, parms->scopedPduLen,
1924
0
                                parms->secStateRef,
1925
0
                                parms->session->sessUser,
1926
0
                                parms->secParams, parms->secParamsLen,
1927
0
                                parms->wholeMsg, parms->wholeMsgLen);
1928
0
}
1929
1930
#ifdef NETSNMP_USE_REVERSE_ASNENCODING
1931
static int
1932
usm_rgenerate_out_msg(int msgProcModel, /* (UNUSED) */
1933
                      u_char * globalData,      /* IN */
1934
                      /*
1935
                       * points at the msgGlobalData, which is of length given by next 
1936
                       * parameter.  
1937
                       */
1938
                      size_t globalDataLen,     /* IN - Length of msg header data.      */
1939
                      int maxMsgSize,   /* (UNUSED) */
1940
                      int secModel,     /* (UNUSED) */
1941
                      const u_char *secEngineID, /* IN - Pointer snmpEngineID.*/
1942
                      size_t secEngineIDLen,     /* IN - SnmpEngineID length. */
1943
                      const char *secName,    /* IN - Pointer to securityName.*/
1944
                      size_t secNameLen,        /* IN - SecurityName length.  */
1945
                      int secLevel,         /* IN - AuthNoPriv, authPriv etc. */
1946
                      const u_char *scopedPdu,       /* IN */
1947
                      /*
1948
                       * Pointer to scopedPdu will be encrypted by USM if needed
1949
                       * * and written to packet buffer immediately following
1950
                       * * securityParameters, entire msg will be authenticated by
1951
                       * * USM if needed.
1952
                       */
1953
                      size_t scopedPduLen,      /* IN - scopedPdu length. */
1954
                      const void *secStateRef,  /* IN */
1955
                      /*
1956
                       * secStateRef, pointer to cached info provided only for
1957
                       * * Response, otherwise NULL.
1958
                       */
1959
                     struct usmUser *sessUser,  /* IN - pointer to current session user. */
1960
1961
                      u_char ** wholeMsg,       /*  IN/OUT  */
1962
                      /*
1963
                       * Points at the pointer to the packet buffer, which might get extended
1964
                       * if necessary via realloc().  
1965
                       */
1966
                      size_t * wholeMsgLen,     /*  IN/OUT  */
1967
                      /*
1968
                       * Length of the entire packet buffer, **not** the length of the
1969
                       * packet.  
1970
                       */
1971
                      size_t * offset           /*  IN/OUT  */
1972
                      /*
1973
                       * Offset from the end of the packet buffer to the start of the packet,
1974
                       * also known as the packet length.  
1975
                       */
1976
    )
1977
0
{
1978
0
    size_t          msgAuthParmLen = 0;
1979
0
    u_int           boots_uint;
1980
0
    u_int           time_uint;
1981
0
    long            boots_long;
1982
0
    long            time_long;
1983
1984
    /*
1985
     * Indirection because secStateRef values override parameters.
1986
     * 
1987
     * None of these are to be free'd - they are either pointing to
1988
     * what's in the secStateRef or to something either in the
1989
     * actual parameter list or the user list.
1990
     */
1991
1992
0
    const char     *theName = NULL;
1993
0
    u_int           theNameLength = 0;
1994
0
    const u_char   *theEngineID = NULL;
1995
0
    u_int           theEngineIDLength = 0;
1996
0
    u_char         *theAuthKey = NULL;
1997
0
    u_int           theAuthKeyLength = 0;
1998
0
    const oid      *theAuthProtocol = NULL;
1999
0
    u_int           theAuthProtocolLength = 0;
2000
0
    u_char         *thePrivKey = NULL;
2001
0
    u_int           thePrivKeyLength = 0;
2002
0
    const oid      *thePrivProtocol = NULL;
2003
0
    u_int           thePrivProtocolLength = 0;
2004
0
    int             theSecLevel = 0;    /* No defined const for bad
2005
                                         * value (other then err). */
2006
0
    size_t          salt_length = 0, save_salt_length = 0;
2007
0
    u_char          salt[BYTESIZE(USM_MAX_SALT_LENGTH)];
2008
0
    u_char          authParams[USM_MAX_AUTHSIZE];
2009
0
    u_char          iv[BYTESIZE(USM_MAX_SALT_LENGTH)];
2010
0
    size_t          sp_offset = 0, mac_offset = 0;
2011
0
    int             rc = 0;
2012
2013
0
    DEBUGMSGTL(("usm", "USM processing has begun (offset %d)\n", (int)*offset));
2014
2015
0
    if (secStateRef != NULL) {
2016
        /*
2017
         * To hush the compiler for now.  XXX 
2018
         */
2019
0
        const struct usmStateReference *ref = secStateRef;
2020
2021
0
        theName = ref->usr_name;
2022
0
        theNameLength = ref->usr_name_length;
2023
0
        theEngineID = ref->usr_engine_id;
2024
0
        theEngineIDLength = ref->usr_engine_id_length;
2025
2026
0
        if (!theEngineIDLength) {
2027
0
            theEngineID = secEngineID;
2028
0
            theEngineIDLength = secEngineIDLen;
2029
0
        }
2030
2031
0
        theAuthProtocol = ref->usr_auth_protocol;
2032
0
        theAuthProtocolLength = ref->usr_auth_protocol_length;
2033
0
        theAuthKey = ref->usr_auth_key;
2034
0
        theAuthKeyLength = ref->usr_auth_key_length;
2035
0
        thePrivProtocol = ref->usr_priv_protocol;
2036
0
        thePrivProtocolLength = ref->usr_priv_protocol_length;
2037
0
        thePrivKey = ref->usr_priv_key;
2038
0
        thePrivKeyLength = ref->usr_priv_key_length;
2039
0
        theSecLevel = ref->usr_sec_level;
2040
0
    }
2041
2042
    /*
2043
     * * Identify the user record.
2044
     */
2045
0
    else {
2046
0
        struct usmUser *user;
2047
2048
        /*
2049
         * we do allow an unknown user name for
2050
         * unauthenticated requests. 
2051
         */
2052
0
        if (sessUser)
2053
0
            user = sessUser;
2054
0
        else
2055
0
            user = usm_get_user2(secEngineID, secEngineIDLen, secName, secNameLen);
2056
2057
0
        if (user == NULL && secLevel != SNMP_SEC_LEVEL_NOAUTH) {
2058
0
            DEBUGMSGTL(("usm", "Unknown User\n"));
2059
0
            return SNMPERR_USM_UNKNOWNSECURITYNAME;
2060
0
        }
2061
2062
0
        theName = secName;
2063
0
        theNameLength = secNameLen;
2064
0
        theEngineID = secEngineID;
2065
0
        theSecLevel = secLevel;
2066
0
        theEngineIDLength = secEngineIDLen;
2067
0
        if (user) {
2068
0
            theAuthProtocol = user->authProtocol;
2069
0
            theAuthProtocolLength = user->authProtocolLen;
2070
0
            theAuthKey = user->authKey;
2071
0
            theAuthKeyLength = user->authKeyLen;
2072
0
            thePrivProtocol = user->privProtocol;
2073
0
            thePrivProtocolLength = user->privProtocolLen;
2074
0
            thePrivKey = user->privKey;
2075
0
            thePrivKeyLength = user->privKeyLen;
2076
0
        } else {
2077
            /*
2078
             * unknown users can not do authentication (obviously) 
2079
             */
2080
0
            theAuthProtocol = usmNoAuthProtocol;
2081
0
            theAuthProtocolLength =
2082
0
                OID_LENGTH(usmNoAuthProtocol);
2083
0
            theAuthKey = NULL;
2084
0
            theAuthKeyLength = 0;
2085
0
            thePrivProtocol = usmNoPrivProtocol;
2086
0
            thePrivProtocolLength =
2087
0
                OID_LENGTH(usmNoPrivProtocol);
2088
0
            thePrivKey = NULL;
2089
0
            thePrivKeyLength = 0;
2090
0
        }
2091
0
    }                           /* endif -- secStateRef==NULL */
2092
2093
2094
    /*
2095
     * From here to the end of the function, avoid reference to
2096
     * secName, secEngineID, secLevel, and associated lengths.
2097
     */
2098
2099
2100
    /*
2101
     * Check to see if the user can use the requested sec services.
2102
     */
2103
0
    if (usm_check_secLevel_vs_protocols(theSecLevel,
2104
0
                                        theAuthProtocol,
2105
0
                                        theAuthProtocolLength,
2106
0
                                        thePrivProtocol,
2107
0
                                        thePrivProtocolLength) == 1) {
2108
0
        DEBUGMSGTL(("usm", "Unsupported Security Level or type (%d)\n",
2109
0
                    theSecLevel));
2110
2111
0
        return SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL;
2112
0
    }
2113
2114
2115
    /*
2116
     * * Retrieve the engine information.
2117
     * *
2118
     * * XXX    No error is declared in the EoP when sending messages to
2119
     * *        unknown engines, processing continues w/ boots/time == (0,0).
2120
     */
2121
0
    if (get_enginetime(theEngineID, theEngineIDLength,
2122
0
                       &boots_uint, &time_uint, FALSE) == -1) {
2123
0
        DEBUGMSGTL(("usm", "%s\n", "Failed to find engine data."));
2124
0
    }
2125
2126
0
    boots_long = boots_uint;
2127
0
    time_long = time_uint;
2128
2129
0
    if (theSecLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
2130
        /*
2131
         * Initially assume that the ciphertext will end up the same size as
2132
         * the plaintext plus some padding.  Really sc_encrypt ought to be able
2133
         * to grow this for us, a la asn_realloc_rbuild_<type> functions, but
2134
         * this will do for now.  
2135
         */
2136
0
        u_char         *ciphertext = NULL;
2137
0
        size_t          ciphertextlen = scopedPduLen + 64;
2138
0
        int             priv_type = sc_get_privtype(thePrivProtocol,
2139
0
                                                    thePrivProtocolLength);
2140
2141
0
        if ((ciphertext = (u_char *) malloc(ciphertextlen)) == NULL) {
2142
0
            DEBUGMSGTL(("usm",
2143
0
                        "couldn't malloc %d bytes for encrypted PDU\n",
2144
0
                        (int)ciphertextlen));
2145
0
            return SNMPERR_MALLOC;
2146
0
        }
2147
2148
        /*
2149
         * XXX Hardwired to seek into a 1DES private key!  
2150
         */
2151
0
#ifdef HAVE_AES
2152
0
        if (USM_CREATE_USER_PRIV_AES == (priv_type & USM_PRIV_MASK_ALG)) {
2153
0
            salt_length = BYTESIZE(USM_AES_SALT_LENGTH);
2154
0
            save_salt_length = BYTESIZE(USM_AES_SALT_LENGTH)/2;
2155
0
            if (!thePrivKey ||
2156
0
                usm_set_aes_iv(salt, &salt_length,
2157
0
                               htonl(boots_uint), htonl(time_uint),
2158
0
                               iv) == -1) {
2159
0
                DEBUGMSGTL(("usm", "Can't set AES iv.\n"));
2160
0
                SNMP_FREE(ciphertext);
2161
0
                return SNMPERR_USM_GENERICERROR;
2162
0
            }
2163
0
        } 
2164
0
#endif
2165
0
#ifndef NETSNMP_DISABLE_DES
2166
0
        if (USM_CREATE_USER_PRIV_DES == (priv_type & USM_PRIV_MASK_ALG)) {
2167
0
            salt_length = BYTESIZE(USM_DES_SALT_LENGTH);
2168
0
            save_salt_length = BYTESIZE(USM_DES_SALT_LENGTH);
2169
0
            if (!thePrivKey || (usm_set_salt(salt, &salt_length,
2170
0
                                             thePrivKey + 8,
2171
0
                                             thePrivKeyLength - 8,
2172
0
                                             iv) == -1)) {
2173
0
                DEBUGMSGTL(("usm", "Can't set DES-CBC salt.\n"));
2174
0
                SNMP_FREE(ciphertext);
2175
0
                return SNMPERR_USM_GENERICERROR;
2176
0
            }
2177
0
        }
2178
0
#endif
2179
#ifdef NETSNMP_ENABLE_TESTING_CODE
2180
        if (debug_is_token_registered("usm/dump") == SNMPERR_SUCCESS) {
2181
            dump_chunk("usm/dump", "This data was encrypted:",
2182
                       scopedPdu, scopedPduLen);
2183
        }
2184
#endif
2185
2186
0
        if (sc_encrypt(thePrivProtocol, thePrivProtocolLength,
2187
0
                       thePrivKey, thePrivKeyLength,
2188
0
                       salt, salt_length,
2189
0
                       scopedPdu, scopedPduLen,
2190
0
                       ciphertext, &ciphertextlen) != SNMP_ERR_NOERROR) {
2191
0
            DEBUGMSGTL(("usm", "encryption error.\n"));
2192
0
            SNMP_FREE(ciphertext);
2193
0
            return SNMPERR_USM_ENCRYPTIONERROR;
2194
0
        }
2195
2196
        /*
2197
         * Write the encrypted scopedPdu back into the packet buffer.  
2198
         */
2199
2200
0
        *offset = 0;
2201
0
        rc = asn_realloc_rbuild_string(wholeMsg, wholeMsgLen, offset, 1,
2202
0
                                       (u_char) (ASN_UNIVERSAL |
2203
0
                                                 ASN_PRIMITIVE |
2204
0
                                                 ASN_OCTET_STR),
2205
0
                                       ciphertext, ciphertextlen);
2206
0
        if (rc == 0) {
2207
0
            DEBUGMSGTL(("usm", "Encryption failed.\n"));
2208
0
            SNMP_FREE(ciphertext);
2209
0
            return SNMPERR_USM_ENCRYPTIONERROR;
2210
0
        }
2211
2212
#ifdef NETSNMP_ENABLE_TESTING_CODE
2213
        if (debug_is_token_registered("usm/dump") == SNMPERR_SUCCESS) {
2214
            dump_chunk("usm/dump", "salt + Encrypted form: ", salt,
2215
                       salt_length);
2216
            dump_chunk("usm/dump", "wholeMsg:",
2217
                       (*wholeMsg + *wholeMsgLen - *offset), *offset);
2218
        }
2219
#endif
2220
2221
0
        DEBUGMSGTL(("usm", "Encryption successful.\n"));
2222
0
        SNMP_FREE(ciphertext);
2223
0
    } else {
2224
        /*
2225
         * theSecLevel != SNMP_SEC_LEVEL_AUTHPRIV  
2226
         */
2227
0
    }
2228
2229
    /*
2230
     * Start encoding the msgSecurityParameters.  
2231
     */
2232
2233
0
    sp_offset = *offset;
2234
2235
0
    DEBUGDUMPHEADER("send", "msgPrivacyParameters");
2236
    /*
2237
     * msgPrivacyParameters (warning: assumes DES salt).  
2238
     */
2239
0
    rc = asn_realloc_rbuild_string(wholeMsg, wholeMsgLen, offset, 1,
2240
0
                                   (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE
2241
0
                                             | ASN_OCTET_STR),
2242
0
                                   iv,
2243
0
                                   save_salt_length);
2244
0
    DEBUGINDENTLESS();
2245
0
    if (rc == 0) {
2246
0
        DEBUGMSGTL(("usm", "building privParams failed.\n"));
2247
0
        return SNMPERR_TOO_LONG;
2248
0
    }
2249
2250
0
    DEBUGDUMPHEADER("send", "msgAuthenticationParameters");
2251
    /*
2252
     * msgAuthenticationParameters.
2253
     */
2254
0
    if (theSecLevel == SNMP_SEC_LEVEL_AUTHNOPRIV
2255
0
        || theSecLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
2256
0
        memset(authParams, 0, sizeof(authParams));
2257
0
        msgAuthParmLen =
2258
0
            sc_get_auth_maclen(sc_get_authtype(theAuthProtocol,
2259
0
                                               theAuthProtocolLength));
2260
0
    }
2261
2262
0
    rc = asn_realloc_rbuild_string(wholeMsg, wholeMsgLen, offset, 1,
2263
0
                                   (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE
2264
0
                                             | ASN_OCTET_STR), authParams,
2265
0
                                   msgAuthParmLen);
2266
0
    DEBUGINDENTLESS();
2267
0
    if (rc == 0) {
2268
0
        DEBUGMSGTL(("usm", "building authParams failed.\n"));
2269
0
        return SNMPERR_TOO_LONG;
2270
0
    }
2271
2272
    /*
2273
     * Remember where to put the actual HMAC we calculate later on.  An
2274
     * encoded OCTET STRING of length USM_MD5_AND_SHA_AUTH_LEN has an ASN.1
2275
     * header of length 2, hence the fudge factor.  This works as long as
2276
     * auth lengths stay < 127.
2277
     */
2278
0
    mac_offset = *offset - 2;
2279
2280
    /*
2281
     * msgUserName.  
2282
     */
2283
0
    DEBUGDUMPHEADER("send", "msgUserName");
2284
0
    rc = asn_realloc_rbuild_string(wholeMsg, wholeMsgLen, offset, 1,
2285
0
                                   (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE
2286
0
                                             | ASN_OCTET_STR),
2287
0
                                   (const u_char *) theName, theNameLength);
2288
0
    DEBUGINDENTLESS();
2289
0
    if (rc == 0) {
2290
0
        DEBUGMSGTL(("usm", "building authParams failed.\n"));
2291
0
        return SNMPERR_TOO_LONG;
2292
0
    }
2293
2294
    /*
2295
     * msgAuthoritativeEngineTime.  
2296
     */
2297
0
    DEBUGDUMPHEADER("send", "msgAuthoritativeEngineTime");
2298
0
    rc = asn_realloc_rbuild_int(wholeMsg, wholeMsgLen, offset, 1,
2299
0
                                (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
2300
0
                                          ASN_INTEGER), &time_long,
2301
0
                                sizeof(long));
2302
0
    DEBUGINDENTLESS();
2303
0
    if (rc == 0) {
2304
0
        DEBUGMSGTL(("usm",
2305
0
                    "building msgAuthoritativeEngineTime failed.\n"));
2306
0
        return SNMPERR_TOO_LONG;
2307
0
    }
2308
2309
    /*
2310
     * msgAuthoritativeEngineBoots.  
2311
     */
2312
0
    DEBUGDUMPHEADER("send", "msgAuthoritativeEngineBoots");
2313
0
    rc = asn_realloc_rbuild_int(wholeMsg, wholeMsgLen, offset, 1,
2314
0
                                (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
2315
0
                                          ASN_INTEGER), &boots_long,
2316
0
                                sizeof(long));
2317
0
    DEBUGINDENTLESS();
2318
0
    if (rc == 0) {
2319
0
        DEBUGMSGTL(("usm",
2320
0
                    "building msgAuthoritativeEngineBoots failed.\n"));
2321
0
        return SNMPERR_TOO_LONG;
2322
0
    }
2323
2324
0
    DEBUGDUMPHEADER("send", "msgAuthoritativeEngineID");
2325
0
    rc = asn_realloc_rbuild_string(wholeMsg, wholeMsgLen, offset, 1,
2326
0
                                   (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE
2327
0
                                             | ASN_OCTET_STR), theEngineID,
2328
0
                                   theEngineIDLength);
2329
0
    DEBUGINDENTLESS();
2330
0
    if (rc == 0) {
2331
0
        DEBUGMSGTL(("usm", "building msgAuthoritativeEngineID failed.\n"));
2332
0
        return SNMPERR_TOO_LONG;
2333
0
    }
2334
2335
    /*
2336
     * USM msgSecurityParameters sequence header  
2337
     */
2338
0
    rc = asn_realloc_rbuild_sequence(wholeMsg, wholeMsgLen, offset, 1,
2339
0
                                     (u_char) (ASN_SEQUENCE |
2340
0
                                               ASN_CONSTRUCTOR),
2341
0
                                     *offset - sp_offset);
2342
0
    if (rc == 0) {
2343
0
        DEBUGMSGTL(("usm", "building usm security parameters failed.\n"));
2344
0
        return SNMPERR_TOO_LONG;
2345
0
    }
2346
2347
    /*
2348
     * msgSecurityParameters OCTET STRING wrapper.  
2349
     */
2350
0
    rc = asn_realloc_rbuild_header(wholeMsg, wholeMsgLen, offset, 1,
2351
0
                                   (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE
2352
0
                                             | ASN_OCTET_STR),
2353
0
                                   *offset - sp_offset);
2354
2355
0
    if (rc == 0) {
2356
0
        DEBUGMSGTL(("usm", "building msgSecurityParameters failed.\n"));
2357
0
        return SNMPERR_TOO_LONG;
2358
0
    }
2359
2360
    /*
2361
     * Copy in the msgGlobalData and msgVersion.  
2362
     */
2363
0
    while ((*wholeMsgLen - *offset) < globalDataLen) {
2364
0
        if (!asn_realloc(wholeMsg, wholeMsgLen)) {
2365
0
            DEBUGMSGTL(("usm", "building global data failed.\n"));
2366
0
            return SNMPERR_TOO_LONG;
2367
0
        }
2368
0
    }
2369
2370
0
    *offset += globalDataLen;
2371
0
    memcpy(*wholeMsg + *wholeMsgLen - *offset, globalData, globalDataLen);
2372
2373
    /*
2374
     * Total packet sequence.  
2375
     */
2376
0
    rc = asn_realloc_rbuild_sequence(wholeMsg, wholeMsgLen, offset, 1,
2377
0
                                     (u_char) (ASN_SEQUENCE |
2378
0
                                               ASN_CONSTRUCTOR), *offset);
2379
0
    if (rc == 0) {
2380
0
        DEBUGMSGTL(("usm", "building master packet sequence failed.\n"));
2381
0
        return SNMPERR_TOO_LONG;
2382
0
    }
2383
2384
    /*
2385
     * Now consider / do authentication.  
2386
     */
2387
2388
0
    if (theSecLevel == SNMP_SEC_LEVEL_AUTHNOPRIV ||
2389
0
        theSecLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
2390
0
        size_t          temp_sig_len = msgAuthParmLen;
2391
0
        u_char         *temp_sig = (u_char *) malloc(temp_sig_len);
2392
0
        u_char         *proto_msg = *wholeMsg + *wholeMsgLen - *offset;
2393
0
        size_t          proto_msg_len = *offset;
2394
2395
2396
0
        if (temp_sig == NULL) {
2397
0
            DEBUGMSGTL(("usm", "Out of memory.\n"));
2398
0
            return SNMPERR_USM_GENERICERROR;
2399
0
        }
2400
2401
0
        if (sc_generate_keyed_hash(theAuthProtocol, theAuthProtocolLength,
2402
0
                                   theAuthKey, theAuthKeyLength,
2403
0
                                   proto_msg, proto_msg_len,
2404
0
                                   temp_sig, &temp_sig_len)
2405
0
            != SNMP_ERR_NOERROR) {
2406
0
            SNMP_FREE(temp_sig);
2407
0
            DEBUGMSGTL(("usm", "Signing failed.\n"));
2408
0
            return SNMPERR_USM_AUTHENTICATIONFAILURE;
2409
0
        }
2410
2411
0
        if (temp_sig_len != msgAuthParmLen) {
2412
0
            SNMP_FREE(temp_sig);
2413
0
            DEBUGMSGTL(("usm", "Signing lengths failed.\n"));
2414
0
            return SNMPERR_USM_AUTHENTICATIONFAILURE;
2415
0
        }
2416
2417
0
        memcpy(*wholeMsg + *wholeMsgLen - mac_offset, temp_sig,
2418
0
               msgAuthParmLen);
2419
0
        SNMP_FREE(temp_sig);
2420
0
    }
2421
    /*
2422
     * endif -- create keyed hash 
2423
     */
2424
0
    DEBUGMSGTL(("usm", "USM processing completed.\n"));
2425
0
    return SNMPERR_SUCCESS;
2426
0
}                               /* end usm_rgenerate_out_msg() */
2427
2428
static int
2429
usm_secmod_rgenerate_out_msg(struct snmp_secmod_outgoing_params *parms)
2430
0
{
2431
0
    if (!parms)
2432
0
        return SNMPERR_GENERR;
2433
2434
0
    return usm_rgenerate_out_msg(parms->msgProcModel,
2435
0
                                 parms->globalData, parms->globalDataLen,
2436
0
                                 parms->maxMsgSize, parms->secModel,
2437
0
                                 parms->secEngineID, parms->secEngineIDLen,
2438
0
                                 parms->secName, parms->secNameLen,
2439
0
                                 parms->secLevel,
2440
0
                                 parms->scopedPdu, parms->scopedPduLen,
2441
0
                                 parms->secStateRef,
2442
0
                                 parms->session->sessUser,
2443
0
                                 parms->wholeMsg, parms->wholeMsgLen,
2444
0
                                 parms->wholeMsgOffset);
2445
0
}
2446
#endif                          /* */
2447
2448
/*******************************************************************-o-******
2449
 * usm_parse_security_parameters
2450
 *
2451
 * Parameters:
2452
 *  (See list below...)
2453
 *      
2454
 * Returns:
2455
 *  0 On success,
2456
 *  -1  Otherwise.
2457
 *
2458
 *  tab stop 4
2459
 *
2460
 *  Extracts values from the security header and data portions of the
2461
 *  incoming buffer.
2462
 */
2463
static int
2464
usm_parse_security_parameters(u_char * secParams,
2465
                              size_t remaining,
2466
                              u_char * secEngineID,
2467
                              size_t * secEngineIDLen,
2468
                              u_int * boots_uint,
2469
                              u_int * time_uint,
2470
                              char *secName,
2471
                              size_t * secNameLen,
2472
                              u_char * signature,
2473
                              size_t * signature_length,
2474
                              u_char * salt,
2475
                              size_t * salt_length, u_char ** data_ptr)
2476
0
{
2477
0
    u_char         *parse_ptr = secParams;
2478
0
    u_char         *value_ptr;
2479
0
    u_char         *next_ptr;
2480
0
    u_char          type_value;
2481
2482
0
    size_t          octet_string_length = remaining;
2483
0
    size_t          sequence_length;
2484
0
    size_t          remaining_bytes;
2485
2486
0
    long            boots_long;
2487
0
    long            time_long;
2488
2489
0
    u_int           origNameLen;
2490
2491
2492
    /*
2493
     * Eat the first octet header.
2494
     */
2495
0
    if ((value_ptr = asn_parse_sequence(parse_ptr, &octet_string_length,
2496
0
                                        &type_value,
2497
0
                                        (ASN_UNIVERSAL | ASN_PRIMITIVE |
2498
0
                                         ASN_OCTET_STR),
2499
0
                                        "usm first octet")) == NULL) {
2500
        /*
2501
         * RETURN parse error 
2502
0
         */ return -1;
2503
0
    }
2504
2505
2506
    /*
2507
     * Eat the sequence header.
2508
     */
2509
0
    parse_ptr = value_ptr;
2510
0
    sequence_length = octet_string_length;
2511
2512
0
    if ((value_ptr = asn_parse_sequence(parse_ptr, &sequence_length,
2513
0
                                        &type_value,
2514
0
                                        (ASN_SEQUENCE | ASN_CONSTRUCTOR),
2515
0
                                        "usm sequence")) == NULL) {
2516
        /*
2517
         * RETURN parse error 
2518
0
         */ return -1;
2519
0
    }
2520
2521
2522
    /*
2523
     * Retrieve the engineID.
2524
     */
2525
0
    parse_ptr = value_ptr;
2526
0
    remaining_bytes = sequence_length;
2527
2528
0
    DEBUGDUMPHEADER("recv", "msgAuthoritativeEngineID");
2529
0
    if ((next_ptr
2530
0
         = asn_parse_string(parse_ptr, &remaining_bytes, &type_value,
2531
0
                            secEngineID, secEngineIDLen)) == NULL) {
2532
0
        DEBUGINDENTLESS();
2533
        /*
2534
         * RETURN parse error 
2535
0
         */ return -1;
2536
0
    }
2537
0
    DEBUGINDENTLESS();
2538
2539
0
    if (type_value !=
2540
0
        (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR)) {
2541
        /*
2542
         * RETURN parse error 
2543
0
         */ return -1;
2544
0
    }
2545
2546
2547
    /*
2548
     * Retrieve the engine boots, notice switch in the way next_ptr and
2549
     * remaining_bytes are used (to accommodate the asn code).
2550
     */
2551
0
    DEBUGDUMPHEADER("recv", "msgAuthoritativeEngineBoots");
2552
0
    if ((next_ptr = asn_parse_int(next_ptr, &remaining_bytes, &type_value,
2553
0
                                  &boots_long, sizeof(long))) == NULL) {
2554
0
        DEBUGINDENTLESS();
2555
        /*
2556
         * RETURN parse error 
2557
0
         */ return -1;
2558
0
    }
2559
0
    DEBUGINDENTLESS();
2560
2561
0
    if (type_value !=
2562
0
        (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER)) {
2563
0
        DEBUGINDENTLESS();
2564
        /*
2565
         * RETURN parse error 
2566
0
         */ return -1;
2567
0
    }
2568
2569
0
    *boots_uint = (u_int) boots_long;
2570
2571
2572
    /*
2573
     * Retrieve the time value.
2574
     */
2575
0
    DEBUGDUMPHEADER("recv", "msgAuthoritativeEngineTime");
2576
0
    if ((next_ptr = asn_parse_int(next_ptr, &remaining_bytes, &type_value,
2577
0
                                  &time_long, sizeof(long))) == NULL) {
2578
        /*
2579
         * RETURN parse error 
2580
0
         */ return -1;
2581
0
    }
2582
0
    DEBUGINDENTLESS();
2583
2584
0
    if (type_value !=
2585
0
        (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER)) {
2586
        /*
2587
         * RETURN parse error 
2588
0
         */ return -1;
2589
0
    }
2590
2591
0
    *time_uint = (u_int) time_long;
2592
2593
0
    if (*boots_uint > ENGINEBOOT_MAX || *time_uint > ENGINETIME_MAX) {
2594
0
        return -1;
2595
0
    }
2596
2597
    /*
2598
     * Retrieve the secName.
2599
     */
2600
0
    origNameLen = *secNameLen;
2601
2602
2603
0
    DEBUGDUMPHEADER("recv", "msgUserName");
2604
0
    if ((next_ptr
2605
0
         = asn_parse_string(next_ptr, &remaining_bytes, &type_value,
2606
0
                            (u_char *) secName, secNameLen)) == NULL) {
2607
0
        DEBUGINDENTLESS();
2608
        /*
2609
         * RETURN parse error 
2610
0
         */ return -1;
2611
0
    }
2612
0
    DEBUGINDENTLESS();
2613
2614
    /*
2615
     * FIX -- doesn't this also indicate a buffer overrun?
2616
     */
2617
0
    if (origNameLen < *secNameLen + 1) {
2618
        /*
2619
         * RETURN parse error, but it's really a parameter error 
2620
         */
2621
0
        return -1;
2622
0
    }
2623
2624
0
    if (*secNameLen > 32) {
2625
        /*
2626
         * This is a USM-specific limitation over and above the above
2627
         * limitation (which will probably default to the length of an
2628
         * SnmpAdminString, i.e. 255).  See RFC 2574, sec. 2.4.  
2629
         */
2630
0
        return -1;
2631
0
    }
2632
2633
0
    secName[*secNameLen] = '\0';
2634
2635
0
    if (type_value !=
2636
0
        (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR)) {
2637
        /*
2638
         * RETURN parse error 
2639
0
         */ return -1;
2640
0
    }
2641
2642
2643
    /*
2644
     * Retrieve the signature and blank it if there.
2645
     */
2646
0
    DEBUGDUMPHEADER("recv", "msgAuthenticationParameters");
2647
0
    if ((next_ptr
2648
0
         = asn_parse_string(next_ptr, &remaining_bytes, &type_value,
2649
0
                            signature, signature_length)) == NULL) {
2650
0
        DEBUGINDENTLESS();
2651
        /*
2652
         * RETURN parse error 
2653
0
         */ return -1;
2654
0
    }
2655
0
    DEBUGINDENTLESS();
2656
2657
0
    if (type_value !=
2658
0
        (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR)) {
2659
        /*
2660
         * RETURN parse error 
2661
0
         */ return -1;
2662
0
    }
2663
2664
0
    if (*signature_length != 0) {       /* Blanking for authentication step later */
2665
0
        memset(next_ptr - (u_long) * signature_length,
2666
0
               0, *signature_length);
2667
0
    }
2668
2669
2670
    /*
2671
     * Retrieve the salt.
2672
     *
2673
     * Note that the next ptr is where the data section starts.
2674
     */
2675
0
    DEBUGDUMPHEADER("recv", "msgPrivacyParameters");
2676
0
    if ((*data_ptr
2677
0
         = asn_parse_string(next_ptr, &remaining_bytes, &type_value,
2678
0
                            salt, salt_length)) == NULL) {
2679
0
        DEBUGINDENTLESS();
2680
        /*
2681
         * RETURN parse error 
2682
0
         */ return -2;
2683
0
    }
2684
0
    DEBUGINDENTLESS();
2685
2686
0
    if (type_value !=
2687
0
        (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR)) {
2688
        /*
2689
         * RETURN parse error 
2690
0
         */ return -2;
2691
0
    }
2692
2693
0
    return 0;
2694
2695
0
}                               /* end usm_parse_security_parameters() */
2696
2697
2698
2699
2700
/*******************************************************************-o-******
2701
 * usm_check_and_update_timeliness
2702
 *
2703
 * Parameters:
2704
 *  *secEngineID
2705
 *   secEngineIDen
2706
 *   boots_uint
2707
 *   time_uint
2708
 *  *error
2709
 *      
2710
 * Returns:
2711
 *  0 On success,
2712
 *  -1  Otherwise.
2713
 *  
2714
 *
2715
 * Performs the incoming timeliness checking and setting.
2716
 */
2717
static int
2718
usm_check_and_update_timeliness(u_char * secEngineID,
2719
                                size_t secEngineIDLen,
2720
                                u_int boots_uint,
2721
                                u_int time_uint, int *error)
2722
0
{
2723
0
    u_char          myID[USM_MAX_ID_LENGTH];
2724
0
    u_long          myIDLength =
2725
0
        snmpv3_get_engineID(myID, USM_MAX_ID_LENGTH);
2726
0
    u_int           myBoots;
2727
0
    u_int           myTime;
2728
2729
2730
2731
0
    if ((myIDLength > USM_MAX_ID_LENGTH) || (myIDLength == 0)) {
2732
        /*
2733
         * We're probably already screwed...buffer overwrite.  XXX? 
2734
         */
2735
0
        DEBUGMSGTL(("usm", "Buffer overflow.\n"));
2736
0
        *error = SNMPERR_USM_GENERICERROR;
2737
0
        return -1;
2738
0
    }
2739
2740
0
    myBoots = snmpv3_local_snmpEngineBoots();
2741
0
    myTime = snmpv3_local_snmpEngineTime();
2742
2743
2744
    /*
2745
     * IF the time involved is local
2746
     *     Make sure  message is inside the time window 
2747
     * ELSE 
2748
     *      IF boots is higher or boots is the same and time is higher
2749
     *              remember this new data
2750
     *      ELSE
2751
     *              IF !(boots same and time within USM_TIME_WINDOW secs)
2752
     *                      Message is too old 
2753
     *              ELSE    
2754
     *                      Message is ok, but don't take time
2755
     *              ENDIF
2756
     *      ENDIF
2757
     * ENDIF
2758
     */
2759
2760
    /*
2761
     * This is a local reference.
2762
     */
2763
0
    if (secEngineIDLen == myIDLength
2764
0
        && memcmp(secEngineID, myID, myIDLength) == 0) {
2765
0
        u_int           time_difference = myTime > time_uint ?
2766
0
            myTime - time_uint : time_uint - myTime;
2767
2768
0
        if (boots_uint == ENGINEBOOT_MAX
2769
0
            || boots_uint != myBoots
2770
0
            || time_difference > USM_TIME_WINDOW) {
2771
0
            snmp_increment_statistic(STAT_USMSTATSNOTINTIMEWINDOWS);
2772
2773
0
            DEBUGMSGTL(("usm",
2774
0
                        "boot_uint %u myBoots %u time_diff %u => not in time window\n",
2775
0
                        boots_uint, myBoots, time_difference));
2776
0
            *error = SNMPERR_USM_NOTINTIMEWINDOW;
2777
0
            return -1;
2778
0
        }
2779
2780
0
        *error = SNMPERR_SUCCESS;
2781
0
        return 0;
2782
0
    }
2783
2784
    /*
2785
     * This is a remote reference.
2786
     */
2787
0
    else {
2788
0
        u_int           theirBoots, theirTime, theirLastTime;
2789
0
        u_int           time_difference;
2790
2791
0
        if (get_enginetime_ex(secEngineID, secEngineIDLen,
2792
0
                              &theirBoots, &theirTime,
2793
0
                              &theirLastTime, TRUE)
2794
0
            != SNMPERR_SUCCESS) {
2795
0
            DEBUGMSGTL(("usm", "%s\n",
2796
0
                        "Failed to get remote engine's times."));
2797
2798
0
            *error = SNMPERR_USM_GENERICERROR;
2799
0
            return -1;
2800
0
        }
2801
2802
0
        time_difference = theirTime > time_uint ?
2803
0
            theirTime - time_uint : time_uint - theirTime;
2804
2805
2806
        /*
2807
         * XXX  Contrary to the pseudocode:
2808
         *      See if boots is invalid first.
2809
         */
2810
0
        if (theirBoots == ENGINEBOOT_MAX || theirBoots > boots_uint) {
2811
0
            DEBUGMSGTL(("usm", "%s\n", "Remote boot count invalid."));
2812
2813
0
            *error = SNMPERR_USM_NOTINTIMEWINDOW;
2814
0
            return -1;
2815
0
        }
2816
2817
2818
        /*
2819
         * Boots is ok, see if the boots is the same but the time
2820
         * is old.
2821
         */
2822
0
        if (theirBoots == boots_uint && time_uint < theirLastTime) {
2823
0
            if (time_difference > USM_TIME_WINDOW) {
2824
0
                DEBUGMSGTL(("usm", "%s\n", "Message too old."));
2825
0
                *error = SNMPERR_USM_NOTINTIMEWINDOW;
2826
0
                return -1;
2827
0
            }
2828
2829
0
            else {              /* Old, but acceptable */
2830
2831
0
                *error = SNMPERR_SUCCESS;
2832
0
                return 0;
2833
0
            }
2834
0
        }
2835
2836
2837
        /*
2838
         * Message is ok, either boots has been advanced, or
2839
         * time is greater than before with the same boots.
2840
         */
2841
2842
0
        if (set_enginetime(secEngineID, secEngineIDLen,
2843
0
                           boots_uint, time_uint, TRUE)
2844
0
            != SNMPERR_SUCCESS) {
2845
0
            DEBUGMSGTL(("usm", "%s\n",
2846
0
                        "Failed updating remote boot/time."));
2847
0
            *error = SNMPERR_USM_GENERICERROR;
2848
0
            return -1;
2849
0
        }
2850
2851
0
        *error = SNMPERR_SUCCESS;
2852
0
        return 0;               /* Fresh message and time updated */
2853
2854
0
    }                           /* endif -- local or remote time reference. */
2855
2856
2857
0
}                               /* end usm_check_and_update_timeliness() */
2858
2859
/*******************************************************************-o-******
2860
 * usm_check_secLevel
2861
 *
2862
 * Parameters:
2863
 *   level
2864
 *  *user
2865
 *      
2866
 * Returns:
2867
 *  0 On success,
2868
 *  -1  Otherwise.
2869
 *
2870
 * Checks that a given security level is valid for a given user.
2871
 */
2872
static int
2873
usm_check_secLevel(int level, struct usmUser *user)
2874
0
{
2875
2876
0
    if (user->userStatus != RS_ACTIVE)
2877
0
        return -1;
2878
2879
0
    DEBUGMSGTL(("comparex", "Comparing: %" NETSNMP_PRIo "u %" NETSNMP_PRIo "u ",
2880
0
                usmNoPrivProtocol[0], usmNoPrivProtocol[1]));
2881
0
    DEBUGMSGOID(("comparex", usmNoPrivProtocol,
2882
0
                 OID_LENGTH(usmNoPrivProtocol)));
2883
0
    DEBUGMSG(("comparex", "\n"));
2884
0
    if (level == SNMP_SEC_LEVEL_AUTHPRIV
2885
0
        && (netsnmp_oid_equals(user->privProtocol, user->privProtocolLen,
2886
0
                             usmNoPrivProtocol,
2887
0
                             OID_LENGTH(usmNoPrivProtocol)) ==
2888
0
            0)) {
2889
0
        DEBUGMSGTL(("usm", "Level: %d\n", level));
2890
0
        DEBUGMSGTL(("usm", "User (%s) Auth Protocol: ", user->name));
2891
0
        DEBUGMSGOID(("usm", user->authProtocol, user->authProtocolLen));
2892
0
        DEBUGMSG(("usm", ", User Priv Protocol: "));
2893
0
        DEBUGMSGOID(("usm", user->privProtocol, user->privProtocolLen));
2894
0
        DEBUGMSG(("usm", "\n"));
2895
0
        return 1;
2896
0
    }
2897
0
    if ((level == SNMP_SEC_LEVEL_AUTHPRIV
2898
0
         || level == SNMP_SEC_LEVEL_AUTHNOPRIV)
2899
0
        &&
2900
0
        (netsnmp_oid_equals
2901
0
         (user->authProtocol, user->authProtocolLen, usmNoAuthProtocol,
2902
0
          OID_LENGTH(usmNoAuthProtocol)) == 0)) {
2903
0
        DEBUGMSGTL(("usm", "Level: %d\n", level));
2904
0
        DEBUGMSGTL(("usm", "User (%s) Auth Protocol: ", user->name));
2905
0
        DEBUGMSGOID(("usm", user->authProtocol, user->authProtocolLen));
2906
0
        DEBUGMSG(("usm", ", User Priv Protocol: "));
2907
0
        DEBUGMSGOID(("usm", user->privProtocol, user->privProtocolLen));
2908
0
        DEBUGMSG(("usm", "\n"));
2909
0
        return 1;
2910
0
    }
2911
2912
0
    return 0;
2913
0
}                               /* end usm_check_secLevel() */
2914
2915
/*******************************************************************-o-******
2916
 * usm_process_in_msg
2917
 *
2918
 * Parameters:
2919
 *  (See list below...)
2920
 *      
2921
 * Returns:
2922
 *  SNMPERR_SUCCESS     On success.
2923
 *  SNMPERR_USM_AUTHENTICATIONFAILURE
2924
 *  SNMPERR_USM_DECRYPTIONERROR
2925
 *  SNMPERR_USM_GENERICERROR
2926
 *  SNMPERR_USM_PARSEERROR
2927
 *  SNMPERR_USM_UNKNOWNENGINEID
2928
 *  SNMPERR_USM_PARSEERROR
2929
 *  SNMPERR_USM_UNKNOWNSECURITYNAME
2930
 *  SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL
2931
 *
2932
 *
2933
 * ASSUMES size of decrypt_buf will always be >= size of encrypted sPDU.
2934
 */
2935
static int
2936
usm_process_in_msg(int msgProcModel,    /* (UNUSED) */
2937
                   size_t maxMsgSize,   /* IN     - Used to calc maxSizeResponse.  */
2938
                   u_char * secParams,  /* IN     - BER encoded securityParameters. */
2939
                   int secModel,        /* (UNUSED) */
2940
                   int secLevel,        /* IN     - AuthNoPriv, authPriv etc.      */
2941
                   u_char * wholeMsg,   /* IN     - Original v3 message.           */
2942
                   size_t wholeMsgLen,  /* IN     - Msg length.                    */
2943
                   u_char * secEngineID,        /* OUT    - Pointer snmpEngineID.          */
2944
                   size_t * secEngineIDLen,     /* IN/OUT - Len available, len returned.   */
2945
                   /*
2946
                    * NOTE: Memory provided by caller.      
2947
                    */
2948
                   char *secName,       /* OUT    - Pointer to securityName.       */
2949
                   size_t * secNameLen, /* IN/OUT - Len available, len returned.   */
2950
                   u_char ** scopedPdu, /* OUT    - Pointer to plaintext scopedPdu. */
2951
                   size_t * scopedPduLen,       /* IN/OUT - Len available, len returned.   */
2952
                   size_t * maxSizeResponse,    /* OUT    - Max size of Response PDU.      */
2953
                   void **secStateRf,   /* OUT    - Ref to security state.         */
2954
                   netsnmp_session * sess,      /* IN     - session which got the message  */
2955
                   u_char msg_flags)
2956
0
{                               /* IN     - v3 Message flags.              */
2957
0
    size_t          remaining = wholeMsgLen - (u_int)
2958
0
        ((u_long) * secParams - (u_long) * wholeMsg);
2959
0
    u_int           boots_uint;
2960
0
    u_int           time_uint;
2961
0
#ifdef HAVE_AES
2962
0
    u_int           net_boots, net_time;
2963
0
#endif
2964
0
#ifndef NETSNMP_DISABLE_DES
2965
0
    int             i;
2966
0
#endif
2967
0
    u_char          signature[USM_MAX_AUTHSIZE];
2968
0
    size_t          signature_length = USM_MAX_AUTHSIZE;
2969
0
    u_char          salt[BYTESIZE(USM_MAX_SALT_LENGTH)];
2970
0
    size_t          salt_length = BYTESIZE(USM_MAX_SALT_LENGTH);
2971
0
    u_char          iv[BYTESIZE(USM_MAX_SALT_LENGTH)];
2972
0
    u_int           iv_length = BYTESIZE(USM_MAX_SALT_LENGTH);
2973
0
    u_char         *data_ptr;
2974
0
    u_char         *value_ptr;
2975
0
    u_char          type_value;
2976
0
    u_char         *end_of_overhead = NULL;
2977
0
    int             error;
2978
0
    int             rc = 0;
2979
0
    struct usmStateReference **secStateRef =
2980
0
        (struct usmStateReference **) secStateRf;
2981
2982
0
    struct usmUser *user;
2983
2984
2985
0
    DEBUGMSGTL(("usm", "USM processing begun...\n"));
2986
2987
0
    netsnmp_assert(secStateRef);
2988
2989
0
    usm_free_usmStateReference(*secStateRef);
2990
0
    *secStateRef = usm_malloc_usmStateReference();
2991
0
    if (*secStateRef == NULL) {
2992
0
        DEBUGMSGTL(("usm", "Out of memory.\n"));
2993
0
        return SNMPERR_USM_GENERICERROR;
2994
0
    }
2995
2996
    /*
2997
     * Make sure the *secParms is an OCTET STRING.
2998
     * Extract the user name, engine ID, and security level.
2999
     */
3000
0
    if ((rc = usm_parse_security_parameters(secParams, remaining,
3001
0
                                            secEngineID, secEngineIDLen,
3002
0
                                            &boots_uint, &time_uint,
3003
0
                                            secName, secNameLen,
3004
0
                                            signature, &signature_length,
3005
0
                                            salt, &salt_length,
3006
0
                                            &data_ptr)) < 0) {
3007
0
        DEBUGMSGTL(("usm", "Parsing failed (rc %d).\n", rc));
3008
0
        if (rc == -2) {
3009
            /*
3010
             * This indicates a decryptionError.  
3011
             */
3012
0
            snmp_increment_statistic(STAT_USMSTATSDECRYPTIONERRORS);
3013
0
            error = SNMPERR_USM_DECRYPTIONERROR;
3014
0
        } else {
3015
0
            snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
3016
0
            error = SNMPERR_USM_PARSEERROR;
3017
0
        }
3018
0
        goto err;
3019
0
    }
3020
3021
    /*
3022
     * RFC 2574 section 8.3.2
3023
     * 1)  If the privParameters field is not an 8-octet OCTET STRING,
3024
     * then an error indication (decryptionError) is returned to the
3025
     * calling module.
3026
     */
3027
0
    if ((secLevel == SNMP_SEC_LEVEL_AUTHPRIV) && (salt_length != 8)) {
3028
0
        snmp_increment_statistic(STAT_USMSTATSDECRYPTIONERRORS);
3029
0
        error = SNMPERR_USM_DECRYPTIONERROR;
3030
0
        goto err;
3031
0
    }
3032
3033
0
    if (secLevel != SNMP_SEC_LEVEL_AUTHPRIV) {
3034
        /*
3035
         * pull these out now so reports can use them 
3036
         */
3037
0
        *scopedPdu = data_ptr;
3038
0
        *scopedPduLen = wholeMsgLen - (data_ptr - wholeMsg);
3039
0
        end_of_overhead = data_ptr;
3040
0
    }
3041
3042
    /*
3043
     * Cache the name, engine ID, and security level,
3044
     * * per step 2 (section 3.2)
3045
     */
3046
0
    if (usm_set_usmStateReference_name
3047
0
        (*secStateRef, secName, *secNameLen) == -1) {
3048
0
        DEBUGMSGTL(("usm", "%s\n", "Couldn't cache name."));
3049
0
        error = SNMPERR_USM_GENERICERROR;
3050
0
        goto err;
3051
0
    }
3052
3053
0
    if (usm_set_usmStateReference_engine_id
3054
0
        (*secStateRef, secEngineID, *secEngineIDLen) == -1) {
3055
0
        DEBUGMSGTL(("usm", "%s\n", "Couldn't cache engine id."));
3056
0
        error = SNMPERR_USM_GENERICERROR;
3057
0
        goto err;
3058
0
    }
3059
3060
0
    if (usm_set_usmStateReference_sec_level(*secStateRef, secLevel) ==
3061
0
        -1) {
3062
0
        DEBUGMSGTL(("usm", "%s\n", "Couldn't cache security level."));
3063
0
        error = SNMPERR_USM_GENERICERROR;
3064
0
        goto err;
3065
0
    }
3066
3067
    /*
3068
     * Locate the engine ID record.
3069
     * If it is unknown, then either create one or note this as an error.
3070
     */
3071
0
    if ((sess && (sess->isAuthoritative == SNMP_SESS_AUTHORITATIVE ||
3072
0
                  (sess->isAuthoritative == SNMP_SESS_UNKNOWNAUTH &&
3073
0
                   (msg_flags & SNMP_MSG_FLAG_RPRT_BIT)))) ||
3074
0
        (!sess && (msg_flags & SNMP_MSG_FLAG_RPRT_BIT))) {
3075
0
        if (ISENGINEKNOWN(secEngineID, *secEngineIDLen) == FALSE) {
3076
0
            DEBUGMSGTL(("usm", "Unknown Engine ID.\n"));
3077
0
            snmp_increment_statistic(STAT_USMSTATSUNKNOWNENGINEIDS);
3078
0
            error = SNMPERR_USM_UNKNOWNENGINEID;
3079
0
            goto err;
3080
0
        }
3081
0
    } else {
3082
0
        if (ENSURE_ENGINE_RECORD(secEngineID, *secEngineIDLen)
3083
0
            != SNMPERR_SUCCESS) {
3084
0
            DEBUGMSGTL(("usm", "%s\n", "Couldn't ensure engine record."));
3085
0
            error = SNMPERR_USM_GENERICERROR;
3086
0
            goto err;
3087
0
        }
3088
3089
0
    }
3090
3091
3092
    /*
3093
     * Locate the User record.
3094
     * If the user/engine ID is unknown, report this as an error.
3095
     */
3096
0
    if (sess && sess->sessUser)
3097
0
        user = sess->sessUser;
3098
0
    else
3099
0
        user = usm_get_user_from_list(secEngineID, *secEngineIDLen,
3100
0
                                       secName, *secNameLen, userList,
3101
0
                                       (((sess && sess->isAuthoritative ==
3102
0
                                          SNMP_SESS_AUTHORITATIVE) ||
3103
0
                                         (!sess)) ? 0 : 1));
3104
3105
0
    if (user == NULL) {
3106
0
        DEBUGMSGTL(("usm", "Unknown User(%s)\n", secName));
3107
0
        snmp_increment_statistic(STAT_USMSTATSUNKNOWNUSERNAMES);
3108
0
        error = SNMPERR_USM_UNKNOWNSECURITYNAME;
3109
0
        goto err;
3110
0
    }
3111
3112
    /* ensure the user is active */
3113
0
    if (user->userStatus != RS_ACTIVE) {
3114
0
        DEBUGMSGTL(("usm", "Attempt to use an inactive user.\n"));
3115
0
        error = SNMPERR_USM_UNKNOWNSECURITYNAME;
3116
0
        goto err;
3117
0
    }
3118
3119
    /*
3120
     * Make sure the security level is appropriate.
3121
     */
3122
3123
0
    rc = usm_check_secLevel(secLevel, user);
3124
0
    if (1 == rc) {
3125
0
        DEBUGMSGTL(("usm", "Unsupported Security Level (%d).\n",
3126
0
                    secLevel));
3127
0
        snmp_increment_statistic(STAT_USMSTATSUNSUPPORTEDSECLEVELS);
3128
0
        error = SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL;
3129
0
        goto err;
3130
0
    } else if (rc != 0) {
3131
0
        DEBUGMSGTL(("usm", "Unknown issue.\n"));
3132
0
        error = SNMPERR_USM_GENERICERROR;
3133
0
        goto err;
3134
0
    }
3135
3136
    /*
3137
     * Check the authentication credentials of the message.
3138
     */
3139
0
    if (secLevel == SNMP_SEC_LEVEL_AUTHNOPRIV
3140
0
        || secLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
3141
0
        if (sc_check_keyed_hash(user->authProtocol, user->authProtocolLen,
3142
0
                                user->authKey, user->authKeyLen,
3143
0
                                wholeMsg, wholeMsgLen,
3144
0
                                signature, signature_length)
3145
0
            != SNMP_ERR_NOERROR) {
3146
0
            DEBUGMSGTL(("usm", "Verification failed.\n"));
3147
0
            snmp_increment_statistic(STAT_USMSTATSWRONGDIGESTS);
3148
0
      snmp_log(LOG_WARNING, "Authentication failed for %s\n",
3149
0
        user->name);
3150
0
            error = SNMPERR_USM_AUTHENTICATIONFAILURE;
3151
0
            goto err;
3152
0
        }
3153
3154
0
        DEBUGMSGTL(("usm", "Verification succeeded.\n"));
3155
0
    }
3156
3157
3158
    /*
3159
     * Steps 10-11  user is already set - relocated before timeliness 
3160
     * check in case it fails - still save user data for response.
3161
     *
3162
     * Cache the keys and protocol oids, per step 11 (s3.2).
3163
     */
3164
0
    if (usm_set_usmStateReference_auth_protocol(*secStateRef,
3165
0
                                                user->authProtocol,
3166
0
                                                user->
3167
0
                                                authProtocolLen) == -1) {
3168
0
        DEBUGMSGTL(("usm", "%s\n",
3169
0
                    "Couldn't cache authentication protocol."));
3170
0
        error = SNMPERR_USM_GENERICERROR;
3171
0
        goto err;
3172
0
    }
3173
3174
0
    if (usm_set_usmStateReference_auth_key(*secStateRef,
3175
0
                                           user->authKey,
3176
0
                                           user->authKeyLen) == -1) {
3177
0
        DEBUGMSGTL(("usm", "%s\n",
3178
0
                    "Couldn't cache authentication key."));
3179
0
        error = SNMPERR_USM_GENERICERROR;
3180
0
        goto err;
3181
0
    }
3182
3183
0
    if (usm_set_usmStateReference_priv_protocol(*secStateRef,
3184
0
                                                user->privProtocol,
3185
0
                                                user->
3186
0
                                                privProtocolLen) == -1) {
3187
0
        DEBUGMSGTL(("usm", "%s\n",
3188
0
                    "Couldn't cache privacy protocol."));
3189
0
        error = SNMPERR_USM_GENERICERROR;
3190
0
        goto err;
3191
0
    }
3192
3193
0
    if (usm_set_usmStateReference_priv_key(*secStateRef,
3194
0
                                           user->privKey,
3195
0
                                           user->privKeyLen) == -1) {
3196
0
        DEBUGMSGTL(("usm", "%s\n", "Couldn't cache privacy key."));
3197
0
        error = SNMPERR_USM_GENERICERROR;
3198
0
        goto err;
3199
0
    }
3200
3201
3202
    /*
3203
     * Perform the timeliness/time manager functions.
3204
     */
3205
0
    if (secLevel == SNMP_SEC_LEVEL_AUTHNOPRIV
3206
0
        || secLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
3207
0
        if (usm_check_and_update_timeliness(secEngineID, *secEngineIDLen,
3208
0
                                            boots_uint, time_uint,
3209
0
                                            &error) == -1) {
3210
0
            goto err;
3211
0
        }
3212
0
    }
3213
0
#ifdef              LCD_TIME_SYNC_OPT
3214
    /*
3215
     * Cache the unauthenticated time to use in case we don't have
3216
     * anything better - this guess will be no worse than (0,0)
3217
     * that we normally use.
3218
     */
3219
0
    else {
3220
0
        set_enginetime(secEngineID, *secEngineIDLen,
3221
0
                       boots_uint, time_uint, FALSE);
3222
0
    }
3223
0
#endif                          /* LCD_TIME_SYNC_OPT */
3224
3225
3226
    /*
3227
     * If needed, decrypt the scoped PDU.
3228
     */
3229
0
    if (secLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
3230
0
        int priv_type = sc_get_privtype(user->privProtocol,
3231
0
                                        user->privProtocolLen);
3232
0
        remaining = wholeMsgLen - (data_ptr - wholeMsg);
3233
3234
0
        if ((value_ptr = asn_parse_sequence(data_ptr, &remaining,
3235
0
                                            &type_value,
3236
0
                                            (ASN_UNIVERSAL | ASN_PRIMITIVE
3237
0
                                             | ASN_OCTET_STR),
3238
0
                                            "encrypted sPDU")) == NULL) {
3239
0
            DEBUGMSGTL(("usm", "%s\n",
3240
0
                        "Failed while parsing encrypted sPDU."));
3241
0
            snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
3242
0
            usm_free_usmStateReference(*secStateRef);
3243
0
            *secStateRef = NULL;
3244
0
            error = SNMPERR_USM_PARSEERROR;
3245
0
            goto err;
3246
0
        }
3247
3248
0
#ifndef NETSNMP_DISABLE_DES
3249
0
        if (USM_CREATE_USER_PRIV_DES == (priv_type & USM_PRIV_MASK_ALG)) {
3250
            /*
3251
             * From RFC2574:
3252
             * 
3253
             * "Before decryption, the encrypted data length is verified.
3254
             * If the length of the OCTET STRING to be decrypted is not
3255
             * an integral multiple of 8 octets, the decryption process
3256
             * is halted and an appropriate exception noted."  
3257
             */
3258
3259
0
            if (remaining % 8 != 0) {
3260
0
                DEBUGMSGTL(("usm",
3261
0
                            "Ciphertext is %lu bytes, not an integer multiple of 8 (rem %lu)\n",
3262
0
                            (unsigned long)remaining, (unsigned long)remaining % 8));
3263
0
                snmp_increment_statistic(STAT_USMSTATSDECRYPTIONERRORS);
3264
0
                usm_free_usmStateReference(*secStateRef);
3265
0
                *secStateRef = NULL;
3266
0
                error = SNMPERR_USM_DECRYPTIONERROR;
3267
0
                goto err;
3268
0
            }
3269
3270
0
            end_of_overhead = value_ptr;
3271
3272
0
            if ( !user->privKey ) {
3273
0
                DEBUGMSGTL(("usm", "No privacy pass phrase for %s\n", user->secName));
3274
0
                snmp_increment_statistic(STAT_USMSTATSDECRYPTIONERRORS);
3275
0
                usm_free_usmStateReference(*secStateRef);
3276
0
                *secStateRef = NULL;
3277
0
                error = SNMPERR_USM_DECRYPTIONERROR;
3278
0
                goto err;
3279
0
            }
3280
3281
            /*
3282
             * XOR the salt with the last (iv_length) bytes
3283
             * of the priv_key to obtain the IV.
3284
             */
3285
0
            iv_length = BYTESIZE(USM_DES_SALT_LENGTH);
3286
0
            for (i = 0; i < (int) iv_length; i++)
3287
0
                iv[i] = salt[i] ^ user->privKey[iv_length + i];
3288
0
        }
3289
0
#endif
3290
0
#ifdef HAVE_AES
3291
0
        if (USM_CREATE_USER_PRIV_AES == (priv_type & USM_PRIV_MASK_ALG)) {
3292
0
            iv_length = BYTESIZE(USM_AES_SALT_LENGTH);
3293
0
            net_boots = ntohl(boots_uint);
3294
0
            net_time = ntohl(time_uint);
3295
0
            memcpy(iv, &net_boots, 4);
3296
0
            memcpy(iv+4, &net_time, 4);
3297
0
            memcpy(iv+8, salt, salt_length);
3298
0
        }
3299
0
#endif
3300
3301
#ifdef NETSNMP_ENABLE_TESTING_CODE
3302
        if (debug_is_token_registered("usm/dump") == SNMPERR_SUCCESS) {
3303
            dump_chunk("usm/dump", "Cypher Text", value_ptr, remaining);
3304
            dump_chunk("usm/dump", "salt + Encrypted form:",
3305
                       salt, salt_length);
3306
            dump_chunk("usm/dump", "IV + Encrypted form:", iv, iv_length);
3307
        }
3308
#endif
3309
0
        if (sc_decrypt(user->privProtocol, user->privProtocolLen,
3310
0
                       user->privKey, user->privKeyLen,
3311
0
                       iv, iv_length,
3312
0
                       value_ptr, remaining, *scopedPdu, scopedPduLen)
3313
0
            != SNMP_ERR_NOERROR) {
3314
0
            DEBUGMSGTL(("usm", "%s\n", "Failed decryption."));
3315
0
            snmp_increment_statistic(STAT_USMSTATSDECRYPTIONERRORS);
3316
0
            error = SNMPERR_USM_DECRYPTIONERROR;
3317
0
            goto err;
3318
0
        }
3319
#ifdef NETSNMP_ENABLE_TESTING_CODE
3320
        if (debug_is_token_registered("usm/dump") == SNMPERR_SUCCESS) {
3321
            dump_chunk("usm/dump", "Decrypted chunk:",
3322
                       *scopedPdu, *scopedPduLen);
3323
        }
3324
#endif
3325
0
    }
3326
    /*
3327
     * sPDU is plaintext.
3328
     */
3329
0
    else {
3330
0
        *scopedPdu = data_ptr;
3331
0
        *scopedPduLen = wholeMsgLen - (data_ptr - wholeMsg);
3332
0
        end_of_overhead = data_ptr;
3333
3334
0
    }                           /* endif -- PDU decryption */
3335
3336
3337
    /*
3338
     * Calculate the biggest sPDU for the response (i.e., whole - ovrhd).
3339
     *
3340
     * FIX  Correct? 
3341
     */
3342
0
    *maxSizeResponse = maxMsgSize - (end_of_overhead - wholeMsg);
3343
3344
3345
0
    DEBUGMSGTL(("usm", "USM processing completed.\n"));
3346
3347
0
    return SNMPERR_SUCCESS;
3348
3349
0
err:
3350
0
    usm_free_usmStateReference(*secStateRef);
3351
0
    *secStateRef = NULL;
3352
0
    netsnmp_assert(error != SNMPERR_SUCCESS);
3353
0
    return error;
3354
0
}                               /* end usm_process_in_msg() */
3355
3356
static int
3357
usm_secmod_process_in_msg(struct snmp_secmod_incoming_params *parms)
3358
0
{
3359
0
    if (!parms)
3360
0
        return SNMPERR_GENERR;
3361
3362
0
    return usm_process_in_msg(parms->msgProcModel,
3363
0
                              parms->maxMsgSize,
3364
0
                              parms->secParams,
3365
0
                              parms->secModel,
3366
0
                              parms->secLevel,
3367
0
                              parms->wholeMsg,
3368
0
                              parms->wholeMsgLen,
3369
0
                              parms->secEngineID,
3370
0
                              parms->secEngineIDLen,
3371
0
                              parms->secName,
3372
0
                              parms->secNameLen,
3373
0
                              parms->scopedPdu,
3374
0
                              parms->scopedPduLen,
3375
0
                              parms->maxSizeResponse,
3376
0
                              parms->secStateRef,
3377
0
                              parms->sess, parms->msg_flags);
3378
0
}
3379
3380
static void
3381
usm_handle_report(struct session_list *slp,
3382
                  netsnmp_transport *transport, netsnmp_session *session,
3383
                  int result, netsnmp_pdu *pdu)
3384
0
{
3385
    /*
3386
     * handle reportable errors 
3387
     */
3388
3389
    /* this will get in our way */
3390
0
    usm_free_usmStateReference(pdu->securityStateRef);
3391
0
    pdu->securityStateRef = NULL;
3392
3393
0
    switch (result) {
3394
0
    case SNMPERR_USM_AUTHENTICATIONFAILURE:
3395
0
    {
3396
0
        int res = session->s_snmp_errno;
3397
0
        session->s_snmp_errno = result;
3398
0
        if (session->callback) {
3399
0
            session->callback(NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE,
3400
0
                              session, pdu->reqid, pdu,
3401
0
                              session->callback_magic);
3402
0
        }
3403
0
        session->s_snmp_errno = res;
3404
0
    }  
3405
0
    NETSNMP_FALLTHROUGH;
3406
0
    case SNMPERR_USM_UNKNOWNENGINEID:
3407
0
    case SNMPERR_USM_UNKNOWNSECURITYNAME:
3408
0
    case SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL:
3409
0
    case SNMPERR_USM_NOTINTIMEWINDOW:
3410
0
    case SNMPERR_USM_DECRYPTIONERROR:
3411
3412
0
        if (SNMP_CMD_CONFIRMED(pdu->command) ||
3413
0
            (pdu->command == 0
3414
0
             && (pdu->flags & SNMP_MSG_FLAG_RPRT_BIT))) {
3415
0
            netsnmp_pdu    *pdu2;
3416
0
            int             flags = pdu->flags;
3417
3418
0
            pdu->flags |= UCD_MSG_FLAG_FORCE_PDU_COPY;
3419
0
            pdu2 = snmp_clone_pdu(pdu);
3420
0
            pdu->flags = pdu2->flags = flags;
3421
0
            snmpv3_make_report(pdu2, result);
3422
0
            if (0 == snmp_sess_send(slp, pdu2)) {
3423
0
                snmp_free_pdu(pdu2);
3424
                /*
3425
                 * TODO: indicate error 
3426
                 */
3427
0
            }
3428
0
        }
3429
0
        break;
3430
0
    }       
3431
0
}
3432
3433
/** utility function to call netsnmp_extend_kul for a usmUser */
3434
int
3435
usm_extend_user_kul(struct usmUser *user, u_int privKeyBufSize)
3436
71
{
3437
71
    const netsnmp_priv_alg_info *pai;
3438
3439
71
    DEBUGMSGTL(("usm", "extending key\n"));
3440
3441
71
    if (NULL == user) {
3442
0
        DEBUGMSGTL(("usm", "null user!\n"));
3443
0
        return SNMPERR_GENERR;
3444
0
    }
3445
3446
71
    pai = sc_get_priv_alg_byoid(user->privProtocol, user->privProtocolLen);
3447
71
    if (NULL == pai) {
3448
0
        DEBUGMSGTL(("usm", "privProtocol lookup failed!\n"));
3449
0
        return SNMPERR_GENERR;
3450
0
    }
3451
3452
71
    return netsnmp_extend_kul(pai->proper_length, user->authProtocol,
3453
71
                              user->authProtocolLen, pai->type, user->engineID,
3454
71
                              user->engineIDLen, &user->privKey,
3455
71
                              &user->privKeyLen, privKeyBufSize);
3456
71
}
3457
3458
/* sets up initial default session parameters */
3459
static int
3460
usm_session_init(netsnmp_session *in_session, netsnmp_session *session)
3461
5.23k
{
3462
5.23k
    char *cp;
3463
5.23k
    size_t i;
3464
    
3465
5.23k
    if (in_session->securityAuthProtoLen > 0) {
3466
0
        session->securityAuthProto =
3467
0
            snmp_duplicate_objid(in_session->securityAuthProto,
3468
0
                                 in_session->securityAuthProtoLen);
3469
0
        if (session->securityAuthProto == NULL) {
3470
0
            in_session->s_snmp_errno = SNMPERR_MALLOC;
3471
0
            return SNMPERR_MALLOC;
3472
0
        }
3473
5.23k
    } else if (get_default_authtype(&i) != NULL) {
3474
5.23k
        session->securityAuthProto =
3475
5.23k
            snmp_duplicate_objid(get_default_authtype(NULL), i);
3476
5.23k
        session->securityAuthProtoLen = i;
3477
5.23k
    }
3478
3479
5.23k
    if (in_session->securityPrivProtoLen > 0) {
3480
0
        session->securityPrivProto =
3481
0
            snmp_duplicate_objid(in_session->securityPrivProto,
3482
0
                                 in_session->securityPrivProtoLen);
3483
0
        if (session->securityPrivProto == NULL) {
3484
0
            in_session->s_snmp_errno = SNMPERR_MALLOC;
3485
0
            return SNMPERR_MALLOC;
3486
0
        }
3487
5.23k
    } else if (get_default_privtype(&i) != NULL) {
3488
5.23k
        session->securityPrivProto =
3489
5.23k
            snmp_duplicate_objid(get_default_privtype(NULL), i);
3490
5.23k
        session->securityPrivProtoLen = i;
3491
5.23k
    }
3492
3493
5.23k
    if ((in_session->securityAuthKeyLen <= 0) &&
3494
5.23k
        ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 
3495
5.23k
             NETSNMP_DS_LIB_AUTHMASTERKEY)))) {
3496
0
        size_t buflen = sizeof(session->securityAuthKey);
3497
0
        u_char *tmpp = session->securityAuthKey;
3498
0
        session->securityAuthKeyLen = 0;
3499
        /* it will be a hex string */
3500
0
        if (!snmp_hex_to_binary(&tmpp, &buflen,
3501
0
                                &session->securityAuthKeyLen, 0, cp)) {
3502
0
            snmp_set_detail("error parsing authentication master key");
3503
0
            return SNMP_ERR_GENERR;
3504
0
        }
3505
5.23k
    } else if ((in_session->securityAuthKeyLen <= 0) &&
3506
5.23k
               ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 
3507
5.23k
                                            NETSNMP_DS_LIB_AUTHPASSPHRASE)) ||
3508
5.23k
                (cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 
3509
5.23k
                                            NETSNMP_DS_LIB_PASSPHRASE)))) {
3510
0
        session->securityAuthKeyLen = USM_AUTH_KU_LEN;
3511
0
        if (generate_Ku(session->securityAuthProto,
3512
0
                        session->securityAuthProtoLen,
3513
0
                        (u_char *) cp, strlen(cp),
3514
0
                        session->securityAuthKey,
3515
0
                        &session->securityAuthKeyLen) != SNMPERR_SUCCESS) {
3516
0
            snmp_set_detail
3517
0
                ("Error generating a key (Ku) from the supplied authentication pass phrase.");
3518
0
            return SNMP_ERR_GENERR;
3519
0
        }
3520
0
    }
3521
3522
    
3523
5.23k
    if ((in_session->securityPrivKeyLen <= 0) &&
3524
5.23k
        ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 
3525
5.23k
             NETSNMP_DS_LIB_PRIVMASTERKEY)))) {
3526
0
        size_t buflen = sizeof(session->securityPrivKey);
3527
0
        u_char *tmpp = session->securityPrivKey;
3528
0
        session->securityPrivKeyLen = 0;
3529
        /* it will be a hex string */
3530
0
        if (!snmp_hex_to_binary(&tmpp, &buflen,
3531
0
                                &session->securityPrivKeyLen, 0, cp)) {
3532
0
            snmp_set_detail("error parsing encryption master key");
3533
0
            return SNMP_ERR_GENERR;
3534
0
        }
3535
5.23k
    } else if ((in_session->securityPrivKeyLen <= 0) &&
3536
5.23k
               ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 
3537
5.23k
                                            NETSNMP_DS_LIB_PRIVPASSPHRASE)) ||
3538
5.23k
                (cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 
3539
5.23k
                                            NETSNMP_DS_LIB_PASSPHRASE)))) {
3540
0
        session->securityPrivKeyLen = USM_PRIV_KU_LEN;
3541
0
        if (generate_Ku(session->securityAuthProto,
3542
0
                        session->securityAuthProtoLen,
3543
0
                        (u_char *) cp, strlen(cp),
3544
0
                        session->securityPrivKey,
3545
0
                        &session->securityPrivKeyLen) != SNMPERR_SUCCESS) {
3546
0
            snmp_set_detail
3547
0
                ("Error generating a key (Ku) from the supplied privacy pass phrase.");
3548
0
            return SNMP_ERR_GENERR;
3549
0
        }
3550
0
    }
3551
3552
5.23k
    return SNMPERR_SUCCESS;
3553
5.23k
}
3554
3555
static int usm_build_user(struct usmUser **result,
3556
                          const netsnmp_session *session)
3557
0
{
3558
0
    struct usmUser *user;
3559
3560
0
    DEBUGMSGTL(("usm", "Building user %s...\n", session->securityName));
3561
    /*
3562
     * user doesn't exist so we create and add it
3563
     */
3564
0
    user = calloc(1, sizeof(struct usmUser));
3565
0
    if (user == NULL)
3566
0
        goto err;
3567
3568
    /*
3569
     * copy in the securityName
3570
     */
3571
0
    if (session->securityName) {
3572
0
        user->name = strdup(session->securityName);
3573
0
        user->secName = strdup(session->securityName);
3574
0
        if (user->name == NULL || user->secName == NULL)
3575
0
            goto err;
3576
0
    }
3577
3578
    /*
3579
     * copy in the engineID
3580
     */
3581
0
    user->engineID = netsnmp_memdup(session->securityEngineID,
3582
0
                                    session->securityEngineIDLen);
3583
0
    if (session->securityEngineID && !user->engineID)
3584
0
        goto err;
3585
0
    user->engineIDLen = session->securityEngineIDLen;
3586
0
    *result = user;
3587
0
    return SNMPERR_SUCCESS;
3588
3589
0
err:
3590
0
    usm_free_user(user);
3591
0
    return SNMPERR_GENERR;
3592
0
}
3593
3594
/*
3595
 * usm_create_user_from_session(netsnmp_session *session):
3596
 * 
3597
 * creates a user in the usm table from the information in a session.
3598
 * If the user already exists, it is updated with the current
3599
 * information from the session, also update boot/time set
3600
 * 
3601
 * Parameters:
3602
 * session -- IN: pointer to the session to use when creating the user.
3603
 * 
3604
 * Returns:
3605
 * SNMPERR_SUCCESS
3606
 * SNMPERR_GENERR 
3607
 */
3608
int
3609
usm_create_user_from_session(netsnmp_session * session)
3610
1.83k
{
3611
1.83k
    struct usmUser *user;
3612
1.83k
    int             user_just_created = 0;
3613
1.83k
    char *cp;
3614
3615
    /*
3616
     * If boot/time supplied set it for this engineID. Do it from hook when
3617
     * creating user in case probe was sent by other means for example
3618
     * asynchronously.
3619
     */
3620
1.83k
    if (!(session->flags & SNMP_FLAGS_TIME_CREATED) &&
3621
1.83k
        (session->engineBoots || session->engineTime)) {
3622
0
        set_enginetime(session->securityEngineID,
3623
0
                       session->securityEngineIDLen,
3624
0
                       session->engineBoots, session->engineTime,
3625
0
                       TRUE);
3626
0
        session->flags |= SNMP_FLAGS_TIME_CREATED;
3627
0
    }
3628
3629
    /*
3630
     * - don't create-another/copy-into user for this session by default
3631
     * - bail now (no error) if we don't have an engineID
3632
     */
3633
1.83k
    if (SNMP_FLAGS_USER_CREATED == (session->flags & SNMP_FLAGS_USER_CREATED) ||
3634
1.83k
        session->securityModel != SNMP_SEC_MODEL_USM ||
3635
1.83k
        session->version != SNMP_VERSION_3 ||
3636
1.83k
        session->securityNameLen == 0 ||
3637
1.83k
        session->securityEngineIDLen == 0)
3638
1.83k
        return SNMPERR_SUCCESS;
3639
3640
0
    DEBUGMSGTL(("usm", "no flag defined...  continuing\n"));
3641
0
    session->flags |= SNMP_FLAGS_USER_CREATED;
3642
3643
    /*
3644
     * now that we have the engineID, create an entry in the USM list
3645
     * for this user using the information in the session 
3646
     */
3647
0
    if ((session->flags & SNMP_FLAGS_SESSION_USER) == 0)
3648
0
        user = usm_get_user_from_list(session->securityEngineID,
3649
0
                                      session->securityEngineIDLen,
3650
0
                                      session->securityName,
3651
0
                                      session->securityNameLen,
3652
0
                                      usm_get_userList(), 0);
3653
0
    else
3654
0
        user = NULL;
3655
3656
3657
0
    if (user) {
3658
0
        DEBUGMSGTL(("usm", "user exists x=%p\n", user));
3659
0
    } else {
3660
0
        if (usm_build_user(&user, session) != SNMPERR_SUCCESS)
3661
0
            return SNMPERR_GENERR;
3662
0
        user_just_created = 1;
3663
0
    }
3664
3665
    /*
3666
     * copy the auth protocol 
3667
     */
3668
0
    if (user->authProtocol == NULL && session->securityAuthProto != NULL) {
3669
0
        SNMP_FREE(user->authProtocol);
3670
0
        user->authProtocol =
3671
0
            snmp_duplicate_objid(session->securityAuthProto,
3672
0
                                 session->securityAuthProtoLen);
3673
0
        if (user->authProtocol == NULL) {
3674
0
            usm_free_user(user);
3675
0
            return SNMPERR_GENERR;
3676
0
        }
3677
0
        user->authProtocolLen = session->securityAuthProtoLen;
3678
0
    }
3679
3680
    /*
3681
     * copy the priv protocol 
3682
     */
3683
0
    if (user->privProtocol == NULL && session->securityPrivProto != NULL) {
3684
0
        SNMP_FREE(user->privProtocol);
3685
0
        user->privProtocol =
3686
0
            snmp_duplicate_objid(session->securityPrivProto,
3687
0
                                 session->securityPrivProtoLen);
3688
0
        if (user->privProtocol == NULL) {
3689
0
            usm_free_user(user);
3690
0
            return SNMPERR_GENERR;
3691
0
        }
3692
0
        user->privProtocolLen = session->securityPrivProtoLen;
3693
0
    }
3694
3695
    /*
3696
     * copy in the authentication Key.  If not localized, localize it 
3697
     */
3698
0
    if (user->authKey == NULL) {
3699
0
        if (session->securityAuthLocalKey != NULL
3700
0
            && session->securityAuthLocalKeyLen != 0) {
3701
            /* already localized key passed in.  use it */
3702
0
            SNMP_FREE(user->authKey);
3703
0
            user->authKey = netsnmp_memdup(session->securityAuthLocalKey,
3704
0
                                           session->securityAuthLocalKeyLen);
3705
0
            if (!user->authKey) {
3706
0
                usm_free_user(user);
3707
0
                return SNMPERR_GENERR;
3708
0
            }
3709
0
            user->authKeyLen = session->securityAuthLocalKeyLen;
3710
0
        } else if (session->securityAuthKeyLen != 0) {
3711
0
            SNMP_FREE(user->authKey);
3712
0
            user->authKey = calloc(1, USM_LENGTH_KU_HASHBLOCK);
3713
0
            user->authKeyLen = USM_LENGTH_KU_HASHBLOCK;
3714
0
            if ((user->authKey == NULL) ||
3715
0
                generate_kul(user->authProtocol, user->authProtocolLen,
3716
0
                             user->engineID, user->engineIDLen,
3717
0
                             session->securityAuthKey,
3718
0
                             session->securityAuthKeyLen, user->authKey,
3719
0
                             &user->authKeyLen) != SNMPERR_SUCCESS) {
3720
0
                usm_free_user(user);
3721
0
                return SNMPERR_GENERR;
3722
0
            }
3723
0
        } else if ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 
3724
0
                                               NETSNMP_DS_LIB_AUTHLOCALIZEDKEY))) {
3725
0
            size_t buflen = USM_AUTH_KU_LEN;
3726
0
            SNMP_FREE(user->authKey);
3727
0
            user->authKey = (u_char *)malloc(buflen); /* max length needed */
3728
0
            user->authKeyLen = 0;
3729
            /* it will be a hex string */
3730
0
            if ((NULL == user->authKey) ||
3731
0
                !snmp_hex_to_binary(&user->authKey, &buflen, &user->authKeyLen,
3732
0
                                    0, cp)) {
3733
0
                usm_free_user(user);
3734
0
                return SNMPERR_GENERR;
3735
0
            }
3736
0
        }
3737
0
    }
3738
3739
    /*
3740
     * copy in the privacy Key.  If not localized, localize it 
3741
     */
3742
0
    if (user->privKey == NULL) {
3743
        /** save buffer size in case we need to extend key */
3744
0
        int keyBufSize = USM_PRIV_KU_LEN;
3745
3746
0
        DEBUGMSGTL(("usm", "copying privKey\n"));
3747
0
        if (session->securityPrivLocalKey != NULL
3748
0
            && session->securityPrivLocalKeyLen != 0) {
3749
            /* already localized key passed in.  use it */
3750
0
            SNMP_FREE(user->privKey);
3751
0
            user->privKey = netsnmp_memdup(session->securityPrivLocalKey,
3752
0
                                           session->securityPrivLocalKeyLen);
3753
0
            if (!user->privKey) {
3754
0
                usm_free_user(user);
3755
0
                return SNMPERR_GENERR;
3756
0
            }
3757
0
            keyBufSize = user->privKeyLen = session->securityPrivLocalKeyLen;
3758
0
        } else if (session->securityPrivKeyLen != 0) {
3759
0
            SNMP_FREE(user->privKey);
3760
0
            user->privKey = calloc(1, keyBufSize);
3761
0
            user->privKeyLen = keyBufSize;
3762
0
            if ((user->privKey == NULL) ||
3763
0
                generate_kul(user->authProtocol, user->authProtocolLen,
3764
0
                             user->engineID, user->engineIDLen,
3765
0
                             session->securityPrivKey,
3766
0
                             session->securityPrivKeyLen, user->privKey,
3767
0
                             &user->privKeyLen) != SNMPERR_SUCCESS) {
3768
0
                usm_free_user(user);
3769
0
                return SNMPERR_GENERR;
3770
0
            }
3771
0
        } else if ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 
3772
0
                                               NETSNMP_DS_LIB_PRIVLOCALIZEDKEY))) {
3773
0
            size_t buflen = keyBufSize;
3774
0
            user->privKey = (u_char *)malloc(buflen); /* max length needed */
3775
0
            user->privKeyLen = 0;
3776
            /* it will be a hex string */
3777
0
            if ((NULL == user->privKey) ||
3778
0
                !snmp_hex_to_binary(&user->privKey, &buflen, &user->privKeyLen,
3779
0
                                    0, cp)) {
3780
0
                usm_free_user(user);
3781
0
                return SNMPERR_GENERR;
3782
0
            }
3783
0
        }
3784
0
        if (usm_extend_user_kul(user, keyBufSize) != SNMPERR_SUCCESS) {
3785
0
            usm_free_user(user);
3786
0
            return SNMPERR_GENERR;
3787
0
        }
3788
0
    }
3789
3790
0
    if (user_just_created) {
3791
        /*
3792
         * add the user into the database 
3793
         */
3794
0
        user->userStatus = RS_ACTIVE;
3795
0
        user->userStorageType = ST_READONLY;
3796
3797
0
        if (session->flags & SNMP_FLAGS_SESSION_USER) {
3798
0
            if (session->sessUser)
3799
0
                usm_free_user(session->sessUser);
3800
0
            session->sessUser = user;
3801
0
        } else {
3802
0
            usm_add_user(user);
3803
0
        }
3804
0
    }
3805
0
    DEBUGMSGTL(("9:usm", "user created and stored in %s\n", session->flags &
3806
0
                SNMP_FLAGS_SESSION_USER ? "session" : "local store"));
3807
3808
0
    return SNMPERR_SUCCESS;
3809
3810
3811
0
}
3812
3813
/* A wrapper around the hook */
3814
static int
3815
usm_create_user_from_session_hook(struct session_list *slp,
3816
                                  netsnmp_session *session)
3817
0
{
3818
0
    DEBUGMSGTL(("usm", "potentially bootstrapping the USM table from session data\n"));
3819
0
    return usm_create_user_from_session(session);
3820
0
}
3821
3822
static int
3823
usm_build_probe_pdu(netsnmp_pdu **pdu, struct usmUser **sessUser)
3824
0
{
3825
0
    struct usmUser *user;
3826
3827
    /*
3828
     * create the pdu 
3829
     */
3830
0
    if (!pdu)
3831
0
        return -1;
3832
0
    *pdu = snmpv3_probe_usm_pdu_create();
3833
0
    if (!(*pdu))
3834
0
        return -1;
3835
3836
    /*
3837
     * create the empty user 
3838
     */
3839
0
    if (sessUser && *sessUser)
3840
0
        user = *sessUser;
3841
0
    else
3842
0
        user = usm_get_user2(NULL, 0, (*pdu)->securityName,
3843
0
                         (*pdu)->securityNameLen);
3844
0
    if (user == NULL) {
3845
0
        user = calloc(1, sizeof(struct usmUser));
3846
0
        if (user == NULL) {
3847
0
            snmp_free_pdu(*pdu);
3848
0
            *pdu = (netsnmp_pdu *) NULL;
3849
0
            return -1;
3850
0
        }
3851
0
        user->name = strdup((*pdu)->securityName);
3852
0
        user->secName = strdup((*pdu)->securityName);
3853
0
        user->authProtocolLen = OID_LENGTH(usmNoAuthProtocol);
3854
0
        user->authProtocol =
3855
0
            snmp_duplicate_objid(usmNoAuthProtocol, user->authProtocolLen);
3856
0
        user->privProtocolLen = OID_LENGTH(usmNoPrivProtocol);
3857
0
        user->privProtocol =
3858
0
            snmp_duplicate_objid(usmNoPrivProtocol, user->privProtocolLen);
3859
0
        if (sessUser)
3860
0
            *sessUser = user;
3861
0
        else
3862
0
            usm_add_user(user);
3863
0
    }
3864
0
    return 0;
3865
0
}
3866
3867
static int usm_discover_engineid(struct session_list *slp,
3868
                                 netsnmp_session *session)
3869
0
{
3870
0
    netsnmp_pdu    *pdu = NULL, *response = NULL;
3871
0
    struct usmUser **user;
3872
0
    int status, i;
3873
3874
0
    user = session->flags & SNMP_FLAGS_SESSION_USER ? &session->sessUser : NULL;
3875
0
    if (usm_build_probe_pdu(&pdu, user) != 0) {
3876
0
        DEBUGMSGTL(("snmp_api", "unable to create probe PDU\n"));
3877
0
        return SNMP_ERR_GENERR;
3878
0
    }
3879
0
    DEBUGMSGTL(("snmp_api", "probing for engineID...\n"));
3880
0
    session->flags |= SNMP_FLAGS_DONT_PROBE; /* prevent recursion */
3881
0
    status = snmp_sess_synch_response(slp, pdu, &response);
3882
3883
0
    if ((response == NULL) && (status == STAT_SUCCESS)) {
3884
0
        status = STAT_ERROR;
3885
0
    }
3886
3887
0
    switch (status) {
3888
0
    case STAT_SUCCESS:
3889
0
        session->s_snmp_errno = SNMPERR_INVALID_MSG; /* XX?? */
3890
0
        DEBUGMSGTL(("snmp_sess_open",
3891
0
                    "error: expected Report as response to probe: %s (%ld)\n",
3892
0
                    snmp_errstring(response->errstat),
3893
0
                    response->errstat));
3894
0
        break;
3895
0
    case STAT_ERROR:   /* this is what we expected -> Report == STAT_ERROR */
3896
0
        session->s_snmp_errno = SNMPERR_UNKNOWN_ENG_ID;
3897
0
        break;
3898
0
    case STAT_TIMEOUT:
3899
0
        session->s_snmp_errno = SNMPERR_TIMEOUT;
3900
0
        break;
3901
0
    default:
3902
0
        DEBUGMSGTL(("snmp_sess_open",
3903
0
                    "unable to connect with remote engine: %s (%d)\n",
3904
0
                    snmp_api_errstring(session->s_snmp_errno),
3905
0
                    session->s_snmp_errno));
3906
0
        break;
3907
0
    }
3908
3909
0
    if (slp->session->securityEngineIDLen == 0) {
3910
0
        DEBUGMSGTL(("snmp_api",
3911
0
                    "unable to determine remote engine ID\n"));
3912
        /* clear the flag so that probe occurs on next inform */
3913
0
        session->flags &= ~SNMP_FLAGS_DONT_PROBE;
3914
0
        return SNMP_ERR_GENERR;
3915
0
    }
3916
3917
0
    session->s_snmp_errno = SNMPERR_SUCCESS;
3918
0
    if (snmp_get_do_debugging()) {
3919
0
        DEBUGMSGTL(("snmp_sess_open",
3920
0
                    "  probe found engineID:  "));
3921
0
        for (i = 0; i < slp->session->securityEngineIDLen; i++)
3922
0
            DEBUGMSG(("snmp_sess_open", "%02x",
3923
0
                      slp->session->securityEngineID[i]));
3924
0
        DEBUGMSG(("snmp_sess_open", "\n"));
3925
0
    }
3926
3927
    /*
3928
     * if boot/time supplied set it for this engineID 
3929
     */
3930
0
    if (session->engineBoots || session->engineTime) {
3931
0
        set_enginetime(session->securityEngineID,
3932
0
                       session->securityEngineIDLen,
3933
0
                       session->engineBoots, session->engineTime,
3934
0
                       TRUE);
3935
0
        session->flags |= SNMP_FLAGS_TIME_CREATED;
3936
0
    }
3937
0
    return SNMPERR_SUCCESS;
3938
0
}
3939
3940
static int
3941
usm_lookup_alg_type(const char *str, const usm_alg_type_t *types)
3942
299
{
3943
299
    int i, l;
3944
299
    l = strlen(str);
3945
3.27k
    for (i = 0; types[i].label; ++i) {
3946
3.06k
        if (0 == strncasecmp(types[i].label, str, l))
3947
97
            return types[i].value;
3948
3.06k
    }
3949
3950
202
    return -1;
3951
299
}
3952
3953
static const char *
3954
usm_lookup_alg_str(int value, const usm_alg_type_t *types)
3955
0
{
3956
0
    int i;
3957
0
    for (i = 0; types[i].label; ++i)
3958
0
        if (value == types[i].value)
3959
0
            return types[i].label;
3960
3961
0
    return NULL;
3962
0
}
3963
3964
int
3965
usm_lookup_auth_type(const char *str)
3966
152
{
3967
152
    return usm_lookup_alg_type(str, usm_auth_type );
3968
152
}
3969
3970
int
3971
usm_lookup_priv_type(const char *str)
3972
147
{
3973
147
    return usm_lookup_alg_type(str, usm_priv_type );
3974
147
}
3975
3976
const char *
3977
usm_lookup_auth_str(int value)
3978
0
{
3979
0
    return usm_lookup_alg_str(value, usm_auth_type );
3980
0
}
3981
3982
const char *
3983
usm_lookup_priv_str(int value)
3984
0
{
3985
0
    return usm_lookup_alg_str(value, usm_priv_type );
3986
0
}
3987
3988
static void
3989
clear_user_list(void)
3990
6.79k
{
3991
6.79k
    struct usmUser *tmp = userList, *next = NULL;
3992
3993
6.79k
    while (tmp != NULL) {
3994
0
  next = tmp->next;
3995
0
  usm_free_user(tmp);
3996
0
  tmp = next;
3997
0
    }
3998
6.79k
    userList = NULL;
3999
4000
6.79k
}
4001
4002
#ifndef NETSNMP_NO_WRITE_SUPPORT
4003
/*
4004
 * take a given user and clone the security info into another 
4005
 */
4006
struct usmUser *
4007
usm_cloneFrom_user(struct usmUser *from, struct usmUser *to)
4008
0
{
4009
0
    to->flags = from->flags;
4010
4011
    /*
4012
     * copy the authProtocol oid row pointer 
4013
     */
4014
0
    SNMP_FREE(to->authProtocol);
4015
4016
0
    if ((to->authProtocol =
4017
0
         snmp_duplicate_objid(from->authProtocol,
4018
0
                              from->authProtocolLen)) != NULL)
4019
0
        to->authProtocolLen = from->authProtocolLen;
4020
0
    else
4021
0
        to->authProtocolLen = 0;
4022
4023
4024
    /*
4025
     * copy the authKey 
4026
     */
4027
0
    SNMP_FREE(to->authKey);
4028
4029
0
    to->authKey = netsnmp_memdup(from->authKey, from->authKeyLen);
4030
0
    to->authKeyLen = to->authKey ? from->authKeyLen : 0;
4031
4032
    /*
4033
     * copy the authKeyKu
4034
     */
4035
0
    SNMP_FREE(to->authKeyKu);
4036
4037
0
    if (from->authKeyKuLen > 0 &&
4038
0
        (to->authKeyKu = (u_char *) malloc(from->authKeyKuLen)) != NULL) {
4039
0
        to->authKeyKuLen = from->authKeyKuLen;
4040
0
        memcpy(to->authKeyKu, from->authKeyKu, to->authKeyKuLen);
4041
0
    } else {
4042
0
        to->authKeyKu = NULL;
4043
0
        to->authKeyKuLen = 0;
4044
0
    }
4045
4046
4047
    /*
4048
     * copy the privProtocol oid row pointer 
4049
     */
4050
0
    SNMP_FREE(to->privProtocol);
4051
4052
0
    if ((to->privProtocol =
4053
0
         snmp_duplicate_objid(from->privProtocol,
4054
0
                              from->privProtocolLen)) != NULL)
4055
0
        to->privProtocolLen = from->privProtocolLen;
4056
0
    else
4057
0
        to->privProtocolLen = 0;
4058
4059
    /*
4060
     * copy the privKey 
4061
     */
4062
0
    SNMP_FREE(to->privKey);
4063
4064
0
    if (from->privKeyLen > 0 &&
4065
0
        (to->privKey = (u_char *) malloc(from->privKeyLen))
4066
0
        != NULL) {
4067
0
        to->privKeyLen = from->privKeyLen;
4068
0
        memcpy(to->privKey, from->privKey, to->privKeyLen);
4069
0
    } else {
4070
0
        to->privKey = NULL;
4071
0
        to->privKeyLen = 0;
4072
0
    }
4073
4074
    /*
4075
     * copy the privKeyKu
4076
     */
4077
0
    SNMP_FREE(to->privKeyKu);
4078
0
    if (from->privKeyKuLen > 0 &&
4079
0
        (to->privKeyKu = (u_char *) malloc(from->privKeyKuLen)) != NULL) {
4080
0
        to->privKeyKuLen = from->privKeyKuLen;
4081
0
        memcpy(to->privKeyKu, from->privKeyKu, to->privKeyKuLen);
4082
0
    } else {
4083
0
        to->privKeyKu = NULL;
4084
0
        to->privKeyKuLen = 0;
4085
0
    }
4086
0
    return to;
4087
0
}
4088
#endif /* NETSNMP_NO_WRITE_SUPPORT */
4089
4090
/*
4091
 * usm_create_user(void):
4092
 * create a default empty user, instantiating only the auth/priv
4093
 * protocols to noAuth and noPriv OID pointers
4094
 */
4095
struct usmUser *
4096
usm_create_user(void)
4097
3.39k
{
4098
3.39k
    struct usmUser *newUser;
4099
4100
    /*
4101
     * create the new user 
4102
     */
4103
3.39k
    newUser = calloc(1, sizeof(struct usmUser));
4104
3.39k
    if (newUser == NULL)
4105
0
        return NULL;
4106
4107
    /*
4108
     * fill the auth/priv protocols 
4109
     */
4110
3.39k
    if ((newUser->authProtocol =
4111
3.39k
         snmp_duplicate_objid(usmNoAuthProtocol,
4112
3.39k
                              OID_LENGTH(usmNoAuthProtocol))) ==
4113
3.39k
        NULL)
4114
0
        return usm_free_user(newUser);
4115
3.39k
    newUser->authProtocolLen = OID_LENGTH(usmNoAuthProtocol);
4116
4117
3.39k
    if ((newUser->privProtocol =
4118
3.39k
         snmp_duplicate_objid(usmNoPrivProtocol,
4119
3.39k
                              OID_LENGTH(usmNoPrivProtocol))) ==
4120
3.39k
        NULL)
4121
0
        return usm_free_user(newUser);
4122
3.39k
    newUser->privProtocolLen = OID_LENGTH(usmNoPrivProtocol);
4123
4124
    /*
4125
     * set the storage type to nonvolatile, and the status to ACTIVE 
4126
     */
4127
3.39k
    newUser->userStorageType = ST_NONVOLATILE;
4128
3.39k
    newUser->userStatus = RS_ACTIVE;
4129
3.39k
    return newUser;
4130
4131
3.39k
}                               /* end usm_clone_user() */
4132
4133
/*
4134
 * usm_create_initial_user(void):
4135
 * creates an initial user, filled with the defaults defined in the
4136
 * USM document.
4137
 */
4138
static struct usmUser *
4139
usm_create_initial_user(const char *name,
4140
                        const oid * authProtocol, size_t authProtocolLen,
4141
                        const oid * privProtocol, size_t privProtocolLen)
4142
3.39k
{
4143
3.39k
    struct usmUser *newUser = usm_create_user();
4144
3.39k
    if (newUser == NULL)
4145
0
        return NULL;
4146
4147
3.39k
    if ((newUser->name = strdup(name)) == NULL)
4148
0
        return usm_free_user(newUser);
4149
4150
3.39k
    if ((newUser->secName = strdup(name)) == NULL)
4151
0
        return usm_free_user(newUser);
4152
4153
3.39k
    if ((newUser->engineID =
4154
3.39k
         snmpv3_generate_engineID(&newUser->engineIDLen)) == NULL)
4155
0
        return usm_free_user(newUser);
4156
4157
3.39k
    if ((newUser->cloneFrom = (oid *) malloc(sizeof(oid) * 2)) == NULL)
4158
0
        return usm_free_user(newUser);
4159
3.39k
    newUser->cloneFrom[0] = 0;
4160
3.39k
    newUser->cloneFrom[1] = 0;
4161
3.39k
    newUser->cloneFromLen = 2;
4162
4163
3.39k
    SNMP_FREE(newUser->privProtocol);
4164
3.39k
    if ((newUser->privProtocol = snmp_duplicate_objid(privProtocol,
4165
3.39k
                                                      privProtocolLen)) ==
4166
3.39k
        NULL) {
4167
0
        return usm_free_user(newUser);
4168
0
    }
4169
3.39k
    newUser->privProtocolLen = privProtocolLen;
4170
4171
3.39k
    SNMP_FREE(newUser->authProtocol);
4172
3.39k
    if ((newUser->authProtocol = snmp_duplicate_objid(authProtocol,
4173
3.39k
                                                      authProtocolLen)) ==
4174
3.39k
        NULL) {
4175
0
        return usm_free_user(newUser);
4176
0
    }
4177
3.39k
    newUser->authProtocolLen = authProtocolLen;
4178
4179
3.39k
    newUser->userStatus = RS_ACTIVE;
4180
3.39k
    newUser->userStorageType = ST_READONLY;
4181
4182
3.39k
    return newUser;
4183
3.39k
}
4184
4185
/*
4186
 * usm_save_user(): saves a user to the persistent cache 
4187
 */
4188
static void
4189
usm_save_user(struct usmUser *user, const char *token, const char *type)
4190
0
{
4191
0
    char            line[4096];
4192
0
    char           *cptr;
4193
4194
0
    memset(line, 0, sizeof(line));
4195
4196
0
    sprintf(line, "%s %d %d ", token, user->userStatus,
4197
0
            user->userStorageType);
4198
0
    cptr = &line[strlen(line)]; /* the NULL */
4199
0
    cptr =
4200
0
        read_config_save_octet_string(cptr, user->engineID,
4201
0
                                      user->engineIDLen);
4202
0
    *cptr++ = ' ';
4203
0
    cptr = read_config_save_octet_string(cptr, (u_char *) user->name,
4204
0
                                         (user->name == NULL) ? 0 :
4205
0
                                         strlen(user->name));
4206
0
    *cptr++ = ' ';
4207
0
    cptr = read_config_save_octet_string(cptr, (u_char *) user->secName,
4208
0
                                         (user->secName == NULL) ? 0 :
4209
0
                                         strlen(user->secName));
4210
0
    *cptr++ = ' ';
4211
0
    cptr =
4212
0
        read_config_save_objid(cptr, user->cloneFrom, user->cloneFromLen);
4213
0
    *cptr++ = ' ';
4214
0
    cptr = read_config_save_objid(cptr, user->authProtocol,
4215
0
                                  user->authProtocolLen);
4216
0
    *cptr++ = ' ';
4217
0
    cptr =
4218
0
        read_config_save_octet_string(cptr, user->authKey,
4219
0
                                      user->authKeyLen);
4220
0
    *cptr++ = ' ';
4221
0
    cptr = read_config_save_objid(cptr, user->privProtocol,
4222
0
                                  user->privProtocolLen);
4223
0
    *cptr++ = ' ';
4224
0
    cptr =
4225
0
        read_config_save_octet_string(cptr, user->privKey,
4226
0
                                      user->privKeyLen);
4227
0
    *cptr++ = ' ';
4228
0
    cptr = read_config_save_octet_string(cptr, user->userPublicString,
4229
0
                                         user->userPublicStringLen);
4230
4231
0
    read_config_store(type, line);
4232
0
}
4233
4234
static void
4235
usm_save_users_from_list(struct usmUser *puserList, const char *token,
4236
                         const char *type)
4237
3.39k
{
4238
3.39k
    struct usmUser *uptr;
4239
3.39k
    for (uptr = puserList; uptr != NULL; uptr = uptr->next) {
4240
0
        if (uptr->userStorageType == ST_NONVOLATILE)
4241
0
            usm_save_user(uptr, token, type);
4242
0
    }
4243
3.39k
}
4244
4245
/*
4246
 * usm_save_users(): saves a list of users to the persistent cache 
4247
 */
4248
static void
4249
usm_save_users(const char *token, const char *type)
4250
3.39k
{
4251
3.39k
    usm_save_users_from_list(userList, token, type);
4252
3.39k
}
4253
4254
/*
4255
 * this is a callback that can store all known users based on a
4256
 * previously registered application ID 
4257
 */
4258
static int
4259
usm_store_users(int majorID, int minorID, void *serverarg, void *clientarg)
4260
3.39k
{
4261
    /*
4262
     * figure out our application name 
4263
     */
4264
3.39k
    char           *appname = (char *) clientarg;
4265
3.39k
    if (appname == NULL) {
4266
3.39k
        appname = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 
4267
3.39k
          NETSNMP_DS_LIB_APPTYPE);
4268
3.39k
    }
4269
4270
    /*
4271
     * save the user base 
4272
     */
4273
3.39k
    usm_save_users("usmUser", appname);
4274
4275
    /*
4276
     * never fails 
4277
     */
4278
3.39k
    return SNMPERR_SUCCESS;
4279
3.39k
}
4280
4281
/**
4282
 * usm_read_user(): reads in a line containing a saved user profile
4283
 * and returns a pointer to a newly created struct usmUser. 
4284
 *
4285
 * @param[in]     line Line of text containing a saved user profile
4286
 *
4287
 * @return A pointer to the newly-created struct usmUser if
4288
 *   parsing succeeded; NULL if an error occurred.
4289
 */
4290
static struct usmUser *
4291
usm_read_user(const char *line)
4292
0
{
4293
0
    struct usmUser *user;
4294
0
    size_t          len, proper_length, privtype;
4295
4296
0
    user = usm_create_user();
4297
0
    if (user == NULL)
4298
0
        return NULL;
4299
4300
0
    user->userStatus = atoi(line);
4301
0
    line = skip_token_const(line);
4302
0
    if (line == NULL) {
4303
0
        DEBUGMSGTL(("usm", "Configuration line missing userStorageType\n"));
4304
0
        usm_free_user(user);
4305
0
        return NULL;
4306
0
    }
4307
4308
0
    user->userStorageType = atoi(line);
4309
0
    line = skip_token_const(line);
4310
0
    if (line == NULL) {
4311
0
        DEBUGMSGTL(("usm", "Configuration line missing engineID\n"));
4312
0
        usm_free_user(user);
4313
0
        return NULL;
4314
0
    }
4315
0
    line = read_config_read_octet_string_const(line, &user->engineID,
4316
0
                                               &user->engineIDLen);
4317
4318
0
    if (line == NULL) {
4319
0
        DEBUGMSGTL(("usm", "Configuration line missing name\n"));
4320
0
        usm_free_user(user);
4321
0
        return NULL;
4322
0
    }
4323
0
    line = read_config_read_octet_string(line, (u_char **) & user->name,
4324
0
                                         &len);
4325
0
    if (line == NULL) {
4326
0
        DEBUGMSGTL(("usm", "Configuration line missing security name\n"));
4327
0
        usm_free_user(user);
4328
0
        return NULL;
4329
0
    }
4330
0
    line = read_config_read_octet_string(line, (u_char **) & user->secName,
4331
0
                                         &len);
4332
0
    SNMP_FREE(user->cloneFrom);
4333
0
    user->cloneFromLen = 0;
4334
4335
0
    if (line == NULL) {
4336
0
        DEBUGMSGTL(("usm", "Configuration line missing clone from\n"));
4337
0
        usm_free_user(user);
4338
0
        return NULL;
4339
0
    }
4340
0
    line = read_config_read_objid_const(line, &user->cloneFrom,
4341
0
                                        &user->cloneFromLen);
4342
4343
0
    SNMP_FREE(user->authProtocol);
4344
0
    user->authProtocolLen = 0;
4345
4346
0
    if (line == NULL) {
4347
0
        DEBUGMSGTL(("usm", "Configuration line missing authentication protocol\n"));
4348
0
        usm_free_user(user);
4349
0
        return NULL;
4350
0
    }
4351
0
    line = read_config_read_objid_const(line, &user->authProtocol,
4352
0
                                        &user->authProtocolLen);
4353
4354
0
    if (line == NULL) {
4355
0
        DEBUGMSGTL(("usm", "Configuration line missing authentication key\n"));
4356
0
        usm_free_user(user);
4357
0
        return NULL;
4358
0
    }
4359
0
    line = read_config_read_octet_string_const(line, &user->authKey,
4360
0
                                               &user->authKeyLen);
4361
0
    SNMP_FREE(user->privProtocol);
4362
0
    user->privProtocolLen = 0;
4363
4364
0
    if (line == NULL) {
4365
0
        DEBUGMSGTL(("usm", "Configuration line missing privacy protocol\n"));
4366
0
        usm_free_user(user);
4367
0
        return NULL;
4368
0
    }
4369
0
    line = read_config_read_objid_const(line, &user->privProtocol,
4370
0
                                        &user->privProtocolLen);
4371
4372
0
    if (line == NULL) {
4373
0
        DEBUGMSGTL(("usm", "Configuration line missing privacy key\n"));
4374
0
        usm_free_user(user);
4375
0
        return NULL;
4376
0
    }
4377
0
    line = read_config_read_octet_string(line, &user->privKey,
4378
0
                                         &user->privKeyLen);
4379
4380
0
    privtype = sc_get_privtype(user->privProtocol, user->privProtocolLen);
4381
0
    proper_length = sc_get_proper_priv_length_bytype(privtype);
4382
0
    if (USM_CREATE_USER_PRIV_DES == privtype)
4383
0
        proper_length *= 2; /* ?? we store salt with key */
4384
    /* For backwards compatibility */
4385
0
    if (user->privKeyLen > proper_length) {
4386
0
        user->privKeyLen = proper_length;
4387
0
    }
4388
4389
0
    if (line == NULL) {
4390
0
        DEBUGMSGTL(("usm", "Configuration line missing public string\n"));
4391
0
        usm_free_user(user);
4392
0
        return NULL;
4393
0
    }
4394
0
    line = read_config_read_octet_string(line, &user->userPublicString,
4395
0
                                         &user->userPublicStringLen);
4396
4397
    /*
4398
     * set the lcd entry for this engineID to the minimum boots/time
4399
     * values so that its a known engineid and won't return a report pdu.
4400
     * This is mostly important when receiving v3 traps so that the usm
4401
     * will at least continue processing them.
4402
     * Note: We do this at the end so that it only runs if the parsing
4403
     * was successful
4404
     */
4405
0
    set_enginetime(user->engineID, user->engineIDLen, 1, 0, 0);
4406
4407
0
    return user;
4408
0
}
4409
4410
/*
4411
 * snmpd.conf parsing routines 
4412
 */
4413
void
4414
usm_parse_config_usmUser(const char *token, char *line)
4415
0
{
4416
0
    struct usmUser *uptr;
4417
4418
0
    uptr = usm_read_user(line);
4419
0
    if ( uptr)
4420
0
        usm_add_user(uptr);
4421
0
}
4422
4423
/*******************************************************************-o-******
4424
 * usm_set_password
4425
 *
4426
 * Parameters:
4427
 *  *token
4428
 *  *line
4429
 *      
4430
 *
4431
 * format: userSetAuthPass     secname engineIDLen engineID pass
4432
 *     or: userSetPrivPass     secname engineIDLen engineID pass 
4433
 *     or: userSetAuthKey      secname engineIDLen engineID KuLen Ku
4434
 *     or: userSetPrivKey      secname engineIDLen engineID KuLen Ku 
4435
 *     or: userSetAuthLocalKey secname engineIDLen engineID KulLen Kul
4436
 *     or: userSetPrivLocalKey secname engineIDLen engineID KulLen Kul 
4437
 *
4438
 * type is: 1=passphrase; 2=Ku; 3=Kul.
4439
 *
4440
 *
4441
 * ASSUMES  Passwords are null-terminated printable strings.
4442
 */
4443
static void
4444
usm_set_password(const char *token, char *line)
4445
994
{
4446
994
    char           *cp;
4447
994
    char            nameBuf[SNMP_MAXBUF];
4448
994
    u_char         *engineID = NULL;
4449
994
    size_t          engineIDLen = 0;
4450
994
    struct usmUser *user;
4451
4452
994
    cp = copy_nword(line, nameBuf, sizeof(nameBuf));
4453
994
    if (cp == NULL) {
4454
30
        config_perror("invalid name specifier");
4455
30
        return;
4456
30
    }
4457
4458
964
    DEBUGMSGTL(("usm", "comparing: %s and %s\n", cp, WILDCARDSTRING));
4459
964
    if (strncmp(cp, WILDCARDSTRING, strlen(WILDCARDSTRING)) == 0) {
4460
        /*
4461
         * match against all engineIDs we know about 
4462
         */
4463
74
        cp = skip_token(cp);
4464
74
        for (user = userList; user != NULL; user = user->next) {
4465
0
            if (user->secName && strcmp(user->secName, nameBuf) == 0) {
4466
0
                usm_set_user_password(user, token, cp);
4467
0
            }
4468
0
        }
4469
890
    } else {
4470
890
        cp = read_config_read_octet_string(cp, &engineID, &engineIDLen);
4471
890
        if (cp == NULL) {
4472
259
            config_perror("invalid engineID specifier");
4473
259
            SNMP_FREE(engineID);
4474
259
            return;
4475
259
        }
4476
4477
631
        user = usm_get_user(engineID, engineIDLen, nameBuf);
4478
631
        if (user == NULL) {
4479
60
            config_perror("not a valid user/engineID pair");
4480
60
            SNMP_FREE(engineID);
4481
60
            return;
4482
60
        }
4483
571
        usm_set_user_password(user, token, cp);
4484
571
        SNMP_FREE(engineID);
4485
571
    }
4486
964
}
4487
4488
/*
4489
 * uses the rest of LINE to configure USER's password of type TOKEN 
4490
 */
4491
void
4492
usm_set_user_password(struct usmUser *user, const char *token, char *line)
4493
571
{
4494
571
    char           *cp = line;
4495
571
    u_char         *engineID = user->engineID;
4496
571
    size_t          engineIDLen = user->engineIDLen;
4497
4498
571
    u_char        **key;
4499
571
    size_t         *keyLen;
4500
571
    u_char          userKey[SNMP_MAXBUF_SMALL];
4501
571
    size_t          userKeyLen = SNMP_MAXBUF_SMALL;
4502
571
    u_char         *userKeyP = userKey;
4503
571
    int             type, ret;
4504
4505
    /*
4506
     * Retrieve the "old" key and set the key type.
4507
     */
4508
571
    if (!token) {
4509
0
        return;
4510
571
    } else if (strcmp(token, "userSetAuthPass") == 0) {
4511
21
        key = &user->authKey;
4512
21
        keyLen = &user->authKeyLen;
4513
21
        type = 0;
4514
550
    } else if (strcmp(token, "userSetPrivPass") == 0) {
4515
199
        key = &user->privKey;
4516
199
        keyLen = &user->privKeyLen;
4517
199
        type = 0;
4518
351
    } else if (strcmp(token, "userSetAuthKey") == 0) {
4519
98
        key = &user->authKey;
4520
98
        keyLen = &user->authKeyLen;
4521
98
        type = 1;
4522
253
    } else if (strcmp(token, "userSetPrivKey") == 0) {
4523
29
        key = &user->privKey;
4524
29
        keyLen = &user->privKeyLen;
4525
29
        type = 1;
4526
224
    } else if (strcmp(token, "userSetAuthLocalKey") == 0) {
4527
75
        key = &user->authKey;
4528
75
        keyLen = &user->authKeyLen;
4529
75
        type = 2;
4530
149
    } else if (strcmp(token, "userSetPrivLocalKey") == 0) {
4531
90
        key = &user->privKey;
4532
90
        keyLen = &user->privKeyLen;
4533
90
        type = 2;
4534
90
    } else {
4535
        /*
4536
         * no old key, or token was not recognized 
4537
         */
4538
59
        return;
4539
59
    }
4540
4541
512
    if (*key) {
4542
        /*
4543
         * (destroy and) free the old key 
4544
         */
4545
242
        memset(*key, 0, *keyLen);
4546
242
        SNMP_FREE(*key);
4547
242
    }
4548
4549
512
    if (type == 0) {
4550
        /*
4551
         * convert the password into a key 
4552
         */
4553
220
        if (cp == NULL) {
4554
0
            config_perror("missing user password");
4555
0
            return;
4556
0
        }
4557
220
        ret = generate_Ku(user->authProtocol, user->authProtocolLen,
4558
220
                          (u_char *) cp, strlen(cp), userKey, &userKeyLen);
4559
4560
220
        if (ret != SNMPERR_SUCCESS) {
4561
156
            config_perror("setting key failed (in sc_genKu())");
4562
156
            return;
4563
156
        }
4564
        /* save master key */
4565
64
        if (user->flags & USMUSER_FLAG_KEEP_MASTER_KEY) {
4566
0
            if (userKey == user->privKey) {
4567
0
                user->privKeyKu = netsnmp_memdup(userKey, userKeyLen);
4568
0
                user->privKeyKuLen = userKeyLen;
4569
0
            } else if (userKey == user->authKey) {
4570
0
                user->authKeyKu = netsnmp_memdup(userKey, userKeyLen);
4571
0
                user->authKeyKuLen = userKeyLen;
4572
0
            }
4573
0
        }
4574
292
    } else if (type == 1) {
4575
127
        cp = read_config_read_octet_string(cp, &userKeyP, &userKeyLen);
4576
4577
127
        if (cp == NULL) {
4578
113
            config_perror("invalid user key");
4579
113
            return;
4580
113
        }
4581
127
    }
4582
4583
243
    if (type < 2) {
4584
78
        *key = (u_char *) malloc(SNMP_MAXBUF_SMALL);
4585
78
        *keyLen = SNMP_MAXBUF_SMALL;
4586
78
        ret = generate_kul(user->authProtocol, user->authProtocolLen,
4587
78
                           engineID, engineIDLen,
4588
78
                           userKey, userKeyLen, *key, keyLen);
4589
78
        if (ret != SNMPERR_SUCCESS) {
4590
78
            config_perror("setting key failed (in generate_kul())");
4591
78
            return;
4592
78
        }
4593
4594
        /*
4595
         * (destroy and) free the old key 
4596
         */
4597
0
        memset(userKey, 0, sizeof(userKey));
4598
4599
165
    } else {
4600
        /*
4601
         * the key is given, copy it in 
4602
         */
4603
165
        cp = read_config_read_octet_string(cp, key, keyLen);
4604
4605
165
        if (cp == NULL) {
4606
71
            config_perror("invalid localized user key");
4607
71
            return;
4608
71
        }
4609
165
    }
4610
4611
94
    if (key == &user->privKey) {
4612
71
        ret = usm_extend_user_kul(user, *keyLen);
4613
71
        if (SNMPERR_SUCCESS != ret) {
4614
0
            config_perror("error extending localized user key");
4615
0
            return;
4616
0
        }
4617
71
    }
4618
94
}                               /* end usm_set_password() */
4619
4620
/*
4621
 * create a usm user from a string.
4622
 *
4623
 * The format for the string is described in the createUser
4624
 * section of the snmpd.conf man page.
4625
 *
4626
 * On success, a pointer to the created usmUser struct is returned.
4627
 * On error, a NULL pointer is returned. In this case, if a pointer to a
4628
 *    char pointer is provided in errorMsg, an error string is returned.
4629
 *    This error string points to a static message, and should not be
4630
 *    freed.
4631
 */
4632
static struct usmUser *
4633
usm_create_usmUser_from_string(char *line, const char **errorMsg)
4634
0
{
4635
0
    char           *cp;
4636
0
    const char     *dummy;
4637
0
    char            buf[SNMP_MAXBUF_MEDIUM];
4638
0
    struct usmUser *newuser;
4639
0
    u_char          userKey[SNMP_MAXBUF_SMALL], *tmpp;
4640
0
    size_t          userKeyLen = SNMP_MAXBUF_SMALL;
4641
0
    size_t          privKeySize;
4642
0
    size_t          ret;
4643
0
    int             ret2, properLen, properPrivKeyLen;
4644
0
    const oid      *def_auth_prot, *def_priv_prot;
4645
0
    size_t          def_auth_prot_len, def_priv_prot_len;
4646
0
    const netsnmp_priv_alg_info *pai;
4647
4648
0
    def_auth_prot = get_default_authtype(&def_auth_prot_len);
4649
0
    def_priv_prot = get_default_privtype(&def_priv_prot_len);
4650
4651
0
    if (NULL == line)
4652
0
        return NULL;
4653
4654
#ifdef NETSNMP_ENABLE_TESTING_CODE
4655
    DEBUGMSGTL(("usmUser", "new user %s\n", line)); /* logs passphrases */
4656
#endif
4657
4658
0
    if (NULL == errorMsg)
4659
0
        errorMsg = &dummy;
4660
0
    *errorMsg = NULL; /* no errors yet */
4661
4662
0
    newuser = usm_create_user();
4663
0
    if (newuser == NULL) {
4664
0
        *errorMsg = "malloc failure creating new user";
4665
0
        goto fail;
4666
0
    }
4667
4668
    /*
4669
     * READ: Security Name 
4670
     */
4671
0
    cp = copy_nword(line, buf, sizeof(buf));
4672
4673
    /*
4674
     * check for (undocumented) 'keep master key' flag. so far, this is
4675
     * just used for users for informs (who need non-localized keys).
4676
     */
4677
0
    if (strcmp(buf, "-M") == 0) {
4678
0
        newuser->flags |= USMUSER_FLAG_KEEP_MASTER_KEY;
4679
0
        cp = copy_nword(cp, buf, sizeof(buf));
4680
0
    }
4681
4682
    /*
4683
     * might be a -e ENGINEID argument 
4684
     */
4685
0
    if (strcmp(buf, "-e") == 0) {
4686
0
        size_t          ebuf_len = 32, eout_len = 0;
4687
0
        u_char         *ebuf = (u_char *) malloc(ebuf_len);
4688
4689
0
        if (ebuf == NULL) {
4690
0
            *errorMsg = "malloc failure processing -e flag";
4691
0
            goto fail;
4692
0
        }
4693
4694
        /*
4695
         * Get the specified engineid from the line.  
4696
         */
4697
0
        cp = copy_nword(cp, buf, sizeof(buf));
4698
0
        if (!snmp_hex_to_binary(&ebuf, &ebuf_len, &eout_len, 1, buf)) {
4699
0
            *errorMsg = "invalid EngineID argument to -e";
4700
0
            SNMP_FREE(ebuf);
4701
0
            goto fail;
4702
0
        }
4703
4704
0
        newuser->engineID = ebuf;
4705
0
        newuser->engineIDLen = eout_len;
4706
0
        cp = copy_nword(cp, buf, sizeof(buf));
4707
0
    } else {
4708
0
        newuser->engineID = snmpv3_generate_engineID(&ret);
4709
0
        if (ret == 0) {
4710
0
            goto fail;
4711
0
        }
4712
0
        newuser->engineIDLen = ret;
4713
0
    }
4714
4715
0
    newuser->secName = strdup(buf);
4716
0
    newuser->name = strdup(buf);
4717
4718
0
    if (!cp) {
4719
#ifdef NETSNMP_FORCE_SYSTEM_V3_AUTHPRIV
4720
        /** no passwords ok iff defaults are noauth/nopriv */
4721
        if (snmp_oid_compare(usmNoAuthProtocol, OID_LENGTH(usmNoAuthProtocol),
4722
                             def_auth_prot, def_auth_prot_len) != 0) {
4723
            *errorMsg = "no authentication pass phrase";
4724
            goto fail;
4725
        }
4726
        if (snmp_oid_compare(usmNoPrivProtocol, OID_LENGTH(usmNoPrivProtocol),
4727
                             def_priv_prot, def_priv_prot_len) != 0) {
4728
            *errorMsg = "no privacy pass phrase";
4729
            goto fail;
4730
        }
4731
#endif /* NETSNMP_FORCE_SYSTEM_V3_AUTHPRIV */
4732
0
        goto add;               /* no authentication or privacy type */
4733
0
    }
4734
4735
    /*
4736
     * READ: Authentication Type 
4737
     */
4738
0
    newuser->authProtocol[0] = 0;
4739
0
    cp = copy_nword(cp, buf, sizeof(buf));
4740
    /* If no authentication protocol was specified, or it was explicitly
4741
     * set to use the default, use the default auth protocol
4742
     */
4743
0
    if (buf[0] == '\0' || strcmp(buf, "default") == 0) {
4744
0
        SNMP_FREE(newuser->authProtocol);
4745
0
        if (!def_auth_prot) {
4746
0
            *errorMsg = "def_auth_prot == NULL";
4747
0
            goto fail;
4748
0
        }
4749
0
        newuser->authProtocol = snmp_duplicate_objid(def_auth_prot,
4750
0
                                                     def_auth_prot_len);
4751
0
        if (newuser->authProtocol == NULL) {
4752
0
            *errorMsg = "malloc failed";
4753
0
            goto fail;
4754
0
        }
4755
0
        newuser->authProtocolLen = def_auth_prot_len;
4756
0
    } else {
4757
0
        const oid *auth_prot;
4758
0
        int auth_type = usm_lookup_auth_type(buf);
4759
0
        if (auth_type < 0) {
4760
0
            *errorMsg = "unknown authProtocol";
4761
0
            goto fail;
4762
0
        }
4763
0
        auth_prot = sc_get_auth_oid(auth_type, &newuser->authProtocolLen);
4764
0
        if (auth_prot) {
4765
0
            SNMP_FREE(newuser->authProtocol);
4766
0
            newuser->authProtocol =
4767
0
                snmp_duplicate_objid(auth_prot, newuser->authProtocolLen);
4768
0
        }
4769
0
        if (newuser->authProtocol == NULL) {
4770
0
            *errorMsg = "malloc failed";
4771
0
            goto fail;
4772
0
        }
4773
0
    }
4774
0
    if (0 == newuser->authProtocol[0]) {
4775
0
        *errorMsg = "Unknown authentication protocol";
4776
0
        goto fail;
4777
0
    }
4778
#ifdef NETSNMP_FORCE_SYSTEM_V3_AUTHPRIV
4779
    if (snmp_oid_compare(newuser->authProtocol, newuser->authProtocolLen,
4780
                         def_auth_prot, def_auth_prot_len) != 0) {
4781
        *errorMsg = "auth protocol does not match system policy";
4782
        goto fail;
4783
    }
4784
#endif /* NETSNMP_FORCE_SYSTEM_V3_AUTHPRIV */
4785
4786
    /*
4787
     * READ: Authentication Pass Phrase or key
4788
     */
4789
0
    cp = copy_nword(cp, buf, sizeof(buf));
4790
0
    if (strcmp(buf,"-m") == 0) {
4791
        /* a master key is specified */
4792
0
        cp = copy_nword(cp, buf, sizeof(buf));
4793
0
        ret = sizeof(userKey);
4794
0
        tmpp = userKey;
4795
0
        userKeyLen = 0;
4796
0
        if (!snmp_hex_to_binary(&tmpp, &ret, &userKeyLen, 0, buf)) {
4797
0
            *errorMsg = "invalid key value argument to -m";
4798
0
            goto fail;
4799
0
        }
4800
        /* save master key */
4801
0
        if (newuser->flags & USMUSER_FLAG_KEEP_MASTER_KEY) {
4802
0
            newuser->authKeyKu = netsnmp_memdup(userKey, userKeyLen);
4803
0
            newuser->authKeyKuLen = userKeyLen;
4804
0
        }
4805
0
    } else if (strcmp(buf,"-l") != 0) {
4806
        /* a password is specified */
4807
0
        userKeyLen = sizeof(userKey);
4808
0
        ret2 = generate_Ku(newuser->authProtocol, newuser->authProtocolLen,
4809
0
                          (u_char *) buf, strlen(buf), userKey, &userKeyLen);
4810
0
        if (ret2 != SNMPERR_SUCCESS) {
4811
0
            *errorMsg = "could not generate the authentication key from the supplied pass phrase.";
4812
0
            goto fail;
4813
0
        }
4814
        /* save master key */
4815
0
        if (newuser->flags & USMUSER_FLAG_KEEP_MASTER_KEY) {
4816
0
            newuser->authKeyKu = netsnmp_memdup(userKey, userKeyLen);
4817
0
            newuser->authKeyKuLen = userKeyLen;
4818
0
        }
4819
0
    }        
4820
        
4821
    /*
4822
     * And turn it into a localized key 
4823
     */
4824
0
    properLen = sc_get_proper_auth_length_bytype(
4825
0
        sc_get_authtype(newuser->authProtocol, newuser->authProtocolLen));
4826
0
    if (properLen <= 0) {
4827
0
        *errorMsg = "Could not get proper authentication protocol key length";
4828
0
        goto fail;
4829
0
    }
4830
0
    newuser->authKey = (u_char *) malloc(properLen);
4831
0
    newuser->authKeyLen = properLen;
4832
4833
0
    if (strcmp(buf,"-l") == 0) {
4834
        /* a local key is directly specified */
4835
0
        cp = copy_nword(cp, buf, sizeof(buf));
4836
0
        ret = newuser->authKeyLen;
4837
0
        newuser->authKeyLen = 0;
4838
0
        if (!snmp_hex_to_binary(&newuser->authKey, &ret,
4839
0
                                &newuser->authKeyLen, 0, buf)) {
4840
0
            *errorMsg = "invalid key value argument to -l";
4841
0
            goto fail;
4842
0
        }
4843
0
        if (properLen != newuser->authKeyLen) {
4844
0
            *errorMsg = "improper key length to -l";
4845
0
            goto fail;
4846
0
        }
4847
0
    } else {
4848
0
        ret2 = generate_kul(newuser->authProtocol, newuser->authProtocolLen,
4849
0
                           newuser->engineID, newuser->engineIDLen,
4850
0
                           userKey, userKeyLen,
4851
0
                           newuser->authKey, &newuser->authKeyLen);
4852
0
        if (ret2 != SNMPERR_SUCCESS) {
4853
0
            *errorMsg = "could not generate localized authentication key (Kul) from the master key (Ku).";
4854
0
            goto fail;
4855
0
        }
4856
0
    }
4857
4858
0
    if (!cp) {
4859
0
#ifndef NETSNMP_FORCE_SYSTEM_V3_AUTHPRIV
4860
0
        goto add;               /* no privacy type (which is legal) */
4861
#else
4862
        if (snmp_oid_compare(usmNoPrivProtocol, OID_LENGTH(usmNoPrivProtocol),
4863
                             def_priv_prot, def_priv_prot_len) == 0)
4864
            goto add;
4865
        else {
4866
            *errorMsg = "priv protocol does not match system policy";
4867
            goto fail;
4868
        }
4869
#endif /* NETSNMP_FORCE_SYSTEM_V3_AUTHPRIV */
4870
0
    }
4871
4872
    /*
4873
     * READ: Privacy Type 
4874
     */
4875
0
    newuser->privProtocol[0] = 0;
4876
0
    cp = copy_nword(cp, buf, sizeof(buf));
4877
0
    if ((strncmp(buf, "default", 7) == 0) && (NULL != def_priv_prot)) {
4878
0
        SNMP_FREE(newuser->privProtocol);
4879
0
        newuser->privProtocol =
4880
0
            snmp_duplicate_objid(def_priv_prot, def_priv_prot_len);
4881
0
        if (newuser->privProtocol == NULL) {
4882
0
            *errorMsg = "malloc failed";
4883
0
            goto fail;
4884
0
        }
4885
0
        newuser->privProtocolLen = def_priv_prot_len;
4886
0
        pai = sc_get_priv_alg_byoid(newuser->privProtocol,
4887
0
                                    newuser->privProtocolLen);
4888
0
    } else {
4889
0
        int priv_type = usm_lookup_priv_type(buf);
4890
0
        if (priv_type < 0) {
4891
0
            *errorMsg = "unknown privProtocol";
4892
0
            DEBUGMSGTL(("usmUser", "%s %s\n", *errorMsg, buf));
4893
0
            goto fail;
4894
0
        }
4895
0
        DEBUGMSGTL(("9:usmUser", "privProtocol %s\n", buf));
4896
0
        pai = sc_get_priv_alg_bytype(priv_type);
4897
0
        if (pai) {
4898
0
            SNMP_FREE(newuser->privProtocol);
4899
0
            newuser->privProtocolLen = pai->oid_len;
4900
0
            newuser->privProtocol =
4901
0
                snmp_duplicate_objid(pai->alg_oid, newuser->privProtocolLen);
4902
0
            DEBUGMSGTL(("9:usmUser", "pai %s\n", pai->name));
4903
0
            if (newuser->privProtocol == NULL) {
4904
0
                *errorMsg = "malloc failed";
4905
0
                goto fail;
4906
0
            }
4907
0
        }
4908
0
    }
4909
0
    if (NULL == pai) {
4910
0
        *errorMsg = "priv protocol lookup failed";
4911
0
        goto fail;
4912
0
    }
4913
4914
0
    if (0 == newuser->privProtocol[0] && NULL == *errorMsg)
4915
0
        *errorMsg = "Unknown privacy protocol";
4916
0
    if (NULL != *errorMsg)
4917
0
        goto fail;
4918
#ifdef NETSNMP_FORCE_SYSTEM_V3_AUTHPRIV
4919
    if (snmp_oid_compare(newuser->privProtocol, newuser->privProtocolLen,
4920
                         def_priv_prot, def_priv_prot_len) != 0) {
4921
        *errorMsg = "priv protocol does not match system policy";
4922
        goto fail;
4923
    }
4924
#endif /* NETSNMP_FORCE_SYSTEM_V3_AUTHPRIV */
4925
4926
0
    properPrivKeyLen = pai->proper_length;
4927
0
    if (USM_CREATE_USER_PRIV_DES == pai->type)
4928
0
        properPrivKeyLen *= 2; /* ?? we store salt with key */
4929
4930
    /*
4931
     * READ: Encryption Pass Phrase or key
4932
     */
4933
0
    if (!cp) {
4934
        /*
4935
         * assume the same as the authentication key 
4936
         */
4937
0
        newuser->privKey = netsnmp_memdup(newuser->authKey,
4938
0
                                          newuser->authKeyLen);
4939
0
        privKeySize = newuser->privKeyLen = newuser->authKeyLen;
4940
0
        if (newuser->flags & USMUSER_FLAG_KEEP_MASTER_KEY) {
4941
0
            newuser->privKeyKu = netsnmp_memdup(newuser->authKeyKu,
4942
0
                                                newuser->authKeyKuLen);
4943
0
            newuser->privKeyKuLen = newuser->authKeyKuLen;
4944
0
        }
4945
0
    } else {
4946
0
        cp = copy_nword(cp, buf, sizeof(buf));
4947
        
4948
0
        if (strcmp(buf,"-m") == 0) {
4949
            /* a master key is specified */
4950
0
            cp = copy_nword(cp, buf, sizeof(buf));
4951
0
            ret = sizeof(userKey);
4952
0
            tmpp = userKey;
4953
0
            userKeyLen = 0;
4954
0
            if (!snmp_hex_to_binary(&tmpp, &ret, &userKeyLen, 0, buf)) {
4955
0
                *errorMsg = "invalid key value argument to -m";
4956
0
                goto fail;
4957
0
            }
4958
            /* save master key */
4959
0
            if (newuser->flags & USMUSER_FLAG_KEEP_MASTER_KEY) {
4960
0
                newuser->privKeyKu = netsnmp_memdup(userKey, userKeyLen);
4961
0
                newuser->privKeyKuLen = userKeyLen;
4962
0
            }
4963
0
        } else if (strcmp(buf,"-l") != 0) {
4964
            /* a password is specified */
4965
0
            userKeyLen = sizeof(userKey);
4966
0
            ret2 = generate_Ku(newuser->authProtocol, newuser->authProtocolLen,
4967
0
                              (u_char*)buf, strlen(buf), userKey, &userKeyLen);
4968
0
            if (ret2 != SNMPERR_SUCCESS) {
4969
0
                *errorMsg = "could not generate the privacy key from the supplied pass phrase.";
4970
0
                goto fail;
4971
0
            }
4972
            /* save master key */
4973
0
            if (newuser->flags & USMUSER_FLAG_KEEP_MASTER_KEY) {
4974
0
                newuser->privKeyKu = netsnmp_memdup(userKey, userKeyLen);
4975
0
                newuser->privKeyKuLen = userKeyLen;
4976
0
            }
4977
0
        }
4978
4979
        /*
4980
         * And turn it into a localized key
4981
         * Allocate enough space for greater of auth mac and privKey len.
4982
         */
4983
0
        privKeySize = SNMP_MAX(properPrivKeyLen, properLen);
4984
0
        newuser->privKey = (u_char *) malloc(privKeySize);
4985
0
        newuser->privKeyLen = privKeySize;
4986
4987
0
        if (strcmp(buf,"-l") == 0) {
4988
            /* a local key is directly specified */
4989
0
            cp = copy_nword(cp, buf, sizeof(buf));
4990
0
            ret = newuser->privKeyLen;
4991
0
            newuser->privKeyLen = 0;
4992
0
            if (!snmp_hex_to_binary(&newuser->privKey, &ret,
4993
0
                                    &newuser->privKeyLen, 0, buf)) {
4994
0
                *errorMsg = "invalid key value argument to -l";
4995
0
                goto fail;
4996
0
            }
4997
0
        } else {
4998
0
            ret2 = generate_kul(newuser->authProtocol, newuser->authProtocolLen,
4999
0
                               newuser->engineID, newuser->engineIDLen,
5000
0
                               userKey, userKeyLen,
5001
0
                               newuser->privKey, &newuser->privKeyLen);
5002
0
            if (ret2 != SNMPERR_SUCCESS) {
5003
0
                *errorMsg = "could not generate localized privacy key (Kul) from the master key (Ku).";
5004
0
                goto fail;
5005
0
            }
5006
0
        }
5007
5008
0
        if (newuser->privKeyLen < properPrivKeyLen) {
5009
0
            ret = usm_extend_user_kul(newuser, properPrivKeyLen);
5010
0
            if (ret != SNMPERR_SUCCESS) {
5011
0
                *errorMsg = "could not extend localized privacy key to required length.";
5012
0
                goto fail;
5013
0
            }
5014
0
        }
5015
0
    }
5016
5017
0
    if ((newuser->privKeyLen >= properPrivKeyLen) || (properPrivKeyLen == 0)){
5018
0
        DEBUGMSGTL(("9:usmUser", "truncating privKeyLen from %" NETSNMP_PRIz "d to %d\n",
5019
0
                    newuser->privKeyLen, properPrivKeyLen));
5020
0
        newuser->privKeyLen = properPrivKeyLen;
5021
0
    }
5022
0
    else {
5023
0
        DEBUGMSGTL(("usmUser",
5024
0
                    "privKey length %" NETSNMP_PRIz "d < %d required by privProtocol\n",
5025
0
                    newuser->privKeyLen, properPrivKeyLen));
5026
0
      *errorMsg = "privKey length is less than required by privProtocol";
5027
0
      goto fail;
5028
0
    }
5029
5030
0
  add:
5031
0
    usm_add_user(newuser);
5032
0
    DEBUGMSGTL(("usmUser", "created a new user %s at ", newuser->secName));
5033
0
    DEBUGMSGHEX(("usmUser", newuser->engineID, newuser->engineIDLen));
5034
0
    DEBUGMSG(("usmUser", "\n"));
5035
5036
0
    return newuser;
5037
5038
0
  fail:
5039
0
    usm_free_user(newuser);
5040
0
    return NULL;
5041
0
}
5042
5043
void
5044
usm_parse_create_usmUser(const char *token, char *line)
5045
0
{
5046
0
    const char *error = NULL;
5047
0
    usm_create_usmUser_from_string(line, &error);
5048
0
    if (error)
5049
0
        config_perror(error);
5050
0
}
5051
5052
static void
5053
snmpv3_authtype_conf(const char *word, char *cptr)
5054
72
{
5055
72
    int auth_type = usm_lookup_auth_type(cptr);
5056
72
    if (auth_type < 0)
5057
51
        config_perror("Unknown authentication type");
5058
72
    defaultAuthType = sc_get_auth_oid(auth_type, &defaultAuthTypeLen);
5059
72
    DEBUGMSGTL(("snmpv3", "set default authentication type: %s\n", cptr));
5060
72
}
5061
5062
const oid      *
5063
get_default_authtype(size_t * len)
5064
10.4k
{
5065
10.4k
    if (defaultAuthType == NULL) {
5066
8
        defaultAuthType = SNMP_DEFAULT_AUTH_PROTO;
5067
8
        defaultAuthTypeLen = SNMP_DEFAULT_AUTH_PROTOLEN;
5068
8
    }
5069
10.4k
    if (len)
5070
5.25k
        *len = defaultAuthTypeLen;
5071
10.4k
    return defaultAuthType;
5072
10.4k
}
5073
5074
static void
5075
snmpv3_privtype_conf(const char *word, char *cptr)
5076
70
{
5077
70
    int priv_type = usm_lookup_priv_type(cptr);
5078
70
    if (priv_type < 0)
5079
54
        config_perror("Unknown privacy type");
5080
70
    defaultPrivType = sc_get_priv_oid(priv_type, &defaultPrivTypeLen);
5081
70
    DEBUGMSGTL(("snmpv3", "set default privacy type: %s\n", cptr));
5082
70
}
5083
5084
const oid      *
5085
get_default_privtype(size_t * len)
5086
10.4k
{
5087
10.4k
    if (defaultPrivType == NULL) {
5088
7
        defaultPrivType = SNMP_DEFAULT_PRIV_PROTO;
5089
7
        defaultPrivTypeLen = SNMP_DEFAULT_PRIV_PROTOLEN;
5090
7
    }
5091
10.4k
    if (len)
5092
5.25k
        *len = defaultPrivTypeLen;
5093
10.4k
    return defaultPrivType;
5094
10.4k
}
5095
5096
void
5097
init_usm_conf(const char *app)
5098
3.39k
{
5099
3.39k
    register_config_handler(app, "usmUser",
5100
3.39k
                                  usm_parse_config_usmUser, NULL, NULL);
5101
3.39k
    register_config_handler(app, "createUser",
5102
3.39k
                                  usm_parse_create_usmUser, NULL,
5103
3.39k
                                  "username [-e ENGINEID] (MD5|SHA|SHA-512|SHA-384|SHA-256|SHA-224|default) authpassphrase [(DES|AES|default) [privpassphrase]]");
5104
5105
    /*
5106
     * we need to be called back later
5107
     */
5108
3.39k
    snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
5109
3.39k
                           usm_store_users, NULL);
5110
3.39k
}
5111
5112
/*
5113
 * initializations for the USM.
5114
 *
5115
 * Should be called after the (engineid) configuration files have been read.
5116
 *
5117
 * Set "arbitrary" portion of salt to a random number.
5118
 */
5119
static int
5120
init_usm_post_config(int majorid, int minorid, void *serverarg,
5121
                     void *clientarg)
5122
3.39k
{
5123
3.39k
    size_t          salt_integer_len = sizeof(salt_integer);
5124
3.39k
    uint64_t        current_time;
5125
5126
3.39k
    if (sc_random((u_char *) & salt_integer, &salt_integer_len) !=
5127
3.39k
        SNMPERR_SUCCESS) {
5128
0
        DEBUGMSGTL(("usm", "sc_random() failed: using time() as salt.\n"));
5129
0
        current_time = time(NULL);
5130
0
        salt_integer = current_time;
5131
0
    }
5132
5133
3.39k
#ifdef HAVE_AES
5134
3.39k
    salt_integer_len = sizeof (salt_integer64_1);
5135
3.39k
    if (sc_random((u_char *) & salt_integer64_1, &salt_integer_len) !=
5136
3.39k
        SNMPERR_SUCCESS) {
5137
0
        DEBUGMSGTL(("usm", "sc_random() failed: using time() as aes1 salt.\n"));
5138
0
        current_time = time(NULL);
5139
0
        salt_integer64_1 = current_time;
5140
0
    }
5141
3.39k
    salt_integer_len = sizeof (salt_integer64_1);
5142
3.39k
    if (sc_random((u_char *) & salt_integer64_2, &salt_integer_len) !=
5143
3.39k
        SNMPERR_SUCCESS) {
5144
0
        DEBUGMSGTL(("usm", "sc_random() failed: using time() as aes2 salt.\n"));
5145
0
        current_time = time(NULL);
5146
0
        salt_integer64_2 = current_time;
5147
0
    }
5148
3.39k
#endif
5149
5150
    // Free noNameUser before it is assigned
5151
3.39k
    usm_free_user(noNameUser);
5152
5153
3.39k
#ifndef NETSNMP_DISABLE_MD5
5154
3.39k
    noNameUser = usm_create_initial_user("", usmHMACMD5AuthProtocol,
5155
3.39k
                                         OID_LENGTH(usmHMACMD5AuthProtocol),
5156
3.39k
                                         SNMP_DEFAULT_PRIV_PROTO,
5157
3.39k
                                         SNMP_DEFAULT_PRIV_PROTOLEN);
5158
#else
5159
    noNameUser = usm_create_initial_user("", usmHMACSHA1AuthProtocol,
5160
                                         OID_LENGTH(usmHMACSHA1AuthProtocol),
5161
                                         SNMP_DEFAULT_PRIV_PROTO,
5162
                                         SNMP_DEFAULT_PRIV_PROTOLEN);
5163
#endif
5164
5165
3.39k
    if ( noNameUser ) {
5166
3.39k
        SNMP_FREE(noNameUser->engineID);
5167
3.39k
        noNameUser->engineIDLen = 0;
5168
3.39k
    }
5169
5170
3.39k
    return SNMPERR_SUCCESS;
5171
3.39k
}                               /* end init_usm_post_config() */
5172
5173
static int
5174
deinit_usm_post_config(int majorid, int minorid, void *serverarg,
5175
           void *clientarg)
5176
3.39k
{
5177
3.39k
    usm_free_user(noNameUser);
5178
3.39k
    noNameUser = NULL;
5179
5180
3.39k
    DEBUGMSGTL(("deinit_usm_post_config", "initial user removed\n"));
5181
3.39k
    return SNMPERR_SUCCESS;
5182
3.39k
}                               /* end deinit_usm_post_config() */
5183
5184
void
5185
init_usm(void)
5186
3.39k
{
5187
3.39k
    struct snmp_secmod_def *def;
5188
3.39k
    char *type;
5189
5190
3.39k
    DEBUGMSGTL(("init_usm", "unit_usm: %" NETSNMP_PRIo "u %" NETSNMP_PRIo "u\n",
5191
3.39k
                usmNoPrivProtocol[0], usmNoPrivProtocol[1]));
5192
5193
3.39k
    sc_init();                  /* initialize scapi code */
5194
5195
    /*
5196
     * register ourselves as a security service
5197
     */
5198
3.39k
    def = SNMP_MALLOC_STRUCT(snmp_secmod_def);
5199
3.39k
    if (def == NULL)
5200
0
        return;
5201
    /*
5202
     * XXX: def->init_sess_secmod move stuff from snmp_api.c
5203
     */
5204
3.39k
    def->encode_reverse = usm_secmod_rgenerate_out_msg;
5205
3.39k
    def->encode_forward = usm_secmod_generate_out_msg;
5206
3.39k
    def->decode = usm_secmod_process_in_msg;
5207
3.39k
    def->pdu_clone = usm_clone;
5208
3.39k
    def->pdu_free_state_ref = usm_free_usmStateReference;
5209
3.39k
    def->session_setup = usm_session_init;
5210
3.39k
    def->handle_report = usm_handle_report;
5211
3.39k
    def->probe_engineid = usm_discover_engineid;
5212
3.39k
    def->post_probe_engineid = usm_create_user_from_session_hook;
5213
3.39k
    if (register_sec_mod(USM_SEC_MODEL_NUMBER, "usm", def) != SNMPERR_SUCCESS) {
5214
0
        SNMP_FREE(def);
5215
0
        snmp_log(LOG_ERR, "could not register usm sec mod\n");
5216
0
        return;
5217
0
    }
5218
5219
3.39k
    snmp_register_callback(SNMP_CALLBACK_LIBRARY,
5220
3.39k
                           SNMP_CALLBACK_POST_PREMIB_READ_CONFIG,
5221
3.39k
                           init_usm_post_config, NULL);
5222
5223
3.39k
    snmp_register_callback(SNMP_CALLBACK_LIBRARY,
5224
3.39k
                           SNMP_CALLBACK_SHUTDOWN,
5225
3.39k
                           deinit_usm_post_config, NULL);
5226
5227
3.39k
    snmp_register_callback(SNMP_CALLBACK_LIBRARY,
5228
3.39k
                           SNMP_CALLBACK_SHUTDOWN,
5229
3.39k
                           free_engineID, NULL);
5230
5231
3.39k
    register_config_handler("snmp", "defAuthType", snmpv3_authtype_conf,
5232
3.39k
                            NULL, "MD5|SHA|SHA-512|SHA-384|SHA-256|SHA-224");
5233
3.39k
    register_config_handler("snmp", "defPrivType", snmpv3_privtype_conf,
5234
3.39k
                            NULL,
5235
3.39k
                            "DES"
5236
3.39k
#ifdef HAVE_AES
5237
3.39k
                            "|AES|AES-128"
5238
3.39k
#ifdef NETSNMP_DRAFT_BLUMENTHAL_AES_04
5239
3.39k
                            "|AES-192|AES-256"
5240
3.39k
#endif /* NETSNMP_DRAFT_BLUMENTHAL_AES_04 */
5241
#else
5242
                            " (AES support not available)"
5243
#endif
5244
3.39k
                           );
5245
5246
    /*
5247
     * Free stuff at shutdown time
5248
     */
5249
3.39k
    snmp_register_callback(SNMP_CALLBACK_LIBRARY,
5250
3.39k
                           SNMP_CALLBACK_SHUTDOWN,
5251
3.39k
                           free_enginetime_on_shutdown, NULL);
5252
5253
5254
3.39k
    type = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_APPTYPE);
5255
5256
3.39k
    register_config_handler(type, "userSetAuthPass", usm_set_password,
5257
3.39k
                            NULL, NULL);
5258
3.39k
    register_config_handler(type, "userSetPrivPass", usm_set_password,
5259
3.39k
                            NULL, NULL);
5260
3.39k
    register_config_handler(type, "userSetAuthKey", usm_set_password, NULL,
5261
3.39k
                            NULL);
5262
3.39k
    register_config_handler(type, "userSetPrivKey", usm_set_password, NULL,
5263
3.39k
                            NULL);
5264
3.39k
    register_config_handler(type, "userSetAuthLocalKey", usm_set_password,
5265
3.39k
                            NULL, NULL);
5266
3.39k
    register_config_handler(type, "userSetPrivLocalKey", usm_set_password,
5267
3.39k
                            NULL, NULL);
5268
3.39k
}
5269
5270
void
5271
shutdown_usm(void)
5272
6.79k
{
5273
6.79k
    free_etimelist();
5274
6.79k
    clear_user_list();
5275
6.79k
}