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