net-snmp 5.7
|
00001 /* Portions of this file are subject to the following copyright(s). See 00002 * the Net-SNMP's COPYING file for more details and other copyrights 00003 * that may apply: 00004 */ 00005 /* 00006 * Portions of this file are copyrighted by: 00007 * Copyright © 2003 Sun Microsystems, Inc. All rights reserved. 00008 * Use is subject to license terms specified in the COPYING file 00009 * distributed with the Net-SNMP package. 00010 */ 00011 /* 00012 * snmpusm.c 00013 * 00014 * Routines to manipulate a information about a "user" as 00015 * defined by the SNMP-USER-BASED-SM-MIB MIB. 00016 * 00017 * All functions usm_set_usmStateReference_*() return 0 on success, -1 00018 * otherwise. 00019 * 00020 * !! Tab stops set to 4 in some parts of this file. !! 00021 * (Designated on a per function.) 00022 */ 00023 00024 #include <net-snmp/net-snmp-config.h> 00025 #include <net-snmp/net-snmp-features.h> 00026 00027 #include <sys/types.h> 00028 #include <stdio.h> 00029 #ifdef HAVE_STDLIB_H 00030 #include <stdlib.h> 00031 #endif 00032 #if TIME_WITH_SYS_TIME 00033 # include <sys/time.h> 00034 # include <time.h> 00035 #else 00036 # if HAVE_SYS_TIME_H 00037 # include <sys/time.h> 00038 # else 00039 # include <time.h> 00040 # endif 00041 #endif 00042 #if HAVE_STRING_H 00043 #include <string.h> 00044 #else 00045 #include <strings.h> 00046 #endif 00047 #ifdef HAVE_NETINET_IN_H 00048 #include <netinet/in.h> 00049 #endif 00050 00051 #if HAVE_UNISTD_H 00052 #include <unistd.h> 00053 #endif 00054 #if HAVE_DMALLOC_H 00055 #include <dmalloc.h> 00056 #endif 00057 00058 #include <net-snmp/types.h> 00059 #include <net-snmp/output_api.h> 00060 #include <net-snmp/config_api.h> 00061 #include <net-snmp/utilities.h> 00062 00063 #include <net-snmp/library/asn1.h> 00064 #include <net-snmp/library/snmp_api.h> 00065 #include <net-snmp/library/callback.h> 00066 #include <net-snmp/library/tools.h> 00067 #include <net-snmp/library/keytools.h> 00068 #include <net-snmp/library/snmpv3.h> 00069 #include <net-snmp/library/lcd_time.h> 00070 #include <net-snmp/library/scapi.h> 00071 #include <net-snmp/library/callback.h> 00072 #include <net-snmp/library/snmp_secmod.h> 00073 #include <net-snmp/library/snmpusm.h> 00074 00075 netsnmp_feature_child_of(usm_all, libnetsnmp) 00076 netsnmp_feature_child_of(usm_support, usm_all) 00077 00078 netsnmp_feature_require(usm_support) 00079 00080 oid usmNoAuthProtocol[10] = { 1, 3, 6, 1, 6, 3, 10, 1, 1, 1 }; 00081 #ifndef NETSNMP_DISABLE_MD5 00082 oid usmHMACMD5AuthProtocol[10] = 00083 { 1, 3, 6, 1, 6, 3, 10, 1, 1, 2 }; 00084 #endif 00085 oid usmHMACSHA1AuthProtocol[10] = 00086 { 1, 3, 6, 1, 6, 3, 10, 1, 1, 3 }; 00087 oid usmNoPrivProtocol[10] = { 1, 3, 6, 1, 6, 3, 10, 1, 2, 1 }; 00088 #ifndef NETSNMP_DISABLE_DES 00089 oid usmDESPrivProtocol[10] = { 1, 3, 6, 1, 6, 3, 10, 1, 2, 2 }; 00090 #endif 00091 oid usmAESPrivProtocol[10] = { 1, 3, 6, 1, 6, 3, 10, 1, 2, 4 }; 00092 /* backwards compat */ 00093 oid *usmAES128PrivProtocol = usmAESPrivProtocol; 00094 00095 static u_int dummy_etime, dummy_eboot; /* For ISENGINEKNOWN(). */ 00096 00097 /* 00098 * Set up default snmpv3 parameter value storage. 00099 */ 00100 #ifdef NETSNMP_SECMOD_USM 00101 static const oid *defaultAuthType = NULL; 00102 static size_t defaultAuthTypeLen = 0; 00103 static const oid *defaultPrivType = NULL; 00104 static size_t defaultPrivTypeLen = 0; 00105 #endif /* NETSNMP_SECMOD_USM */ 00106 00107 /* 00108 * Globals. 00109 */ 00110 static u_int salt_integer; 00111 #ifdef HAVE_AES 00112 static u_int salt_integer64_1, salt_integer64_2; 00113 #endif 00114 /* 00115 * 1/2 of seed for the salt. Cf. RFC2274, Sect 8.1.1.1. 00116 */ 00117 00118 static struct usmUser *noNameUser = NULL; 00119 /* 00120 * Local storage (LCD) of the default user list. 00121 */ 00122 static struct usmUser *userList = NULL; 00123 00124 /* 00125 * Prototypes 00126 */ 00127 int 00128 usm_check_secLevel_vs_protocols(int level, 00129 const oid * authProtocol, 00130 u_int authProtocolLen, 00131 const oid * privProtocol, 00132 u_int privProtocolLen); 00133 int 00134 usm_calc_offsets(size_t globalDataLen, 00135 int secLevel, size_t secEngineIDLen, 00136 size_t secNameLen, size_t scopedPduLen, 00137 u_long engineboots, long engine_time, 00138 size_t * theTotalLength, 00139 size_t * authParamsOffset, 00140 size_t * privParamsOffset, 00141 size_t * dataOffset, size_t * datalen, 00142 size_t * msgAuthParmLen, 00143 size_t * msgPrivParmLen, size_t * otstlen, 00144 size_t * seq_len, size_t * msgSecParmLen); 00145 /* 00146 * Set a given field of the secStateRef. 00147 * 00148 * Allocate <len> bytes for type <type> pointed to by ref-><field>. 00149 * Then copy in <item> and record its length in ref-><field_len>. 00150 * 00151 * Return 0 on success, -1 otherwise. 00152 */ 00153 #define MAKE_ENTRY( type, item, len, field, field_len ) \ 00154 { \ 00155 if (ref == NULL) \ 00156 return -1; \ 00157 if (ref->field != NULL) { \ 00158 SNMP_ZERO(ref->field, ref->field_len); \ 00159 SNMP_FREE(ref->field); \ 00160 } \ 00161 ref->field_len = 0; \ 00162 if (len == 0 || item == NULL) { \ 00163 return 0; \ 00164 } \ 00165 if ((ref->field = (type*) malloc (len * sizeof(type))) == NULL) \ 00166 { \ 00167 return -1; \ 00168 } \ 00169 \ 00170 memcpy (ref->field, item, len * sizeof(type)); \ 00171 ref->field_len = len; \ 00172 \ 00173 return 0; \ 00174 } 00175 00176 00177 int 00178 free_enginetime_on_shutdown(int majorid, int minorid, void *serverarg, 00179 void *clientarg) 00180 { 00181 u_char engineID[SNMP_MAX_ENG_SIZE]; 00182 size_t engineID_len = sizeof(engineID); 00183 00184 DEBUGMSGTL(("snmpv3", "free enginetime callback called\n")); 00185 00186 engineID_len = snmpv3_get_engineID(engineID, engineID_len); 00187 if (engineID_len > 0) 00188 free_enginetime(engineID, engineID_len); 00189 return 0; 00190 } 00191 00192 struct usmStateReference * 00193 usm_malloc_usmStateReference(void) 00194 { 00195 struct usmStateReference *retval = (struct usmStateReference *) 00196 calloc(1, sizeof(struct usmStateReference)); 00197 00198 return retval; 00199 } /* end usm_malloc_usmStateReference() */ 00200 00201 00202 void 00203 usm_free_usmStateReference(void *old) 00204 { 00205 struct usmStateReference *old_ref = (struct usmStateReference *) old; 00206 00207 if (old_ref) { 00208 00209 SNMP_FREE(old_ref->usr_name); 00210 SNMP_FREE(old_ref->usr_engine_id); 00211 SNMP_FREE(old_ref->usr_auth_protocol); 00212 SNMP_FREE(old_ref->usr_priv_protocol); 00213 00214 if (old_ref->usr_auth_key) { 00215 SNMP_ZERO(old_ref->usr_auth_key, old_ref->usr_auth_key_length); 00216 SNMP_FREE(old_ref->usr_auth_key); 00217 } 00218 if (old_ref->usr_priv_key) { 00219 SNMP_ZERO(old_ref->usr_priv_key, old_ref->usr_priv_key_length); 00220 SNMP_FREE(old_ref->usr_priv_key); 00221 } 00222 00223 SNMP_ZERO(old_ref, sizeof(*old_ref)); 00224 SNMP_FREE(old_ref); 00225 00226 } 00227 00228 } /* end usm_free_usmStateReference() */ 00229 00230 struct usmUser * 00231 usm_get_userList(void) 00232 { 00233 return userList; 00234 } 00235 00236 int 00237 usm_set_usmStateReference_name(struct usmStateReference *ref, 00238 char *name, size_t name_len) 00239 { 00240 MAKE_ENTRY(char, name, name_len, usr_name, usr_name_length); 00241 } 00242 00243 int 00244 usm_set_usmStateReference_engine_id(struct usmStateReference *ref, 00245 u_char * engine_id, 00246 size_t engine_id_len) 00247 { 00248 MAKE_ENTRY(u_char, engine_id, engine_id_len, 00249 usr_engine_id, usr_engine_id_length); 00250 } 00251 00252 int 00253 usm_set_usmStateReference_auth_protocol(struct usmStateReference *ref, 00254 oid * auth_protocol, 00255 size_t auth_protocol_len) 00256 { 00257 MAKE_ENTRY(oid, auth_protocol, auth_protocol_len, 00258 usr_auth_protocol, usr_auth_protocol_length); 00259 } 00260 00261 int 00262 usm_set_usmStateReference_auth_key(struct usmStateReference *ref, 00263 u_char * auth_key, size_t auth_key_len) 00264 { 00265 MAKE_ENTRY(u_char, auth_key, auth_key_len, 00266 usr_auth_key, usr_auth_key_length); 00267 } 00268 00269 int 00270 usm_set_usmStateReference_priv_protocol(struct usmStateReference *ref, 00271 oid * priv_protocol, 00272 size_t priv_protocol_len) 00273 { 00274 MAKE_ENTRY(oid, priv_protocol, priv_protocol_len, 00275 usr_priv_protocol, usr_priv_protocol_length); 00276 } 00277 00278 int 00279 usm_set_usmStateReference_priv_key(struct usmStateReference *ref, 00280 u_char * priv_key, size_t priv_key_len) 00281 { 00282 MAKE_ENTRY(u_char, priv_key, priv_key_len, 00283 usr_priv_key, usr_priv_key_length); 00284 } 00285 00286 int 00287 usm_set_usmStateReference_sec_level(struct usmStateReference *ref, 00288 int sec_level) 00289 { 00290 if (ref == NULL) 00291 return -1; 00292 ref->usr_sec_level = sec_level; 00293 return 0; 00294 } 00295 00296 00297 00298 #ifdef NETSNMP_ENABLE_TESTING_CODE 00299 /*******************************************************************-o-****** 00300 * emergency_print 00301 * 00302 * Parameters: 00303 * *field 00304 * length 00305 * 00306 * This is a print routine that is solely included so that it can be 00307 * used in gdb. Don't use it as a function, it will be pulled before 00308 * a real release of the code. 00309 * 00310 * tab stop 4 00311 * 00312 * XXX fflush() only works on FreeBSD; core dumps on Sun OS's 00313 */ 00314 void 00315 emergency_print(u_char * field, u_int length) 00316 { 00317 int iindex; 00318 int start = 0; 00319 int stop = 25; 00320 00321 while (start < stop) { 00322 for (iindex = start; iindex < stop; iindex++) 00323 printf("%02X ", field[iindex]); 00324 00325 printf("\n"); 00326 start = stop; 00327 stop = stop + 25 < length ? stop + 25 : length; 00328 } 00329 fflush(0); 00330 00331 } /* end emergency_print() */ 00332 #endif /* NETSNMP_ENABLE_TESTING_CODE */ 00333 00334 00335 /*******************************************************************-o-****** 00336 * asn_predict_int_length 00337 * 00338 * Parameters: 00339 * type (UNUSED) 00340 * number 00341 * len 00342 * 00343 * Returns: 00344 * Number of bytes necessary to store the ASN.1 encoded value of 'number'. 00345 * 00346 * 00347 * This gives the number of bytes that the ASN.1 encoder (in asn1.c) will 00348 * use to encode a particular integer value. 00349 * 00350 * Returns the length of the integer -- NOT THE HEADER! 00351 * 00352 * Do this the same way as asn_build_int()... 00353 */ 00354 int 00355 asn_predict_int_length(int type, long number, size_t len) 00356 { 00357 register u_long mask; 00358 00359 00360 if (len != sizeof(long)) 00361 return -1; 00362 00363 mask = ((u_long) 0x1FF) << ((8 * (sizeof(long) - 1)) - 1); 00364 /* 00365 * mask is 0xFF800000 on a big-endian machine 00366 */ 00367 00368 while ((((number & mask) == 0) || ((number & mask) == mask)) 00369 && len > 1) { 00370 len--; 00371 number <<= 8; 00372 } 00373 00374 return len; 00375 00376 } /* end asn_predict_length() */ 00377 00378 00379 00380 00381 /*******************************************************************-o-****** 00382 * asn_predict_length 00383 * 00384 * Parameters: 00385 * type 00386 * *ptr 00387 * u_char_len 00388 * 00389 * Returns: 00390 * Length in bytes: 1 + <n> + <u_char_len>, where 00391 * 00392 * 1 For the ASN.1 type. 00393 * <n> # of bytes to store length of data. 00394 * <u_char_len> Length of data associated with ASN.1 type. 00395 * 00396 * This gives the number of bytes that the ASN.1 encoder (in asn1.c) will 00397 * use to encode a particular integer value. This is as broken as the 00398 * currently used encoder. 00399 * 00400 * XXX How is <n> chosen, exactly?? 00401 */ 00402 int 00403 asn_predict_length(int type, u_char * ptr, size_t u_char_len) 00404 { 00405 00406 if (type & ASN_SEQUENCE) 00407 return 1 + 3 + u_char_len; 00408 00409 if (type & ASN_INTEGER) { 00410 u_long value; 00411 memcpy(&value, ptr, u_char_len); 00412 u_char_len = asn_predict_int_length(type, value, u_char_len); 00413 } 00414 00415 if (u_char_len < 0x80) 00416 return 1 + 1 + u_char_len; 00417 else if (u_char_len < 0xFF) 00418 return 1 + 2 + u_char_len; 00419 else 00420 return 1 + 3 + u_char_len; 00421 00422 } /* end asn_predict_length() */ 00423 00424 00425 00426 00427 /*******************************************************************-o-****** 00428 * usm_calc_offsets 00429 * 00430 * Parameters: 00431 * (See list below...) 00432 * 00433 * Returns: 00434 * 0 On success, 00435 * -1 Otherwise. 00436 * 00437 * 00438 * This routine calculates the offsets into an outgoing message buffer 00439 * for the necessary values. The outgoing buffer will generically 00440 * look like this: 00441 * 00442 * SNMPv3 Message 00443 * SEQ len[11] 00444 * INT len version 00445 * Header 00446 * SEQ len 00447 * INT len MsgID 00448 * INT len msgMaxSize 00449 * OST len msgFlags (OST = OCTET STRING) 00450 * INT len msgSecurityModel 00451 * MsgSecurityParameters 00452 * [1] OST len[2] 00453 * SEQ len[3] 00454 * OST len msgAuthoritativeEngineID 00455 * INT len msgAuthoritativeEngineBoots 00456 * INT len msgAuthoritativeEngineTime 00457 * OST len msgUserName 00458 * OST len[4] [5] msgAuthenticationParameters 00459 * OST len[6] [7] msgPrivacyParameters 00460 * MsgData 00461 * [8] OST len[9] [10] encryptedPDU 00462 * or 00463 * [8,10] SEQUENCE len[9] scopedPDU 00464 * [12] 00465 * 00466 * The bracketed points will be needed to be identified ([x] is an index 00467 * value, len[x] means a length value). Here is a semantic guide to them: 00468 * 00469 * [1] = globalDataLen (input) 00470 * [2] = otstlen 00471 * [3] = seq_len 00472 * [4] = msgAuthParmLen (may be 0 or 12) 00473 * [5] = authParamsOffset 00474 * [6] = msgPrivParmLen (may be 0 or 8) 00475 * [7] = privParamsOffset 00476 * [8] = globalDataLen + msgSecParmLen 00477 * [9] = datalen 00478 * [10] = dataOffset 00479 * [11] = theTotalLength - the length of the header itself 00480 * [12] = theTotalLength 00481 */ 00482 int 00483 usm_calc_offsets(size_t globalDataLen, /* SNMPv3Message + HeaderData */ 00484 int secLevel, size_t secEngineIDLen, size_t secNameLen, size_t scopedPduLen, /* An BER encoded sequence. */ 00485 u_long engineboots, /* XXX (asn1.c works in long, not int.) */ 00486 long engine_time, /* XXX (asn1.c works in long, not int.) */ 00487 size_t * theTotalLength, /* globalDataLen + msgSecurityP. + msgData */ 00488 size_t * authParamsOffset, /* Distance to auth bytes. */ 00489 size_t * privParamsOffset, /* Distance to priv bytes. */ 00490 size_t * dataOffset, /* Distance to scopedPdu SEQ -or- the 00491 * crypted (data) portion of msgData. */ 00492 size_t * datalen, /* Size of msgData OCTET STRING encoding. */ 00493 size_t * msgAuthParmLen, /* Size of msgAuthenticationParameters. */ 00494 size_t * msgPrivParmLen, /* Size of msgPrivacyParameters. */ 00495 size_t * otstlen, /* Size of msgSecurityP. O.S. encoding. */ 00496 size_t * seq_len, /* Size of msgSecurityP. SEQ data. */ 00497 size_t * msgSecParmLen) 00498 { /* Size of msgSecurityP. SEQ. */ 00499 int engIDlen, /* Sizes of OCTET STRING and SEQ encodings */ 00500 engBtlen, /* for fields within */ 00501 engTmlen, /* msgSecurityParameters portion of */ 00502 namelen, /* SNMPv3Message. */ 00503 authlen, privlen, ret; 00504 00505 /* 00506 * If doing authentication, msgAuthParmLen = 12 else msgAuthParmLen = 0. 00507 * If doing encryption, msgPrivParmLen = 8 else msgPrivParmLen = 0. 00508 */ 00509 *msgAuthParmLen = (secLevel == SNMP_SEC_LEVEL_AUTHNOPRIV 00510 || secLevel == SNMP_SEC_LEVEL_AUTHPRIV) ? 12 : 0; 00511 00512 *msgPrivParmLen = (secLevel == SNMP_SEC_LEVEL_AUTHPRIV) ? 8 : 0; 00513 00514 00515 /* 00516 * Calculate lengths. 00517 */ 00518 if ((engIDlen = asn_predict_length(ASN_OCTET_STR, 00519 NULL, secEngineIDLen)) == -1) { 00520 return -1; 00521 } 00522 00523 if ((engBtlen = asn_predict_length(ASN_INTEGER, 00524 (u_char *) & engineboots, 00525 sizeof(long))) == -1) { 00526 return -1; 00527 } 00528 00529 if ((engTmlen = asn_predict_length(ASN_INTEGER, 00530 (u_char *) & engine_time, 00531 sizeof(long))) == -1) { 00532 return -1; 00533 } 00534 00535 if ((namelen = asn_predict_length(ASN_OCTET_STR, 00536 NULL, secNameLen)) == -1) { 00537 return -1; 00538 } 00539 00540 if ((authlen = asn_predict_length(ASN_OCTET_STR, 00541 NULL, *msgAuthParmLen)) == -1) { 00542 return -1; 00543 } 00544 00545 if ((privlen = asn_predict_length(ASN_OCTET_STR, 00546 NULL, *msgPrivParmLen)) == -1) { 00547 return -1; 00548 } 00549 00550 *seq_len = 00551 engIDlen + engBtlen + engTmlen + namelen + authlen + privlen; 00552 00553 if ((ret = asn_predict_length(ASN_SEQUENCE, 00554 NULL, *seq_len)) == -1) { 00555 return -1; 00556 } 00557 *otstlen = (size_t)ret; 00558 00559 if ((ret = asn_predict_length(ASN_OCTET_STR, 00560 NULL, *otstlen)) == -1) { 00561 return -1; 00562 } 00563 *msgSecParmLen = (size_t)ret; 00564 00565 *authParamsOffset = globalDataLen + +(*msgSecParmLen - *seq_len) 00566 + engIDlen + engBtlen + engTmlen + namelen 00567 + (authlen - *msgAuthParmLen); 00568 00569 *privParamsOffset = *authParamsOffset + *msgAuthParmLen 00570 + (privlen - *msgPrivParmLen); 00571 00572 00573 /* 00574 * Compute the size of the plaintext. Round up to account for cipher 00575 * block size, if necessary. 00576 * 00577 * XXX This is hardwired for 1DES... If scopedPduLen is already 00578 * a multiple of 8, then *add* 8 more; otherwise, round up 00579 * to the next multiple of 8. 00580 * 00581 * FIX Calculation of encrypted portion of msgData and consequent 00582 * setting and sanity checking of theTotalLength, et al. should 00583 * occur *after* encryption has taken place. 00584 */ 00585 if (secLevel == SNMP_SEC_LEVEL_AUTHPRIV) { 00586 scopedPduLen = ROUNDUP8(scopedPduLen); 00587 00588 if ((ret = asn_predict_length(ASN_OCTET_STR, NULL, scopedPduLen)) == -1) { 00589 return -1; 00590 } 00591 *datalen = (size_t)ret; 00592 } else { 00593 *datalen = scopedPduLen; 00594 } 00595 00596 *dataOffset = globalDataLen + *msgSecParmLen + 00597 (*datalen - scopedPduLen); 00598 *theTotalLength = globalDataLen + *msgSecParmLen + *datalen; 00599 00600 return 0; 00601 00602 } /* end usm_calc_offsets() */ 00603 00604 00605 00606 00607 00608 #ifndef NETSNMP_DISABLE_DES 00609 /*******************************************************************-o-****** 00610 * usm_set_salt 00611 * 00612 * Parameters: 00613 * *iv (O) Buffer to contain IV. 00614 * *iv_length (O) Length of iv. 00615 * *priv_salt (I) Salt portion of private key. 00616 * priv_salt_length (I) Length of priv_salt. 00617 * *msgSalt (I/O) Pointer salt portion of outgoing msg buffer. 00618 * 00619 * Returns: 00620 * 0 On success, 00621 * -1 Otherwise. 00622 * 00623 * Determine the initialization vector for the DES-CBC encryption. 00624 * (Cf. RFC 2274, 8.1.1.1.) 00625 * 00626 * iv is defined as the concatenation of engineBoots and the 00627 * salt integer. 00628 * The salt integer is incremented. 00629 * The resulting salt is copied into the msgSalt buffer. 00630 * The result of the concatenation is then XORed with the salt 00631 * portion of the private key (last 8 bytes). 00632 * The IV result is returned individually for further use. 00633 */ 00634 int 00635 usm_set_salt(u_char * iv, 00636 size_t * iv_length, 00637 u_char * priv_salt, size_t priv_salt_length, u_char * msgSalt) 00638 { 00639 size_t propersize_salt = BYTESIZE(USM_DES_SALT_LENGTH); 00640 int net_boots; 00641 int net_salt_int; 00642 /* 00643 * net_* should be encoded in network byte order. XXX Why? 00644 */ 00645 int iindex; 00646 00647 00648 /* 00649 * Sanity check. 00650 */ 00651 if (!iv || !iv_length || !priv_salt || (*iv_length != propersize_salt) 00652 || (priv_salt_length < propersize_salt)) { 00653 return -1; 00654 } 00655 00656 00657 net_boots = htonl(snmpv3_local_snmpEngineBoots()); 00658 net_salt_int = htonl(salt_integer); 00659 00660 salt_integer += 1; 00661 00662 memcpy(iv, &net_boots, propersize_salt / 2); 00663 memcpy(iv + (propersize_salt / 2), &net_salt_int, propersize_salt / 2); 00664 00665 if (msgSalt) 00666 memcpy(msgSalt, iv, propersize_salt); 00667 00668 00669 /* 00670 * Turn the salt into an IV: XOR <boots, salt_int> with salt 00671 * portion of priv_key. 00672 */ 00673 for (iindex = 0; iindex < (int) propersize_salt; iindex++) 00674 iv[iindex] ^= priv_salt[iindex]; 00675 00676 00677 return 0; 00678 00679 } /* end usm_set_salt() */ 00680 #endif 00681 00682 #ifdef HAVE_AES 00683 /*******************************************************************-o-****** 00684 * usm_set_aes_iv 00685 * 00686 * Parameters: 00687 * *iv (O) Buffer to contain IV. 00688 * *iv_length (O) Length of iv. 00689 * net_boots (I) the network byte order of the authEng boots val 00690 * net_time (I) the network byte order of the authEng time val 00691 * *salt (O) A buffer for the outgoing salt (= 8 bytes of iv) 00692 * 00693 * Returns: 00694 * 0 On success, 00695 * -1 Otherwise. 00696 * 00697 * Determine the initialization vector for AES encryption. 00698 * (draft-blumenthal-aes-usm-03.txt, 3.1.2.2) 00699 * 00700 * iv is defined as the concatenation of engineBoots, engineTime 00701 and a 64 bit salt-integer. 00702 * The 64 bit salt integer is incremented. 00703 * The resulting salt is copied into the salt buffer. 00704 * The IV result is returned individually for further use. 00705 */ 00706 int 00707 usm_set_aes_iv(u_char * iv, 00708 size_t * iv_length, 00709 u_int net_boots, 00710 u_int net_time, 00711 u_char * salt) 00712 { 00713 /* 00714 * net_* should be encoded in network byte order. 00715 */ 00716 int net_salt_int1, net_salt_int2; 00717 #define PROPER_AES_IV_SIZE 64 00718 00719 /* 00720 * Sanity check. 00721 */ 00722 if (!iv || !iv_length) { 00723 return -1; 00724 } 00725 00726 net_salt_int1 = htonl(salt_integer64_1); 00727 net_salt_int2 = htonl(salt_integer64_2); 00728 00729 if ((salt_integer64_2 += 1) == 0) 00730 salt_integer64_2 += 1; 00731 00732 /* XXX: warning: hard coded proper lengths */ 00733 memcpy(iv, &net_boots, 4); 00734 memcpy(iv+4, &net_time, 4); 00735 memcpy(iv+8, &net_salt_int1, 4); 00736 memcpy(iv+12, &net_salt_int2, 4); 00737 00738 memcpy(salt, iv+8, 8); /* only copy the needed portion */ 00739 return 0; 00740 } /* end usm_set_salt() */ 00741 #endif /* HAVE_AES */ 00742 00743 int 00744 usm_secmod_generate_out_msg(struct snmp_secmod_outgoing_params *parms) 00745 { 00746 if (!parms) 00747 return SNMPERR_GENERR; 00748 00749 return usm_generate_out_msg(parms->msgProcModel, 00750 parms->globalData, parms->globalDataLen, 00751 parms->maxMsgSize, parms->secModel, 00752 parms->secEngineID, parms->secEngineIDLen, 00753 parms->secName, parms->secNameLen, 00754 parms->secLevel, 00755 parms->scopedPdu, parms->scopedPduLen, 00756 parms->secStateRef, 00757 parms->secParams, parms->secParamsLen, 00758 parms->wholeMsg, parms->wholeMsgLen); 00759 } 00760 00761 /*******************************************************************-o-****** 00762 * usm_generate_out_msg 00763 * 00764 * Parameters: 00765 * (See list below...) 00766 * 00767 * Returns: 00768 * SNMPERR_SUCCESS On success. 00769 * SNMPERR_USM_AUTHENTICATIONFAILURE 00770 * SNMPERR_USM_ENCRYPTIONERROR 00771 * SNMPERR_USM_GENERICERROR 00772 * SNMPERR_USM_UNKNOWNSECURITYNAME 00773 * SNMPERR_USM_GENERICERROR 00774 * SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL 00775 * 00776 * 00777 * Generates an outgoing message. 00778 * 00779 * XXX Beware of misnomers! 00780 */ 00781 int 00782 usm_generate_out_msg(int msgProcModel, /* (UNUSED) */ 00783 u_char * globalData, /* IN */ 00784 /* 00785 * Pointer to msg header data will point to the beginning 00786 * * of the entire packet buffer to be transmitted on wire, 00787 * * memory will be contiguous with secParams, typically 00788 * * this pointer will be passed back as beginning of 00789 * * wholeMsg below. asn seq. length is updated w/ new length. 00790 * * 00791 * * While this points to a buffer that should be big enough 00792 * * for the whole message, only the first two parts 00793 * * of the message are completed, namely SNMPv3Message and 00794 * * HeaderData. globalDataLen (next parameter) represents 00795 * * the length of these two completed parts. 00796 */ 00797 size_t globalDataLen, /* IN - Length of msg header data. */ 00798 int maxMsgSize, /* (UNUSED) */ 00799 int secModel, /* (UNUSED) */ 00800 u_char * secEngineID, /* IN - Pointer snmpEngineID. */ 00801 size_t secEngineIDLen, /* IN - SnmpEngineID length. */ 00802 char *secName, /* IN - Pointer to securityName. */ 00803 size_t secNameLen, /* IN - SecurityName length. */ 00804 int secLevel, /* IN - AuthNoPriv, authPriv etc. */ 00805 u_char * scopedPdu, /* IN */ 00806 /* 00807 * Pointer to scopedPdu will be encrypted by USM if needed 00808 * * and written to packet buffer immediately following 00809 * * securityParameters, entire msg will be authenticated by 00810 * * USM if needed. 00811 */ 00812 size_t scopedPduLen, /* IN - scopedPdu length. */ 00813 void *secStateRef, /* IN */ 00814 /* 00815 * secStateRef, pointer to cached info provided only for 00816 * * Response, otherwise NULL. 00817 */ 00818 u_char * secParams, /* OUT */ 00819 /* 00820 * BER encoded securityParameters pointer to offset within 00821 * * packet buffer where secParams should be written, the 00822 * * entire BER encoded OCTET STRING (including header) is 00823 * * written here by USM secParams = globalData + 00824 * * globalDataLen. 00825 */ 00826 size_t * secParamsLen, /* IN/OUT - Len available, len returned. */ 00827 u_char ** wholeMsg, /* OUT */ 00828 /* 00829 * Complete authenticated/encrypted message - typically 00830 * * the pointer to start of packet buffer provided in 00831 * * globalData is returned here, could also be a separate 00832 * * buffer. 00833 */ 00834 size_t * wholeMsgLen) 00835 { /* IN/OUT - Len available, len returned. */ 00836 size_t otstlen; 00837 size_t seq_len; 00838 size_t msgAuthParmLen; 00839 size_t msgPrivParmLen; 00840 size_t msgSecParmLen; 00841 size_t authParamsOffset; 00842 size_t privParamsOffset; 00843 size_t datalen; 00844 size_t dataOffset; 00845 size_t theTotalLength; 00846 00847 u_char *ptr; 00848 size_t ptr_len; 00849 size_t remaining; 00850 size_t offSet; 00851 u_int boots_uint; 00852 u_int time_uint; 00853 long boots_long; 00854 long time_long; 00855 00856 /* 00857 * Indirection because secStateRef values override parameters. 00858 * 00859 * None of these are to be free'd - they are either pointing to 00860 * what's in the secStateRef or to something either in the 00861 * actual prarmeter list or the user list. 00862 */ 00863 00864 char *theName = NULL; 00865 u_int theNameLength = 0; 00866 u_char *theEngineID = NULL; 00867 u_int theEngineIDLength = 0; 00868 u_char *theAuthKey = NULL; 00869 u_int theAuthKeyLength = 0; 00870 const oid *theAuthProtocol = NULL; 00871 u_int theAuthProtocolLength = 0; 00872 u_char *thePrivKey = NULL; 00873 u_int thePrivKeyLength = 0; 00874 const oid *thePrivProtocol = NULL; 00875 u_int thePrivProtocolLength = 0; 00876 int theSecLevel = 0; /* No defined const for bad 00877 * value (other then err). 00878 */ 00879 00880 DEBUGMSGTL(("usm", "USM processing has begun.\n")); 00881 00882 if (secStateRef != NULL) { 00883 /* 00884 * To hush the compiler for now. XXX 00885 */ 00886 struct usmStateReference *ref 00887 = (struct usmStateReference *) secStateRef; 00888 00889 theName = ref->usr_name; 00890 theNameLength = ref->usr_name_length; 00891 theEngineID = ref->usr_engine_id; 00892 theEngineIDLength = ref->usr_engine_id_length; 00893 00894 if (!theEngineIDLength) { 00895 theEngineID = secEngineID; 00896 theEngineIDLength = secEngineIDLen; 00897 } 00898 00899 theAuthProtocol = ref->usr_auth_protocol; 00900 theAuthProtocolLength = ref->usr_auth_protocol_length; 00901 theAuthKey = ref->usr_auth_key; 00902 theAuthKeyLength = ref->usr_auth_key_length; 00903 thePrivProtocol = ref->usr_priv_protocol; 00904 thePrivProtocolLength = ref->usr_priv_protocol_length; 00905 thePrivKey = ref->usr_priv_key; 00906 thePrivKeyLength = ref->usr_priv_key_length; 00907 theSecLevel = ref->usr_sec_level; 00908 } 00909 00910 /* 00911 * Identify the user record. 00912 */ 00913 else { 00914 struct usmUser *user; 00915 00916 /* 00917 * we do allow an unknown user name for 00918 * unauthenticated requests. 00919 */ 00920 if ((user = usm_get_user(secEngineID, secEngineIDLen, secName)) 00921 == NULL && secLevel != SNMP_SEC_LEVEL_NOAUTH) { 00922 DEBUGMSGTL(("usm", "Unknown User(%s)\n", secName)); 00923 usm_free_usmStateReference(secStateRef); 00924 return SNMPERR_USM_UNKNOWNSECURITYNAME; 00925 } 00926 00927 theName = secName; 00928 theNameLength = secNameLen; 00929 theEngineID = secEngineID; 00930 theSecLevel = secLevel; 00931 theEngineIDLength = secEngineIDLen; 00932 if (user) { 00933 theAuthProtocol = user->authProtocol; 00934 theAuthProtocolLength = user->authProtocolLen; 00935 theAuthKey = user->authKey; 00936 theAuthKeyLength = user->authKeyLen; 00937 thePrivProtocol = user->privProtocol; 00938 thePrivProtocolLength = user->privProtocolLen; 00939 thePrivKey = user->privKey; 00940 thePrivKeyLength = user->privKeyLen; 00941 } else { 00942 /* 00943 * unknown users can not do authentication (obviously) 00944 */ 00945 theAuthProtocol = usmNoAuthProtocol; 00946 theAuthProtocolLength = 00947 sizeof(usmNoAuthProtocol) / sizeof(oid); 00948 theAuthKey = NULL; 00949 theAuthKeyLength = 0; 00950 thePrivProtocol = usmNoPrivProtocol; 00951 thePrivProtocolLength = 00952 sizeof(usmNoPrivProtocol) / sizeof(oid); 00953 thePrivKey = NULL; 00954 thePrivKeyLength = 0; 00955 } 00956 } /* endif -- secStateRef==NULL */ 00957 00958 00959 /* 00960 * From here to the end of the function, avoid reference to 00961 * secName, secEngineID, secLevel, and associated lengths. 00962 */ 00963 00964 00965 /* 00966 * Check to see if the user can use the requested sec services. 00967 */ 00968 if (usm_check_secLevel_vs_protocols(theSecLevel, 00969 theAuthProtocol, 00970 theAuthProtocolLength, 00971 thePrivProtocol, 00972 thePrivProtocolLength) == 1) { 00973 DEBUGMSGTL(("usm", "Unsupported Security Level (%d)\n", 00974 theSecLevel)); 00975 usm_free_usmStateReference(secStateRef); 00976 return SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL; 00977 } 00978 00979 00980 /* 00981 * Retrieve the engine information. 00982 * 00983 * XXX No error is declared in the EoP when sending messages to 00984 * unknown engines, processing continues w/ boots/time == (0,0). 00985 */ 00986 if (get_enginetime(theEngineID, theEngineIDLength, 00987 &boots_uint, &time_uint, FALSE) == -1) { 00988 DEBUGMSGTL(("usm", "%s\n", "Failed to find engine data.")); 00989 } 00990 00991 boots_long = boots_uint; 00992 time_long = time_uint; 00993 00994 00995 /* 00996 * Set up the Offsets. 00997 */ 00998 if (usm_calc_offsets(globalDataLen, theSecLevel, theEngineIDLength, 00999 theNameLength, scopedPduLen, boots_long, 01000 time_long, &theTotalLength, &authParamsOffset, 01001 &privParamsOffset, &dataOffset, &datalen, 01002 &msgAuthParmLen, &msgPrivParmLen, &otstlen, 01003 &seq_len, &msgSecParmLen) == -1) { 01004 DEBUGMSGTL(("usm", "Failed calculating offsets.\n")); 01005 usm_free_usmStateReference(secStateRef); 01006 return SNMPERR_USM_GENERICERROR; 01007 } 01008 01009 /* 01010 * So, we have the offsets for the three parts that need to be 01011 * determined, and an overall length. Now we need to make 01012 * sure all of this would fit in the outgoing buffer, and 01013 * whether or not we need to make a new buffer, etc. 01014 */ 01015 01016 01017 /* 01018 * Set wholeMsg as a pointer to globalData. Sanity check for 01019 * the proper size. 01020 * 01021 * Mark workspace in the message with bytes of all 1's to make it 01022 * easier to find mistakes in raw message dumps. 01023 */ 01024 ptr = *wholeMsg = globalData; 01025 if (theTotalLength > *wholeMsgLen) { 01026 DEBUGMSGTL(("usm", "Message won't fit in buffer.\n")); 01027 usm_free_usmStateReference(secStateRef); 01028 return SNMPERR_USM_GENERICERROR; 01029 } 01030 01031 ptr_len = *wholeMsgLen = theTotalLength; 01032 01033 #ifdef NETSNMP_ENABLE_TESTING_CODE 01034 memset(&ptr[globalDataLen], 0xFF, theTotalLength - globalDataLen); 01035 #endif /* NETSNMP_ENABLE_TESTING_CODE */ 01036 01037 /* 01038 * Do the encryption. 01039 */ 01040 if (theSecLevel == SNMP_SEC_LEVEL_AUTHPRIV) { 01041 size_t encrypted_length = theTotalLength - dataOffset; 01042 size_t salt_length = BYTESIZE(USM_MAX_SALT_LENGTH); 01043 u_char salt[BYTESIZE(USM_MAX_SALT_LENGTH)]; 01044 01045 /* 01046 * XXX Hardwired to seek into a 1DES private key! 01047 */ 01048 #ifdef HAVE_AES 01049 if (ISTRANSFORM(thePrivProtocol, AESPriv)) { 01050 if (!thePrivKey || 01051 usm_set_aes_iv(salt, &salt_length, 01052 htonl(boots_uint), htonl(time_uint), 01053 &ptr[privParamsOffset]) == -1) { 01054 DEBUGMSGTL(("usm", "Can't set AES iv.\n")); 01055 usm_free_usmStateReference(secStateRef); 01056 return SNMPERR_USM_GENERICERROR; 01057 } 01058 } 01059 #endif 01060 #ifndef NETSNMP_DISABLE_DES 01061 if (ISTRANSFORM(thePrivProtocol, DESPriv)) { 01062 if (!thePrivKey || 01063 (usm_set_salt(salt, &salt_length, 01064 thePrivKey + 8, thePrivKeyLength - 8, 01065 &ptr[privParamsOffset]) 01066 == -1)) { 01067 DEBUGMSGTL(("usm", "Can't set DES-CBC salt.\n")); 01068 usm_free_usmStateReference(secStateRef); 01069 return SNMPERR_USM_GENERICERROR; 01070 } 01071 } 01072 #endif 01073 01074 if (sc_encrypt(thePrivProtocol, thePrivProtocolLength, 01075 thePrivKey, thePrivKeyLength, 01076 salt, salt_length, 01077 scopedPdu, scopedPduLen, 01078 &ptr[dataOffset], &encrypted_length) 01079 != SNMP_ERR_NOERROR) { 01080 DEBUGMSGTL(("usm", "encryption error.\n")); 01081 usm_free_usmStateReference(secStateRef); 01082 return SNMPERR_USM_ENCRYPTIONERROR; 01083 } 01084 #ifdef NETSNMP_ENABLE_TESTING_CODE 01085 if (debug_is_token_registered("usm/dump") == SNMPERR_SUCCESS) { 01086 dump_chunk("usm/dump", "This data was encrypted:", 01087 scopedPdu, scopedPduLen); 01088 dump_chunk("usm/dump", "salt + Encrypted form:", 01089 salt, salt_length); 01090 dump_chunk("usm/dump", NULL, 01091 &ptr[dataOffset], encrypted_length); 01092 dump_chunk("usm/dump", "*wholeMsg:", 01093 *wholeMsg, theTotalLength); 01094 } 01095 #endif 01096 01097 01098 ptr = *wholeMsg; 01099 ptr_len = *wholeMsgLen = theTotalLength; 01100 01101 01102 /* 01103 * XXX Sanity check for salt length should be moved up 01104 * under usm_calc_offsets() or tossed. 01105 */ 01106 if ((encrypted_length != (theTotalLength - dataOffset)) 01107 || (salt_length != msgPrivParmLen)) { 01108 DEBUGMSGTL(("usm", "encryption length error.\n")); 01109 usm_free_usmStateReference(secStateRef); 01110 return SNMPERR_USM_ENCRYPTIONERROR; 01111 } 01112 01113 DEBUGMSGTL(("usm", "Encryption successful.\n")); 01114 } 01115 01116 /* 01117 * No encryption for you! 01118 */ 01119 else { 01120 memcpy(&ptr[dataOffset], scopedPdu, scopedPduLen); 01121 } 01122 01123 01124 01125 /* 01126 * Start filling in the other fields (in prep for authentication). 01127 * 01128 * offSet is an octet string header, which is different from all 01129 * the other headers. 01130 */ 01131 remaining = ptr_len - globalDataLen; 01132 01133 offSet = ptr_len - remaining; 01134 asn_build_header(&ptr[offSet], &remaining, 01135 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | 01136 ASN_OCTET_STR), otstlen); 01137 01138 offSet = ptr_len - remaining; 01139 asn_build_sequence(&ptr[offSet], &remaining, 01140 (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), seq_len); 01141 01142 offSet = ptr_len - remaining; 01143 DEBUGDUMPHEADER("send", "msgAuthoritativeEngineID"); 01144 asn_build_string(&ptr[offSet], &remaining, 01145 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | 01146 ASN_OCTET_STR), theEngineID, 01147 theEngineIDLength); 01148 DEBUGINDENTLESS(); 01149 01150 offSet = ptr_len - remaining; 01151 DEBUGDUMPHEADER("send", "msgAuthoritativeEngineBoots"); 01152 asn_build_int(&ptr[offSet], &remaining, 01153 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), 01154 &boots_long, sizeof(long)); 01155 DEBUGINDENTLESS(); 01156 01157 offSet = ptr_len - remaining; 01158 DEBUGDUMPHEADER("send", "msgAuthoritativeEngineTime"); 01159 asn_build_int(&ptr[offSet], &remaining, 01160 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), 01161 &time_long, sizeof(long)); 01162 DEBUGINDENTLESS(); 01163 01164 offSet = ptr_len - remaining; 01165 DEBUGDUMPHEADER("send", "msgUserName"); 01166 asn_build_string(&ptr[offSet], &remaining, 01167 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | 01168 ASN_OCTET_STR), (u_char *) theName, 01169 theNameLength); 01170 DEBUGINDENTLESS(); 01171 01172 01173 /* 01174 * Note: if there is no authentication being done, 01175 * msgAuthParmLen is 0, and there is no effect (other than 01176 * inserting a zero-length header) of the following 01177 * statements. 01178 */ 01179 01180 offSet = ptr_len - remaining; 01181 asn_build_header(&ptr[offSet], 01182 &remaining, 01183 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | 01184 ASN_OCTET_STR), msgAuthParmLen); 01185 01186 if (theSecLevel == SNMP_SEC_LEVEL_AUTHNOPRIV 01187 || theSecLevel == SNMP_SEC_LEVEL_AUTHPRIV) { 01188 offSet = ptr_len - remaining; 01189 memset(&ptr[offSet], 0, msgAuthParmLen); 01190 } 01191 01192 remaining -= msgAuthParmLen; 01193 01194 01195 /* 01196 * Note: if there is no encryption being done, msgPrivParmLen 01197 * is 0, and there is no effect (other than inserting a 01198 * zero-length header) of the following statements. 01199 */ 01200 01201 offSet = ptr_len - remaining; 01202 asn_build_header(&ptr[offSet], 01203 &remaining, 01204 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | 01205 ASN_OCTET_STR), msgPrivParmLen); 01206 01207 remaining -= msgPrivParmLen; /* Skipping the IV already there. */ 01208 01209 01210 /* 01211 * For privacy, need to add the octet string header for it. 01212 */ 01213 if (theSecLevel == SNMP_SEC_LEVEL_AUTHPRIV) { 01214 offSet = ptr_len - remaining; 01215 asn_build_header(&ptr[offSet], 01216 &remaining, 01217 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | 01218 ASN_OCTET_STR), 01219 theTotalLength - dataOffset); 01220 } 01221 01222 01223 /* 01224 * Adjust overall length and store it as the first SEQ length 01225 * of the SNMPv3Message. 01226 * 01227 * FIX 4 is a magic number! 01228 */ 01229 remaining = theTotalLength; 01230 asn_build_sequence(ptr, &remaining, 01231 (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), 01232 theTotalLength - 4); 01233 01234 01235 /* 01236 * Now, time to consider / do authentication. 01237 */ 01238 if (theSecLevel == SNMP_SEC_LEVEL_AUTHNOPRIV 01239 || theSecLevel == SNMP_SEC_LEVEL_AUTHPRIV) { 01240 size_t temp_sig_len = msgAuthParmLen; 01241 u_char *temp_sig = (u_char *) malloc(temp_sig_len); 01242 01243 if (temp_sig == NULL) { 01244 DEBUGMSGTL(("usm", "Out of memory.\n")); 01245 usm_free_usmStateReference(secStateRef); 01246 return SNMPERR_USM_GENERICERROR; 01247 } 01248 01249 if (sc_generate_keyed_hash(theAuthProtocol, theAuthProtocolLength, 01250 theAuthKey, theAuthKeyLength, 01251 ptr, ptr_len, temp_sig, &temp_sig_len) 01252 != SNMP_ERR_NOERROR) { 01253 /* 01254 * FIX temp_sig_len defined?! 01255 */ 01256 SNMP_ZERO(temp_sig, temp_sig_len); 01257 SNMP_FREE(temp_sig); 01258 DEBUGMSGTL(("usm", "Signing failed.\n")); 01259 usm_free_usmStateReference(secStateRef); 01260 return SNMPERR_USM_AUTHENTICATIONFAILURE; 01261 } 01262 01263 if (temp_sig_len != msgAuthParmLen) { 01264 SNMP_ZERO(temp_sig, temp_sig_len); 01265 SNMP_FREE(temp_sig); 01266 DEBUGMSGTL(("usm", "Signing lengths failed.\n")); 01267 usm_free_usmStateReference(secStateRef); 01268 return SNMPERR_USM_AUTHENTICATIONFAILURE; 01269 } 01270 01271 memcpy(&ptr[authParamsOffset], temp_sig, msgAuthParmLen); 01272 01273 SNMP_ZERO(temp_sig, temp_sig_len); 01274 SNMP_FREE(temp_sig); 01275 01276 } 01277 01278 /* 01279 * endif -- create keyed hash 01280 */ 01281 usm_free_usmStateReference(secStateRef); 01282 01283 DEBUGMSGTL(("usm", "USM processing completed.\n")); 01284 01285 return SNMPERR_SUCCESS; 01286 01287 } /* end usm_generate_out_msg() */ 01288 01289 #ifdef NETSNMP_USE_REVERSE_ASNENCODING 01290 int 01291 usm_secmod_rgenerate_out_msg(struct snmp_secmod_outgoing_params *parms) 01292 { 01293 if (!parms) 01294 return SNMPERR_GENERR; 01295 01296 return usm_rgenerate_out_msg(parms->msgProcModel, 01297 parms->globalData, parms->globalDataLen, 01298 parms->maxMsgSize, parms->secModel, 01299 parms->secEngineID, parms->secEngineIDLen, 01300 parms->secName, parms->secNameLen, 01301 parms->secLevel, 01302 parms->scopedPdu, parms->scopedPduLen, 01303 parms->secStateRef, 01304 parms->wholeMsg, parms->wholeMsgLen, 01305 parms->wholeMsgOffset); 01306 } 01307 01308 int 01309 usm_rgenerate_out_msg(int msgProcModel, /* (UNUSED) */ 01310 u_char * globalData, /* IN */ 01311 /* 01312 * points at the msgGlobalData, which is of length given by next 01313 * parameter. 01314 */ 01315 size_t globalDataLen, /* IN - Length of msg header data. */ 01316 int maxMsgSize, /* (UNUSED) */ 01317 int secModel, /* (UNUSED) */ 01318 u_char * secEngineID, /* IN - Pointer snmpEngineID. */ 01319 size_t secEngineIDLen, /* IN - SnmpEngineID length. */ 01320 char *secName, /* IN - Pointer to securityName. */ 01321 size_t secNameLen, /* IN - SecurityName length. */ 01322 int secLevel, /* IN - AuthNoPriv, authPriv etc. */ 01323 u_char * scopedPdu, /* IN */ 01324 /* 01325 * Pointer to scopedPdu will be encrypted by USM if needed 01326 * * and written to packet buffer immediately following 01327 * * securityParameters, entire msg will be authenticated by 01328 * * USM if needed. 01329 */ 01330 size_t scopedPduLen, /* IN - scopedPdu length. */ 01331 void *secStateRef, /* IN */ 01332 /* 01333 * secStateRef, pointer to cached info provided only for 01334 * * Response, otherwise NULL. 01335 */ 01336 u_char ** wholeMsg, /* IN/OUT */ 01337 /* 01338 * Points at the pointer to the packet buffer, which might get extended 01339 * if necessary via realloc(). 01340 */ 01341 size_t * wholeMsgLen, /* IN/OUT */ 01342 /* 01343 * Length of the entire packet buffer, **not** the length of the 01344 * packet. 01345 */ 01346 size_t * offset /* IN/OUT */ 01347 /* 01348 * Offset from the end of the packet buffer to the start of the packet, 01349 * also known as the packet length. 01350 */ 01351 ) 01352 { 01353 size_t msgAuthParmLen = 0; 01354 #ifdef NETSNMP_ENABLE_TESTING_CODE 01355 size_t theTotalLength; 01356 #endif 01357 01358 u_int boots_uint; 01359 u_int time_uint; 01360 long boots_long; 01361 long time_long; 01362 01363 /* 01364 * Indirection because secStateRef values override parameters. 01365 * 01366 * None of these are to be free'd - they are either pointing to 01367 * what's in the secStateRef or to something either in the 01368 * actual parameter list or the user list. 01369 */ 01370 01371 char *theName = NULL; 01372 u_int theNameLength = 0; 01373 u_char *theEngineID = NULL; 01374 u_int theEngineIDLength = 0; 01375 u_char *theAuthKey = NULL; 01376 u_int theAuthKeyLength = 0; 01377 const oid *theAuthProtocol = NULL; 01378 u_int theAuthProtocolLength = 0; 01379 u_char *thePrivKey = NULL; 01380 u_int thePrivKeyLength = 0; 01381 const oid *thePrivProtocol = NULL; 01382 u_int thePrivProtocolLength = 0; 01383 int theSecLevel = 0; /* No defined const for bad 01384 * value (other then err). */ 01385 size_t salt_length = 0, save_salt_length = 0, save_salt_offset = 0; 01386 u_char salt[BYTESIZE(USM_MAX_SALT_LENGTH)]; 01387 u_char authParams[USM_MAX_AUTHSIZE]; 01388 u_char iv[BYTESIZE(USM_MAX_SALT_LENGTH)]; 01389 size_t sp_offset = 0, mac_offset = 0; 01390 int rc = 0; 01391 01392 DEBUGMSGTL(("usm", "USM processing has begun (offset %d)\n", (int)*offset)); 01393 01394 if (secStateRef != NULL) { 01395 /* 01396 * To hush the compiler for now. XXX 01397 */ 01398 struct usmStateReference *ref 01399 = (struct usmStateReference *) secStateRef; 01400 01401 theName = ref->usr_name; 01402 theNameLength = ref->usr_name_length; 01403 theEngineID = ref->usr_engine_id; 01404 theEngineIDLength = ref->usr_engine_id_length; 01405 01406 if (!theEngineIDLength) { 01407 theEngineID = secEngineID; 01408 theEngineIDLength = secEngineIDLen; 01409 } 01410 01411 theAuthProtocol = ref->usr_auth_protocol; 01412 theAuthProtocolLength = ref->usr_auth_protocol_length; 01413 theAuthKey = ref->usr_auth_key; 01414 theAuthKeyLength = ref->usr_auth_key_length; 01415 thePrivProtocol = ref->usr_priv_protocol; 01416 thePrivProtocolLength = ref->usr_priv_protocol_length; 01417 thePrivKey = ref->usr_priv_key; 01418 thePrivKeyLength = ref->usr_priv_key_length; 01419 theSecLevel = ref->usr_sec_level; 01420 } 01421 01422 /* 01423 * * Identify the user record. 01424 */ 01425 else { 01426 struct usmUser *user; 01427 01428 /* 01429 * we do allow an unknown user name for 01430 * unauthenticated requests. 01431 */ 01432 if ((user = usm_get_user(secEngineID, secEngineIDLen, secName)) 01433 == NULL && secLevel != SNMP_SEC_LEVEL_NOAUTH) { 01434 DEBUGMSGTL(("usm", "Unknown User\n")); 01435 usm_free_usmStateReference(secStateRef); 01436 return SNMPERR_USM_UNKNOWNSECURITYNAME; 01437 } 01438 01439 theName = secName; 01440 theNameLength = secNameLen; 01441 theEngineID = secEngineID; 01442 theSecLevel = secLevel; 01443 theEngineIDLength = secEngineIDLen; 01444 if (user) { 01445 theAuthProtocol = user->authProtocol; 01446 theAuthProtocolLength = user->authProtocolLen; 01447 theAuthKey = user->authKey; 01448 theAuthKeyLength = user->authKeyLen; 01449 thePrivProtocol = user->privProtocol; 01450 thePrivProtocolLength = user->privProtocolLen; 01451 thePrivKey = user->privKey; 01452 thePrivKeyLength = user->privKeyLen; 01453 } else { 01454 /* 01455 * unknown users can not do authentication (obviously) 01456 */ 01457 theAuthProtocol = usmNoAuthProtocol; 01458 theAuthProtocolLength = 01459 sizeof(usmNoAuthProtocol) / sizeof(oid); 01460 theAuthKey = NULL; 01461 theAuthKeyLength = 0; 01462 thePrivProtocol = usmNoPrivProtocol; 01463 thePrivProtocolLength = 01464 sizeof(usmNoPrivProtocol) / sizeof(oid); 01465 thePrivKey = NULL; 01466 thePrivKeyLength = 0; 01467 } 01468 } /* endif -- secStateRef==NULL */ 01469 01470 01471 /* 01472 * From here to the end of the function, avoid reference to 01473 * secName, secEngineID, secLevel, and associated lengths. 01474 */ 01475 01476 01477 /* 01478 * Check to see if the user can use the requested sec services. 01479 */ 01480 if (usm_check_secLevel_vs_protocols(theSecLevel, 01481 theAuthProtocol, 01482 theAuthProtocolLength, 01483 thePrivProtocol, 01484 thePrivProtocolLength) == 1) { 01485 DEBUGMSGTL(("usm", "Unsupported Security Level or type (%d)\n", 01486 theSecLevel)); 01487 01488 usm_free_usmStateReference(secStateRef); 01489 return SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL; 01490 } 01491 01492 01493 /* 01494 * * Retrieve the engine information. 01495 * * 01496 * * XXX No error is declared in the EoP when sending messages to 01497 * * unknown engines, processing continues w/ boots/time == (0,0). 01498 */ 01499 if (get_enginetime(theEngineID, theEngineIDLength, 01500 &boots_uint, &time_uint, FALSE) == -1) { 01501 DEBUGMSGTL(("usm", "%s\n", "Failed to find engine data.")); 01502 } 01503 01504 boots_long = boots_uint; 01505 time_long = time_uint; 01506 01507 if (theSecLevel == SNMP_SEC_LEVEL_AUTHPRIV) { 01508 /* 01509 * Initially assume that the ciphertext will end up the same size as 01510 * the plaintext plus some padding. Really sc_encrypt ought to be able 01511 * to grow this for us, a la asn_realloc_rbuild_<type> functions, but 01512 * this will do for now. 01513 */ 01514 u_char *ciphertext = NULL; 01515 size_t ciphertextlen = scopedPduLen + 64; 01516 01517 if ((ciphertext = (u_char *) malloc(ciphertextlen)) == NULL) { 01518 DEBUGMSGTL(("usm", 01519 "couldn't malloc %d bytes for encrypted PDU\n", 01520 (int)ciphertextlen)); 01521 usm_free_usmStateReference(secStateRef); 01522 return SNMPERR_MALLOC; 01523 } 01524 01525 /* 01526 * XXX Hardwired to seek into a 1DES private key! 01527 */ 01528 #ifdef HAVE_AES 01529 if (ISTRANSFORM(thePrivProtocol, AESPriv)) { 01530 salt_length = BYTESIZE(USM_AES_SALT_LENGTH); 01531 save_salt_length = BYTESIZE(USM_AES_SALT_LENGTH)/2; 01532 save_salt_offset = 0; 01533 if (!thePrivKey || 01534 usm_set_aes_iv(salt, &salt_length, 01535 htonl(boots_uint), htonl(time_uint), 01536 iv) == -1) { 01537 DEBUGMSGTL(("usm", "Can't set AES iv.\n")); 01538 usm_free_usmStateReference(secStateRef); 01539 SNMP_FREE(ciphertext); 01540 return SNMPERR_USM_GENERICERROR; 01541 } 01542 } 01543 #endif 01544 #ifndef NETSNMP_DISABLE_DES 01545 if (ISTRANSFORM(thePrivProtocol, DESPriv)) { 01546 salt_length = BYTESIZE(USM_DES_SALT_LENGTH); 01547 save_salt_length = BYTESIZE(USM_DES_SALT_LENGTH); 01548 save_salt_offset = 0; 01549 if (!thePrivKey || (usm_set_salt(salt, &salt_length, 01550 thePrivKey + 8, 01551 thePrivKeyLength - 8, 01552 iv) == -1)) { 01553 DEBUGMSGTL(("usm", "Can't set DES-CBC salt.\n")); 01554 usm_free_usmStateReference(secStateRef); 01555 SNMP_FREE(ciphertext); 01556 return SNMPERR_USM_GENERICERROR; 01557 } 01558 } 01559 #endif 01560 #ifdef NETSNMP_ENABLE_TESTING_CODE 01561 if (debug_is_token_registered("usm/dump") == SNMPERR_SUCCESS) { 01562 dump_chunk("usm/dump", "This data was encrypted:", 01563 scopedPdu, scopedPduLen); 01564 } 01565 #endif 01566 01567 if (sc_encrypt(thePrivProtocol, thePrivProtocolLength, 01568 thePrivKey, thePrivKeyLength, 01569 salt, salt_length, 01570 scopedPdu, scopedPduLen, 01571 ciphertext, &ciphertextlen) != SNMP_ERR_NOERROR) { 01572 DEBUGMSGTL(("usm", "encryption error.\n")); 01573 usm_free_usmStateReference(secStateRef); 01574 SNMP_FREE(ciphertext); 01575 return SNMPERR_USM_ENCRYPTIONERROR; 01576 } 01577 01578 /* 01579 * Write the encrypted scopedPdu back into the packet buffer. 01580 */ 01581 01582 #ifdef NETSNMP_ENABLE_TESTING_CODE 01583 theTotalLength = *wholeMsgLen; 01584 #endif 01585 *offset = 0; 01586 rc = asn_realloc_rbuild_string(wholeMsg, wholeMsgLen, offset, 1, 01587 (u_char) (ASN_UNIVERSAL | 01588 ASN_PRIMITIVE | 01589 ASN_OCTET_STR), 01590 ciphertext, ciphertextlen); 01591 if (rc == 0) { 01592 DEBUGMSGTL(("usm", "Encryption failed.\n")); 01593 usm_free_usmStateReference(secStateRef); 01594 SNMP_FREE(ciphertext); 01595 return SNMPERR_USM_ENCRYPTIONERROR; 01596 } 01597 01598 #ifdef NETSNMP_ENABLE_TESTING_CODE 01599 if (debug_is_token_registered("usm/dump") == SNMPERR_SUCCESS) { 01600 dump_chunk("usm/dump", "salt + Encrypted form: ", salt, 01601 salt_length); 01602 dump_chunk("usm/dump", "wholeMsg:", 01603 (*wholeMsg + *wholeMsgLen - *offset), *offset); 01604 } 01605 #endif 01606 01607 DEBUGMSGTL(("usm", "Encryption successful.\n")); 01608 SNMP_FREE(ciphertext); 01609 } else { 01610 /* 01611 * theSecLevel != SNMP_SEC_LEVEL_AUTHPRIV 01612 */ 01613 } 01614 01615 /* 01616 * Start encoding the msgSecurityParameters. 01617 */ 01618 01619 sp_offset = *offset; 01620 01621 DEBUGDUMPHEADER("send", "msgPrivacyParameters"); 01622 /* 01623 * msgPrivacyParameters (warning: assumes DES salt). 01624 */ 01625 rc = asn_realloc_rbuild_string(wholeMsg, wholeMsgLen, offset, 1, 01626 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE 01627 | ASN_OCTET_STR), 01628 iv, 01629 save_salt_length); 01630 DEBUGINDENTLESS(); 01631 if (rc == 0) { 01632 DEBUGMSGTL(("usm", "building privParams failed.\n")); 01633 usm_free_usmStateReference(secStateRef); 01634 return SNMPERR_TOO_LONG; 01635 } 01636 01637 DEBUGDUMPHEADER("send", "msgAuthenticationParameters"); 01638 /* 01639 * msgAuthenticationParameters (warnings assumes 0x00 by 12). 01640 */ 01641 if (theSecLevel == SNMP_SEC_LEVEL_AUTHNOPRIV 01642 || theSecLevel == SNMP_SEC_LEVEL_AUTHPRIV) { 01643 memset(authParams, 0, USM_MD5_AND_SHA_AUTH_LEN); 01644 msgAuthParmLen = USM_MD5_AND_SHA_AUTH_LEN; 01645 } 01646 01647 rc = asn_realloc_rbuild_string(wholeMsg, wholeMsgLen, offset, 1, 01648 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE 01649 | ASN_OCTET_STR), authParams, 01650 msgAuthParmLen); 01651 DEBUGINDENTLESS(); 01652 if (rc == 0) { 01653 DEBUGMSGTL(("usm", "building authParams failed.\n")); 01654 usm_free_usmStateReference(secStateRef); 01655 return SNMPERR_TOO_LONG; 01656 } 01657 01658 /* 01659 * Remember where to put the actual HMAC we calculate later on. An 01660 * encoded OCTET STRING of length USM_MD5_AND_SHA_AUTH_LEN has an ASN.1 01661 * header of length 2, hence the fudge factor. 01662 */ 01663 01664 mac_offset = *offset - 2; 01665 01666 /* 01667 * msgUserName. 01668 */ 01669 DEBUGDUMPHEADER("send", "msgUserName"); 01670 rc = asn_realloc_rbuild_string(wholeMsg, wholeMsgLen, offset, 1, 01671 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE 01672 | ASN_OCTET_STR), 01673 (u_char *) theName, theNameLength); 01674 DEBUGINDENTLESS(); 01675 if (rc == 0) { 01676 DEBUGMSGTL(("usm", "building authParams failed.\n")); 01677 usm_free_usmStateReference(secStateRef); 01678 return SNMPERR_TOO_LONG; 01679 } 01680 01681 /* 01682 * msgAuthoritativeEngineTime. 01683 */ 01684 DEBUGDUMPHEADER("send", "msgAuthoritativeEngineTime"); 01685 rc = asn_realloc_rbuild_int(wholeMsg, wholeMsgLen, offset, 1, 01686 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | 01687 ASN_INTEGER), &time_long, 01688 sizeof(long)); 01689 DEBUGINDENTLESS(); 01690 if (rc == 0) { 01691 DEBUGMSGTL(("usm", 01692 "building msgAuthoritativeEngineTime failed.\n")); 01693 usm_free_usmStateReference(secStateRef); 01694 return SNMPERR_TOO_LONG; 01695 } 01696 01697 /* 01698 * msgAuthoritativeEngineBoots. 01699 */ 01700 DEBUGDUMPHEADER("send", "msgAuthoritativeEngineBoots"); 01701 rc = asn_realloc_rbuild_int(wholeMsg, wholeMsgLen, offset, 1, 01702 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | 01703 ASN_INTEGER), &boots_long, 01704 sizeof(long)); 01705 DEBUGINDENTLESS(); 01706 if (rc == 0) { 01707 DEBUGMSGTL(("usm", 01708 "building msgAuthoritativeEngineBoots failed.\n")); 01709 usm_free_usmStateReference(secStateRef); 01710 return SNMPERR_TOO_LONG; 01711 } 01712 01713 DEBUGDUMPHEADER("send", "msgAuthoritativeEngineID"); 01714 rc = asn_realloc_rbuild_string(wholeMsg, wholeMsgLen, offset, 1, 01715 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE 01716 | ASN_OCTET_STR), theEngineID, 01717 theEngineIDLength); 01718 DEBUGINDENTLESS(); 01719 if (rc == 0) { 01720 DEBUGMSGTL(("usm", "building msgAuthoritativeEngineID failed.\n")); 01721 usm_free_usmStateReference(secStateRef); 01722 return SNMPERR_TOO_LONG; 01723 } 01724 01725 /* 01726 * USM msgSecurityParameters sequence header 01727 */ 01728 rc = asn_realloc_rbuild_sequence(wholeMsg, wholeMsgLen, offset, 1, 01729 (u_char) (ASN_SEQUENCE | 01730 ASN_CONSTRUCTOR), 01731 *offset - sp_offset); 01732 if (rc == 0) { 01733 DEBUGMSGTL(("usm", "building usm security parameters failed.\n")); 01734 usm_free_usmStateReference(secStateRef); 01735 return SNMPERR_TOO_LONG; 01736 } 01737 01738 /* 01739 * msgSecurityParameters OCTET STRING wrapper. 01740 */ 01741 rc = asn_realloc_rbuild_header(wholeMsg, wholeMsgLen, offset, 1, 01742 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE 01743 | ASN_OCTET_STR), 01744 *offset - sp_offset); 01745 01746 if (rc == 0) { 01747 DEBUGMSGTL(("usm", "building msgSecurityParameters failed.\n")); 01748 usm_free_usmStateReference(secStateRef); 01749 return SNMPERR_TOO_LONG; 01750 } 01751 01752 /* 01753 * Copy in the msgGlobalData and msgVersion. 01754 */ 01755 while ((*wholeMsgLen - *offset) < globalDataLen) { 01756 if (!asn_realloc(wholeMsg, wholeMsgLen)) { 01757 DEBUGMSGTL(("usm", "building global data failed.\n")); 01758 usm_free_usmStateReference(secStateRef); 01759 return SNMPERR_TOO_LONG; 01760 } 01761 } 01762 01763 *offset += globalDataLen; 01764 memcpy(*wholeMsg + *wholeMsgLen - *offset, globalData, globalDataLen); 01765 01766 /* 01767 * Total packet sequence. 01768 */ 01769 rc = asn_realloc_rbuild_sequence(wholeMsg, wholeMsgLen, offset, 1, 01770 (u_char) (ASN_SEQUENCE | 01771 ASN_CONSTRUCTOR), *offset); 01772 if (rc == 0) { 01773 DEBUGMSGTL(("usm", "building master packet sequence failed.\n")); 01774 usm_free_usmStateReference(secStateRef); 01775 return SNMPERR_TOO_LONG; 01776 } 01777 01778 /* 01779 * Now consider / do authentication. 01780 */ 01781 01782 if (theSecLevel == SNMP_SEC_LEVEL_AUTHNOPRIV || 01783 theSecLevel == SNMP_SEC_LEVEL_AUTHPRIV) { 01784 size_t temp_sig_len = msgAuthParmLen; 01785 u_char *temp_sig = (u_char *) malloc(temp_sig_len); 01786 u_char *proto_msg = *wholeMsg + *wholeMsgLen - *offset; 01787 size_t proto_msg_len = *offset; 01788 01789 01790 if (temp_sig == NULL) { 01791 DEBUGMSGTL(("usm", "Out of memory.\n")); 01792 usm_free_usmStateReference(secStateRef); 01793 return SNMPERR_USM_GENERICERROR; 01794 } 01795 01796 if (sc_generate_keyed_hash(theAuthProtocol, theAuthProtocolLength, 01797 theAuthKey, theAuthKeyLength, 01798 proto_msg, proto_msg_len, 01799 temp_sig, &temp_sig_len) 01800 != SNMP_ERR_NOERROR) { 01801 SNMP_FREE(temp_sig); 01802 DEBUGMSGTL(("usm", "Signing failed.\n")); 01803 usm_free_usmStateReference(secStateRef); 01804 return SNMPERR_USM_AUTHENTICATIONFAILURE; 01805 } 01806 01807 if (temp_sig_len != msgAuthParmLen) { 01808 SNMP_FREE(temp_sig); 01809 DEBUGMSGTL(("usm", "Signing lengths failed.\n")); 01810 usm_free_usmStateReference(secStateRef); 01811 return SNMPERR_USM_AUTHENTICATIONFAILURE; 01812 } 01813 01814 memcpy(*wholeMsg + *wholeMsgLen - mac_offset, temp_sig, 01815 msgAuthParmLen); 01816 SNMP_FREE(temp_sig); 01817 } 01818 /* 01819 * endif -- create keyed hash 01820 */ 01821 usm_free_usmStateReference(secStateRef); 01822 DEBUGMSGTL(("usm", "USM processing completed.\n")); 01823 return SNMPERR_SUCCESS; 01824 } /* end usm_rgenerate_out_msg() */ 01825 01826 #endif /* */ 01827 01828 01829 01830 /*******************************************************************-o-****** 01831 * usm_parse_security_parameters 01832 * 01833 * Parameters: 01834 * (See list below...) 01835 * 01836 * Returns: 01837 * 0 On success, 01838 * -1 Otherwise. 01839 * 01840 * tab stop 4 01841 * 01842 * Extracts values from the security header and data portions of the 01843 * incoming buffer. 01844 */ 01845 int 01846 usm_parse_security_parameters(u_char * secParams, 01847 size_t remaining, 01848 u_char * secEngineID, 01849 size_t * secEngineIDLen, 01850 u_int * boots_uint, 01851 u_int * time_uint, 01852 char *secName, 01853 size_t * secNameLen, 01854 u_char * signature, 01855 size_t * signature_length, 01856 u_char * salt, 01857 size_t * salt_length, u_char ** data_ptr) 01858 { 01859 u_char *parse_ptr = secParams; 01860 u_char *value_ptr; 01861 u_char *next_ptr; 01862 u_char type_value; 01863 01864 size_t octet_string_length = remaining; 01865 size_t sequence_length; 01866 size_t remaining_bytes; 01867 01868 long boots_long; 01869 long time_long; 01870 01871 u_int origNameLen; 01872 01873 01874 /* 01875 * Eat the first octet header. 01876 */ 01877 if ((value_ptr = asn_parse_sequence(parse_ptr, &octet_string_length, 01878 &type_value, 01879 (ASN_UNIVERSAL | ASN_PRIMITIVE | 01880 ASN_OCTET_STR), 01881 "usm first octet")) == NULL) { 01882 /* 01883 * RETURN parse error 01884 */ return -1; 01885 } 01886 01887 01888 /* 01889 * Eat the sequence header. 01890 */ 01891 parse_ptr = value_ptr; 01892 sequence_length = octet_string_length; 01893 01894 if ((value_ptr = asn_parse_sequence(parse_ptr, &sequence_length, 01895 &type_value, 01896 (ASN_SEQUENCE | ASN_CONSTRUCTOR), 01897 "usm sequence")) == NULL) { 01898 /* 01899 * RETURN parse error 01900 */ return -1; 01901 } 01902 01903 01904 /* 01905 * Retrieve the engineID. 01906 */ 01907 parse_ptr = value_ptr; 01908 remaining_bytes = sequence_length; 01909 01910 DEBUGDUMPHEADER("recv", "msgAuthoritativeEngineID"); 01911 if ((next_ptr 01912 = asn_parse_string(parse_ptr, &remaining_bytes, &type_value, 01913 secEngineID, secEngineIDLen)) == NULL) { 01914 DEBUGINDENTLESS(); 01915 /* 01916 * RETURN parse error 01917 */ return -1; 01918 } 01919 DEBUGINDENTLESS(); 01920 01921 if (type_value != 01922 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR)) { 01923 /* 01924 * RETURN parse error 01925 */ return -1; 01926 } 01927 01928 01929 /* 01930 * Retrieve the engine boots, notice switch in the way next_ptr and 01931 * remaining_bytes are used (to accomodate the asn code). 01932 */ 01933 DEBUGDUMPHEADER("recv", "msgAuthoritativeEngineBoots"); 01934 if ((next_ptr = asn_parse_int(next_ptr, &remaining_bytes, &type_value, 01935 &boots_long, sizeof(long))) == NULL) { 01936 DEBUGINDENTLESS(); 01937 /* 01938 * RETURN parse error 01939 */ return -1; 01940 } 01941 DEBUGINDENTLESS(); 01942 01943 if (type_value != 01944 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER)) { 01945 DEBUGINDENTLESS(); 01946 /* 01947 * RETURN parse error 01948 */ return -1; 01949 } 01950 01951 *boots_uint = (u_int) boots_long; 01952 01953 01954 /* 01955 * Retrieve the time value. 01956 */ 01957 DEBUGDUMPHEADER("recv", "msgAuthoritativeEngineTime"); 01958 if ((next_ptr = asn_parse_int(next_ptr, &remaining_bytes, &type_value, 01959 &time_long, sizeof(long))) == NULL) { 01960 /* 01961 * RETURN parse error 01962 */ return -1; 01963 } 01964 DEBUGINDENTLESS(); 01965 01966 if (type_value != 01967 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER)) { 01968 /* 01969 * RETURN parse error 01970 */ return -1; 01971 } 01972 01973 *time_uint = (u_int) time_long; 01974 01975 if (*boots_uint > ENGINEBOOT_MAX || *time_uint > ENGINETIME_MAX) { 01976 return -1; 01977 } 01978 01979 /* 01980 * Retrieve the secName. 01981 */ 01982 origNameLen = *secNameLen; 01983 01984 01985 DEBUGDUMPHEADER("recv", "msgUserName"); 01986 if ((next_ptr 01987 = asn_parse_string(next_ptr, &remaining_bytes, &type_value, 01988 (u_char *) secName, secNameLen)) == NULL) { 01989 DEBUGINDENTLESS(); 01990 /* 01991 * RETURN parse error 01992 */ return -1; 01993 } 01994 DEBUGINDENTLESS(); 01995 01996 /* 01997 * FIX -- doesn't this also indicate a buffer overrun? 01998 */ 01999 if (origNameLen < *secNameLen + 1) { 02000 /* 02001 * RETURN parse error, but it's really a parameter error 02002 */ 02003 return -1; 02004 } 02005 02006 if (*secNameLen > 32) { 02007 /* 02008 * This is a USM-specific limitation over and above the above 02009 * limitation (which will probably default to the length of an 02010 * SnmpAdminString, i.e. 255). See RFC 2574, sec. 2.4. 02011 */ 02012 return -1; 02013 } 02014 02015 secName[*secNameLen] = '\0'; 02016 02017 if (type_value != 02018 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR)) { 02019 /* 02020 * RETURN parse error 02021 */ return -1; 02022 } 02023 02024 02025 /* 02026 * Retrieve the signature and blank it if there. 02027 */ 02028 DEBUGDUMPHEADER("recv", "msgAuthenticationParameters"); 02029 if ((next_ptr 02030 = asn_parse_string(next_ptr, &remaining_bytes, &type_value, 02031 signature, signature_length)) == NULL) { 02032 DEBUGINDENTLESS(); 02033 /* 02034 * RETURN parse error 02035 */ return -1; 02036 } 02037 DEBUGINDENTLESS(); 02038 02039 if (type_value != 02040 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR)) { 02041 /* 02042 * RETURN parse error 02043 */ return -1; 02044 } 02045 02046 if (*signature_length != 0) { /* Blanking for authentication step later */ 02047 memset(next_ptr - (u_long) * signature_length, 02048 0, *signature_length); 02049 } 02050 02051 02052 /* 02053 * Retrieve the salt. 02054 * 02055 * Note that the next ptr is where the data section starts. 02056 */ 02057 DEBUGDUMPHEADER("recv", "msgPrivacyParameters"); 02058 if ((*data_ptr 02059 = asn_parse_string(next_ptr, &remaining_bytes, &type_value, 02060 salt, salt_length)) == NULL) { 02061 DEBUGINDENTLESS(); 02062 /* 02063 * RETURN parse error 02064 */ return -2; 02065 } 02066 DEBUGINDENTLESS(); 02067 02068 if (type_value != 02069 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR)) { 02070 /* 02071 * RETURN parse error 02072 */ return -2; 02073 } 02074 02075 return 0; 02076 02077 } /* end usm_parse_security_parameters() */ 02078 02079 02080 02081 02082 /*******************************************************************-o-****** 02083 * usm_check_and_update_timeliness 02084 * 02085 * Parameters: 02086 * *secEngineID 02087 * secEngineIDen 02088 * boots_uint 02089 * time_uint 02090 * *error 02091 * 02092 * Returns: 02093 * 0 On success, 02094 * -1 Otherwise. 02095 * 02096 * 02097 * Performs the incoming timeliness checking and setting. 02098 */ 02099 int 02100 usm_check_and_update_timeliness(u_char * secEngineID, 02101 size_t secEngineIDLen, 02102 u_int boots_uint, 02103 u_int time_uint, int *error) 02104 { 02105 u_char myID[USM_MAX_ID_LENGTH]; 02106 u_long myIDLength = 02107 snmpv3_get_engineID(myID, USM_MAX_ID_LENGTH); 02108 u_int myBoots; 02109 u_int myTime; 02110 02111 02112 02113 if ((myIDLength > USM_MAX_ID_LENGTH) || (myIDLength == 0)) { 02114 /* 02115 * We're probably already screwed...buffer overwrite. XXX? 02116 */ 02117 DEBUGMSGTL(("usm", "Buffer overflow.\n")); 02118 *error = SNMPERR_USM_GENERICERROR; 02119 return -1; 02120 } 02121 02122 myBoots = snmpv3_local_snmpEngineBoots(); 02123 myTime = snmpv3_local_snmpEngineTime(); 02124 02125 02126 /* 02127 * IF the time involved is local 02128 * Make sure message is inside the time window 02129 * ELSE 02130 * IF boots is higher or boots is the same and time is higher 02131 * remember this new data 02132 * ELSE 02133 * IF !(boots same and time within USM_TIME_WINDOW secs) 02134 * Message is too old 02135 * ELSE 02136 * Message is ok, but don't take time 02137 * ENDIF 02138 * ENDIF 02139 * ENDIF 02140 */ 02141 02142 /* 02143 * This is a local reference. 02144 */ 02145 if (secEngineIDLen == myIDLength 02146 && memcmp(secEngineID, myID, myIDLength) == 0) { 02147 u_int time_difference = myTime > time_uint ? 02148 myTime - time_uint : time_uint - myTime; 02149 02150 if (boots_uint == ENGINEBOOT_MAX 02151 || boots_uint != myBoots 02152 || time_difference > USM_TIME_WINDOW) { 02153 snmp_increment_statistic(STAT_USMSTATSNOTINTIMEWINDOWS); 02154 02155 DEBUGMSGTL(("usm", 02156 "boot_uint %u myBoots %u time_diff %u => not in time window\n", 02157 boots_uint, myBoots, time_difference)); 02158 *error = SNMPERR_USM_NOTINTIMEWINDOW; 02159 return -1; 02160 } 02161 02162 *error = SNMPERR_SUCCESS; 02163 return 0; 02164 } 02165 02166 /* 02167 * This is a remote reference. 02168 */ 02169 else { 02170 u_int theirBoots, theirTime, theirLastTime; 02171 u_int time_difference; 02172 02173 if (get_enginetime_ex(secEngineID, secEngineIDLen, 02174 &theirBoots, &theirTime, 02175 &theirLastTime, TRUE) 02176 != SNMPERR_SUCCESS) { 02177 DEBUGMSGTL(("usm", "%s\n", 02178 "Failed to get remote engine's times.")); 02179 02180 *error = SNMPERR_USM_GENERICERROR; 02181 return -1; 02182 } 02183 02184 time_difference = theirTime > time_uint ? 02185 theirTime - time_uint : time_uint - theirTime; 02186 02187 02188 /* 02189 * XXX Contrary to the pseudocode: 02190 * See if boots is invalid first. 02191 */ 02192 if (theirBoots == ENGINEBOOT_MAX || theirBoots > boots_uint) { 02193 DEBUGMSGTL(("usm", "%s\n", "Remote boot count invalid.")); 02194 02195 *error = SNMPERR_USM_NOTINTIMEWINDOW; 02196 return -1; 02197 } 02198 02199 02200 /* 02201 * Boots is ok, see if the boots is the same but the time 02202 * is old. 02203 */ 02204 if (theirBoots == boots_uint && time_uint < theirLastTime) { 02205 if (time_difference > USM_TIME_WINDOW) { 02206 DEBUGMSGTL(("usm", "%s\n", "Message too old.")); 02207 *error = SNMPERR_USM_NOTINTIMEWINDOW; 02208 return -1; 02209 } 02210 02211 else { /* Old, but acceptable */ 02212 02213 *error = SNMPERR_SUCCESS; 02214 return 0; 02215 } 02216 } 02217 02218 02219 /* 02220 * Message is ok, either boots has been advanced, or 02221 * time is greater than before with the same boots. 02222 */ 02223 02224 if (set_enginetime(secEngineID, secEngineIDLen, 02225 boots_uint, time_uint, TRUE) 02226 != SNMPERR_SUCCESS) { 02227 DEBUGMSGTL(("usm", "%s\n", 02228 "Failed updating remote boot/time.")); 02229 *error = SNMPERR_USM_GENERICERROR; 02230 return -1; 02231 } 02232 02233 *error = SNMPERR_SUCCESS; 02234 return 0; /* Fresh message and time updated */ 02235 02236 } /* endif -- local or remote time reference. */ 02237 02238 02239 } /* end usm_check_and_update_timeliness() */ 02240 02241 02242 02243 int 02244 usm_secmod_process_in_msg(struct snmp_secmod_incoming_params *parms) 02245 { 02246 if (!parms) 02247 return SNMPERR_GENERR; 02248 02249 return usm_process_in_msg(parms->msgProcModel, 02250 parms->maxMsgSize, 02251 parms->secParams, 02252 parms->secModel, 02253 parms->secLevel, 02254 parms->wholeMsg, 02255 parms->wholeMsgLen, 02256 parms->secEngineID, 02257 parms->secEngineIDLen, 02258 parms->secName, 02259 parms->secNameLen, 02260 parms->scopedPdu, 02261 parms->scopedPduLen, 02262 parms->maxSizeResponse, 02263 parms->secStateRef, 02264 parms->sess, parms->msg_flags); 02265 } 02266 02267 /*******************************************************************-o-****** 02268 * usm_process_in_msg 02269 * 02270 * Parameters: 02271 * (See list below...) 02272 * 02273 * Returns: 02274 * SNMPERR_SUCCESS On success. 02275 * SNMPERR_USM_AUTHENTICATIONFAILURE 02276 * SNMPERR_USM_DECRYPTIONERROR 02277 * SNMPERR_USM_GENERICERROR 02278 * SNMPERR_USM_PARSEERROR 02279 * SNMPERR_USM_UNKNOWNENGINEID 02280 * SNMPERR_USM_PARSEERROR 02281 * SNMPERR_USM_UNKNOWNSECURITYNAME 02282 * SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL 02283 * 02284 * 02285 * ASSUMES size of decrypt_buf will always be >= size of encrypted sPDU. 02286 * 02287 * FIX Memory leaks if secStateRef is allocated and a return occurs 02288 * without cleaning up. May contain secrets... 02289 */ 02290 int 02291 usm_process_in_msg(int msgProcModel, /* (UNUSED) */ 02292 size_t maxMsgSize, /* IN - Used to calc maxSizeResponse. */ 02293 u_char * secParams, /* IN - BER encoded securityParameters. */ 02294 int secModel, /* (UNUSED) */ 02295 int secLevel, /* IN - AuthNoPriv, authPriv etc. */ 02296 u_char * wholeMsg, /* IN - Original v3 message. */ 02297 size_t wholeMsgLen, /* IN - Msg length. */ 02298 u_char * secEngineID, /* OUT - Pointer snmpEngineID. */ 02299 size_t * secEngineIDLen, /* IN/OUT - Len available, len returned. */ 02300 /* 02301 * NOTE: Memory provided by caller. 02302 */ 02303 char *secName, /* OUT - Pointer to securityName. */ 02304 size_t * secNameLen, /* IN/OUT - Len available, len returned. */ 02305 u_char ** scopedPdu, /* OUT - Pointer to plaintext scopedPdu. */ 02306 size_t * scopedPduLen, /* IN/OUT - Len available, len returned. */ 02307 size_t * maxSizeResponse, /* OUT - Max size of Response PDU. */ 02308 void **secStateRf, /* OUT - Ref to security state. */ 02309 netsnmp_session * sess, /* IN - session which got the message */ 02310 u_char msg_flags) 02311 { /* IN - v3 Message flags. */ 02312 size_t remaining = wholeMsgLen - (u_int) 02313 ((u_long) * secParams - (u_long) * wholeMsg); 02314 u_int boots_uint; 02315 u_int time_uint; 02316 #ifdef HAVE_AES 02317 u_int net_boots, net_time; 02318 #endif 02319 u_char signature[BYTESIZE(USM_MAX_KEYEDHASH_LENGTH)]; 02320 size_t signature_length = BYTESIZE(USM_MAX_KEYEDHASH_LENGTH); 02321 u_char salt[BYTESIZE(USM_MAX_SALT_LENGTH)]; 02322 size_t salt_length = BYTESIZE(USM_MAX_SALT_LENGTH); 02323 u_char iv[BYTESIZE(USM_MAX_SALT_LENGTH)]; 02324 u_int iv_length = BYTESIZE(USM_MAX_SALT_LENGTH); 02325 u_char *data_ptr; 02326 u_char *value_ptr; 02327 u_char type_value; 02328 u_char *end_of_overhead = NULL; 02329 int error; 02330 int i, rc = 0; 02331 struct usmStateReference **secStateRef = 02332 (struct usmStateReference **) secStateRf; 02333 02334 struct usmUser *user; 02335 02336 02337 DEBUGMSGTL(("usm", "USM processing begun...\n")); 02338 02339 02340 if (secStateRef) { 02341 usm_free_usmStateReference(*secStateRef); 02342 *secStateRef = usm_malloc_usmStateReference(); 02343 if (*secStateRef == NULL) { 02344 DEBUGMSGTL(("usm", "Out of memory.\n")); 02345 return SNMPERR_USM_GENERICERROR; 02346 } 02347 } 02348 02349 02350 /* 02351 * Make sure the *secParms is an OCTET STRING. 02352 * Extract the user name, engine ID, and security level. 02353 */ 02354 if ((rc = usm_parse_security_parameters(secParams, remaining, 02355 secEngineID, secEngineIDLen, 02356 &boots_uint, &time_uint, 02357 secName, secNameLen, 02358 signature, &signature_length, 02359 salt, &salt_length, 02360 &data_ptr)) < 0) { 02361 DEBUGMSGTL(("usm", "Parsing failed (rc %d).\n", rc)); 02362 if (rc == -2) { 02363 /* 02364 * This indicates a decryptionError. 02365 */ 02366 snmp_increment_statistic(STAT_USMSTATSDECRYPTIONERRORS); 02367 return SNMPERR_USM_DECRYPTIONERROR; 02368 } 02369 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS); 02370 return SNMPERR_USM_PARSEERROR; 02371 } 02372 02373 /* 02374 * RFC 2574 section 8.3.2 02375 * 1) If the privParameters field is not an 8-octet OCTET STRING, 02376 * then an error indication (decryptionError) is returned to the 02377 * calling module. 02378 */ 02379 if ((secLevel == SNMP_SEC_LEVEL_AUTHPRIV) && (salt_length != 8)) { 02380 snmp_increment_statistic(STAT_USMSTATSDECRYPTIONERRORS); 02381 return SNMPERR_USM_DECRYPTIONERROR; 02382 } 02383 02384 if (secLevel != SNMP_SEC_LEVEL_AUTHPRIV) { 02385 /* 02386 * pull these out now so reports can use them 02387 */ 02388 *scopedPdu = data_ptr; 02389 *scopedPduLen = wholeMsgLen - (data_ptr - wholeMsg); 02390 end_of_overhead = data_ptr; 02391 } 02392 02393 if (secStateRef) { 02394 /* 02395 * Cache the name, engine ID, and security level, 02396 * * per step 2 (section 3.2) 02397 */ 02398 if (usm_set_usmStateReference_name 02399 (*secStateRef, secName, *secNameLen) == -1) { 02400 DEBUGMSGTL(("usm", "%s\n", "Couldn't cache name.")); 02401 return SNMPERR_USM_GENERICERROR; 02402 } 02403 02404 if (usm_set_usmStateReference_engine_id 02405 (*secStateRef, secEngineID, *secEngineIDLen) == -1) { 02406 DEBUGMSGTL(("usm", "%s\n", "Couldn't cache engine id.")); 02407 return SNMPERR_USM_GENERICERROR; 02408 } 02409 02410 if (usm_set_usmStateReference_sec_level(*secStateRef, secLevel) == 02411 -1) { 02412 DEBUGMSGTL(("usm", "%s\n", "Couldn't cache security level.")); 02413 return SNMPERR_USM_GENERICERROR; 02414 } 02415 } 02416 02417 02418 /* 02419 * Locate the engine ID record. 02420 * If it is unknown, then either create one or note this as an error. 02421 */ 02422 if ((sess && (sess->isAuthoritative == SNMP_SESS_AUTHORITATIVE || 02423 (sess->isAuthoritative == SNMP_SESS_UNKNOWNAUTH && 02424 (msg_flags & SNMP_MSG_FLAG_RPRT_BIT)))) || 02425 (!sess && (msg_flags & SNMP_MSG_FLAG_RPRT_BIT))) { 02426 if (ISENGINEKNOWN(secEngineID, *secEngineIDLen) == FALSE) { 02427 DEBUGMSGTL(("usm", "Unknown Engine ID.\n")); 02428 snmp_increment_statistic(STAT_USMSTATSUNKNOWNENGINEIDS); 02429 return SNMPERR_USM_UNKNOWNENGINEID; 02430 } 02431 } else { 02432 if (ENSURE_ENGINE_RECORD(secEngineID, *secEngineIDLen) 02433 != SNMPERR_SUCCESS) { 02434 DEBUGMSGTL(("usm", "%s\n", "Couldn't ensure engine record.")); 02435 return SNMPERR_USM_GENERICERROR; 02436 } 02437 02438 } 02439 02440 02441 /* 02442 * Locate the User record. 02443 * If the user/engine ID is unknown, report this as an error. 02444 */ 02445 if ((user = usm_get_user_from_list(secEngineID, *secEngineIDLen, 02446 secName, userList, 02447 (((sess && sess->isAuthoritative == 02448 SNMP_SESS_AUTHORITATIVE) || 02449 (!sess)) ? 0 : 1))) 02450 == NULL) { 02451 DEBUGMSGTL(("usm", "Unknown User(%s)\n", secName)); 02452 snmp_increment_statistic(STAT_USMSTATSUNKNOWNUSERNAMES); 02453 return SNMPERR_USM_UNKNOWNSECURITYNAME; 02454 } 02455 02456 /* ensure the user is active */ 02457 if (user->userStatus != RS_ACTIVE) { 02458 DEBUGMSGTL(("usm", "Attempt to use an inactive user.\n")); 02459 return SNMPERR_USM_UNKNOWNSECURITYNAME; 02460 } 02461 02462 /* 02463 * Make sure the security level is appropriate. 02464 */ 02465 02466 rc = usm_check_secLevel(secLevel, user); 02467 if (1 == rc) { 02468 DEBUGMSGTL(("usm", "Unsupported Security Level (%d).\n", 02469 secLevel)); 02470 snmp_increment_statistic(STAT_USMSTATSUNSUPPORTEDSECLEVELS); 02471 return SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL; 02472 } else if (rc != 0) { 02473 DEBUGMSGTL(("usm", "Unknown issue.\n")); 02474 return SNMPERR_USM_GENERICERROR; 02475 } 02476 02477 /* 02478 * Check the authentication credentials of the message. 02479 */ 02480 if (secLevel == SNMP_SEC_LEVEL_AUTHNOPRIV 02481 || secLevel == SNMP_SEC_LEVEL_AUTHPRIV) { 02482 if (sc_check_keyed_hash(user->authProtocol, user->authProtocolLen, 02483 user->authKey, user->authKeyLen, 02484 wholeMsg, wholeMsgLen, 02485 signature, signature_length) 02486 != SNMP_ERR_NOERROR) { 02487 DEBUGMSGTL(("usm", "Verification failed.\n")); 02488 snmp_increment_statistic(STAT_USMSTATSWRONGDIGESTS); 02489 snmp_log(LOG_WARNING, "Authentication failed for %s\n", 02490 user->name); 02491 return SNMPERR_USM_AUTHENTICATIONFAILURE; 02492 } 02493 02494 DEBUGMSGTL(("usm", "Verification succeeded.\n")); 02495 } 02496 02497 02498 /* 02499 * Steps 10-11 user is already set - relocated before timeliness 02500 * check in case it fails - still save user data for response. 02501 * 02502 * Cache the keys and protocol oids, per step 11 (s3.2). 02503 */ 02504 if (secStateRef) { 02505 if (usm_set_usmStateReference_auth_protocol(*secStateRef, 02506 user->authProtocol, 02507 user-> 02508 authProtocolLen) == 02509 -1) { 02510 DEBUGMSGTL(("usm", "%s\n", 02511 "Couldn't cache authentication protocol.")); 02512 return SNMPERR_USM_GENERICERROR; 02513 } 02514 02515 if (usm_set_usmStateReference_auth_key(*secStateRef, 02516 user->authKey, 02517 user->authKeyLen) == -1) { 02518 DEBUGMSGTL(("usm", "%s\n", 02519 "Couldn't cache authentication key.")); 02520 return SNMPERR_USM_GENERICERROR; 02521 } 02522 02523 if (usm_set_usmStateReference_priv_protocol(*secStateRef, 02524 user->privProtocol, 02525 user-> 02526 privProtocolLen) == 02527 -1) { 02528 DEBUGMSGTL(("usm", "%s\n", 02529 "Couldn't cache privacy protocol.")); 02530 return SNMPERR_USM_GENERICERROR; 02531 } 02532 02533 if (usm_set_usmStateReference_priv_key(*secStateRef, 02534 user->privKey, 02535 user->privKeyLen) == -1) { 02536 DEBUGMSGTL(("usm", "%s\n", "Couldn't cache privacy key.")); 02537 return SNMPERR_USM_GENERICERROR; 02538 } 02539 } 02540 02541 02542 /* 02543 * Perform the timeliness/time manager functions. 02544 */ 02545 if (secLevel == SNMP_SEC_LEVEL_AUTHNOPRIV 02546 || secLevel == SNMP_SEC_LEVEL_AUTHPRIV) { 02547 if (usm_check_and_update_timeliness(secEngineID, *secEngineIDLen, 02548 boots_uint, time_uint, 02549 &error) == -1) { 02550 return error; 02551 } 02552 } 02553 #ifdef LCD_TIME_SYNC_OPT 02554 /* 02555 * Cache the unauthenticated time to use in case we don't have 02556 * anything better - this guess will be no worse than (0,0) 02557 * that we normally use. 02558 */ 02559 else { 02560 set_enginetime(secEngineID, *secEngineIDLen, 02561 boots_uint, time_uint, FALSE); 02562 } 02563 #endif /* LCD_TIME_SYNC_OPT */ 02564 02565 02566 /* 02567 * If needed, decrypt the scoped PDU. 02568 */ 02569 if (secLevel == SNMP_SEC_LEVEL_AUTHPRIV) { 02570 remaining = wholeMsgLen - (data_ptr - wholeMsg); 02571 02572 if ((value_ptr = asn_parse_sequence(data_ptr, &remaining, 02573 &type_value, 02574 (ASN_UNIVERSAL | ASN_PRIMITIVE 02575 | ASN_OCTET_STR), 02576 "encrypted sPDU")) == NULL) { 02577 DEBUGMSGTL(("usm", "%s\n", 02578 "Failed while parsing encrypted sPDU.")); 02579 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS); 02580 usm_free_usmStateReference(*secStateRef); 02581 *secStateRef = NULL; 02582 return SNMPERR_USM_PARSEERROR; 02583 } 02584 02585 #ifndef NETSNMP_DISABLE_DES 02586 if (ISTRANSFORM(user->privProtocol, DESPriv)) { 02587 /* 02588 * From RFC2574: 02589 * 02590 * "Before decryption, the encrypted data length is verified. 02591 * If the length of the OCTET STRING to be decrypted is not 02592 * an integral multiple of 8 octets, the decryption process 02593 * is halted and an appropriate exception noted." 02594 */ 02595 02596 if (remaining % 8 != 0) { 02597 DEBUGMSGTL(("usm", 02598 "Ciphertext is %lu bytes, not an integer multiple of 8 (rem %lu)\n", 02599 (unsigned long)remaining, (unsigned long)remaining % 8)); 02600 snmp_increment_statistic(STAT_USMSTATSDECRYPTIONERRORS); 02601 usm_free_usmStateReference(*secStateRef); 02602 *secStateRef = NULL; 02603 return SNMPERR_USM_DECRYPTIONERROR; 02604 } 02605 02606 end_of_overhead = value_ptr; 02607 02608 if ( !user->privKey ) { 02609 DEBUGMSGTL(("usm", "No privacy pass phrase for %s\n", user->secName)); 02610 snmp_increment_statistic(STAT_USMSTATSDECRYPTIONERRORS); 02611 usm_free_usmStateReference(*secStateRef); 02612 *secStateRef = NULL; 02613 return SNMPERR_USM_DECRYPTIONERROR; 02614 } 02615 02616 /* 02617 * XOR the salt with the last (iv_length) bytes 02618 * of the priv_key to obtain the IV. 02619 */ 02620 iv_length = BYTESIZE(USM_DES_SALT_LENGTH); 02621 for (i = 0; i < (int) iv_length; i++) 02622 iv[i] = salt[i] ^ user->privKey[iv_length + i]; 02623 } 02624 #endif 02625 #ifdef HAVE_AES 02626 if (ISTRANSFORM(user->privProtocol, AESPriv)) { 02627 iv_length = BYTESIZE(USM_AES_SALT_LENGTH); 02628 net_boots = ntohl(boots_uint); 02629 net_time = ntohl(time_uint); 02630 memcpy(iv, &net_boots, 4); 02631 memcpy(iv+4, &net_time, 4); 02632 memcpy(iv+8, salt, salt_length); 02633 } 02634 #endif 02635 02636 if (sc_decrypt(user->privProtocol, user->privProtocolLen, 02637 user->privKey, user->privKeyLen, 02638 iv, iv_length, 02639 value_ptr, remaining, *scopedPdu, scopedPduLen) 02640 != SNMP_ERR_NOERROR) { 02641 DEBUGMSGTL(("usm", "%s\n", "Failed decryption.")); 02642 snmp_increment_statistic(STAT_USMSTATSDECRYPTIONERRORS); 02643 return SNMPERR_USM_DECRYPTIONERROR; 02644 } 02645 #ifdef NETSNMP_ENABLE_TESTING_CODE 02646 if (debug_is_token_registered("usm/dump") == SNMPERR_SUCCESS) { 02647 dump_chunk("usm/dump", "Cypher Text", value_ptr, remaining); 02648 dump_chunk("usm/dump", "salt + Encrypted form:", 02649 salt, salt_length); 02650 dump_chunk("usm/dump", "IV + Encrypted form:", iv, iv_length); 02651 dump_chunk("usm/dump", "Decrypted chunk:", 02652 *scopedPdu, *scopedPduLen); 02653 } 02654 #endif 02655 } 02656 /* 02657 * sPDU is plaintext. 02658 */ 02659 else { 02660 *scopedPdu = data_ptr; 02661 *scopedPduLen = wholeMsgLen - (data_ptr - wholeMsg); 02662 end_of_overhead = data_ptr; 02663 02664 } /* endif -- PDU decryption */ 02665 02666 02667 /* 02668 * Calculate the biggest sPDU for the response (i.e., whole - ovrhd). 02669 * 02670 * FIX Correct? 02671 */ 02672 *maxSizeResponse = maxMsgSize - (end_of_overhead - wholeMsg); 02673 02674 02675 DEBUGMSGTL(("usm", "USM processing completed.\n")); 02676 02677 return SNMPERR_SUCCESS; 02678 02679 } /* end usm_process_in_msg() */ 02680 02681 void 02682 usm_handle_report(void *sessp, 02683 netsnmp_transport *transport, netsnmp_session *session, 02684 int result, netsnmp_pdu *pdu) 02685 { 02686 /* 02687 * handle reportable errors 02688 */ 02689 02690 /* this will get in our way */ 02691 usm_free_usmStateReference(pdu->securityStateRef); 02692 pdu->securityStateRef = NULL; 02693 02694 switch (result) { 02695 case SNMPERR_USM_AUTHENTICATIONFAILURE: 02696 { 02697 int res = session->s_snmp_errno; 02698 session->s_snmp_errno = result; 02699 if (session->callback) { 02700 session->callback(NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE, 02701 session, pdu->reqid, pdu, 02702 session->callback_magic); 02703 } 02704 session->s_snmp_errno = res; 02705 } 02706 case SNMPERR_USM_UNKNOWNENGINEID: 02707 case SNMPERR_USM_UNKNOWNSECURITYNAME: 02708 case SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL: 02709 case SNMPERR_USM_NOTINTIMEWINDOW: 02710 case SNMPERR_USM_DECRYPTIONERROR: 02711 02712 if (SNMP_CMD_CONFIRMED(pdu->command) || 02713 (pdu->command == 0 02714 && (pdu->flags & SNMP_MSG_FLAG_RPRT_BIT))) { 02715 netsnmp_pdu *pdu2; 02716 int flags = pdu->flags; 02717 02718 pdu->flags |= UCD_MSG_FLAG_FORCE_PDU_COPY; 02719 pdu2 = snmp_clone_pdu(pdu); 02720 pdu->flags = pdu2->flags = flags; 02721 snmpv3_make_report(pdu2, result); 02722 if (0 == snmp_sess_send(sessp, pdu2)) { 02723 snmp_free_pdu(pdu2); 02724 /* 02725 * TODO: indicate error 02726 */ 02727 } 02728 } 02729 break; 02730 } 02731 } 02732 02733 /* sets up initial default session parameters */ 02734 int 02735 usm_session_init(netsnmp_session *in_session, netsnmp_session *session) 02736 { 02737 char *cp; 02738 size_t i; 02739 02740 if (in_session->securityAuthProtoLen > 0) { 02741 session->securityAuthProto = 02742 snmp_duplicate_objid(in_session->securityAuthProto, 02743 in_session->securityAuthProtoLen); 02744 if (session->securityAuthProto == NULL) { 02745 in_session->s_snmp_errno = SNMPERR_MALLOC; 02746 return SNMPERR_MALLOC; 02747 } 02748 } else if (get_default_authtype(&i) != NULL) { 02749 session->securityAuthProto = 02750 snmp_duplicate_objid(get_default_authtype(NULL), i); 02751 session->securityAuthProtoLen = i; 02752 } 02753 02754 if (in_session->securityPrivProtoLen > 0) { 02755 session->securityPrivProto = 02756 snmp_duplicate_objid(in_session->securityPrivProto, 02757 in_session->securityPrivProtoLen); 02758 if (session->securityPrivProto == NULL) { 02759 in_session->s_snmp_errno = SNMPERR_MALLOC; 02760 return SNMPERR_MALLOC; 02761 } 02762 } else if (get_default_privtype(&i) != NULL) { 02763 session->securityPrivProto = 02764 snmp_duplicate_objid(get_default_privtype(NULL), i); 02765 session->securityPrivProtoLen = i; 02766 } 02767 02768 if ((in_session->securityAuthKeyLen <= 0) && 02769 ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 02770 NETSNMP_DS_LIB_AUTHMASTERKEY)))) { 02771 size_t buflen = sizeof(session->securityAuthKey); 02772 u_char *tmpp = session->securityAuthKey; 02773 session->securityAuthKeyLen = 0; 02774 /* it will be a hex string */ 02775 if (!snmp_hex_to_binary(&tmpp, &buflen, 02776 &session->securityAuthKeyLen, 0, cp)) { 02777 snmp_set_detail("error parsing authentication master key"); 02778 return SNMP_ERR_GENERR; 02779 } 02780 } else if ((in_session->securityAuthKeyLen <= 0) && 02781 ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 02782 NETSNMP_DS_LIB_AUTHPASSPHRASE)) || 02783 (cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 02784 NETSNMP_DS_LIB_PASSPHRASE)))) { 02785 session->securityAuthKeyLen = USM_AUTH_KU_LEN; 02786 if (generate_Ku(session->securityAuthProto, 02787 session->securityAuthProtoLen, 02788 (u_char *) cp, strlen(cp), 02789 session->securityAuthKey, 02790 &session->securityAuthKeyLen) != SNMPERR_SUCCESS) { 02791 snmp_set_detail 02792 ("Error generating a key (Ku) from the supplied authentication pass phrase."); 02793 return SNMP_ERR_GENERR; 02794 } 02795 } 02796 02797 02798 if ((in_session->securityPrivKeyLen <= 0) && 02799 ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 02800 NETSNMP_DS_LIB_PRIVMASTERKEY)))) { 02801 size_t buflen = sizeof(session->securityPrivKey); 02802 u_char *tmpp = session->securityPrivKey; 02803 session->securityPrivKeyLen = 0; 02804 /* it will be a hex string */ 02805 if (!snmp_hex_to_binary(&tmpp, &buflen, 02806 &session->securityPrivKeyLen, 0, cp)) { 02807 snmp_set_detail("error parsing encryption master key"); 02808 return SNMP_ERR_GENERR; 02809 } 02810 } else if ((in_session->securityPrivKeyLen <= 0) && 02811 ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 02812 NETSNMP_DS_LIB_PRIVPASSPHRASE)) || 02813 (cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 02814 NETSNMP_DS_LIB_PASSPHRASE)))) { 02815 session->securityPrivKeyLen = USM_PRIV_KU_LEN; 02816 if (generate_Ku(session->securityAuthProto, 02817 session->securityAuthProtoLen, 02818 (u_char *) cp, strlen(cp), 02819 session->securityPrivKey, 02820 &session->securityPrivKeyLen) != SNMPERR_SUCCESS) { 02821 snmp_set_detail 02822 ("Error generating a key (Ku) from the supplied privacy pass phrase."); 02823 return SNMP_ERR_GENERR; 02824 } 02825 } 02826 02827 return SNMPERR_SUCCESS; 02828 } 02829 02830 02831 /* 02832 * usm_create_user_from_session(netsnmp_session *session): 02833 * 02834 * creates a user in the usm table from the information in a session. 02835 * If the user already exists, it is updated with the current 02836 * information from the session 02837 * 02838 * Parameters: 02839 * session -- IN: pointer to the session to use when creating the user. 02840 * 02841 * Returns: 02842 * SNMPERR_SUCCESS 02843 * SNMPERR_GENERR 02844 */ 02845 int 02846 usm_create_user_from_session(netsnmp_session * session) 02847 { 02848 struct usmUser *user; 02849 int user_just_created = 0; 02850 char *cp; 02851 02852 /* 02853 * - don't create-another/copy-into user for this session by default 02854 * - bail now (no error) if we don't have an engineID 02855 */ 02856 if (SNMP_FLAGS_USER_CREATED == (session->flags & SNMP_FLAGS_USER_CREATED) || 02857 session->securityModel != SNMP_SEC_MODEL_USM || 02858 session->version != SNMP_VERSION_3 || 02859 session->securityNameLen == 0 || 02860 session->securityEngineIDLen == 0) 02861 return SNMPERR_SUCCESS; 02862 02863 DEBUGMSGTL(("usm", "no flag defined... continuing\n")); 02864 session->flags |= SNMP_FLAGS_USER_CREATED; 02865 02866 /* 02867 * now that we have the engineID, create an entry in the USM list 02868 * for this user using the information in the session 02869 */ 02870 user = usm_get_user_from_list(session->securityEngineID, 02871 session->securityEngineIDLen, 02872 session->securityName, 02873 usm_get_userList(), 0); 02874 DEBUGMSGTL(("usm", "user exists? x=%p\n", user)); 02875 if (user == NULL) { 02876 DEBUGMSGTL(("usm", "Building user %s...\n", 02877 session->securityName)); 02878 /* 02879 * user doesn't exist so we create and add it 02880 */ 02881 user = (struct usmUser *) calloc(1, sizeof(struct usmUser)); 02882 if (user == NULL) 02883 return SNMPERR_GENERR; 02884 02885 /* 02886 * copy in the securityName 02887 */ 02888 if (session->securityName) { 02889 user->name = strdup(session->securityName); 02890 user->secName = strdup(session->securityName); 02891 if (user->name == NULL || user->secName == NULL) { 02892 usm_free_user(user); 02893 return SNMPERR_GENERR; 02894 } 02895 } 02896 02897 /* 02898 * copy in the engineID 02899 */ 02900 if (memdup(&user->engineID, session->securityEngineID, 02901 session->securityEngineIDLen) != SNMPERR_SUCCESS) { 02902 usm_free_user(user); 02903 return SNMPERR_GENERR; 02904 } 02905 user->engineIDLen = session->securityEngineIDLen; 02906 02907 user_just_created = 1; 02908 } 02909 02910 /* 02911 * copy the auth protocol 02912 */ 02913 if (user->authProtocol == NULL && session->securityAuthProto != NULL) { 02914 SNMP_FREE(user->authProtocol); 02915 user->authProtocol = 02916 snmp_duplicate_objid(session->securityAuthProto, 02917 session->securityAuthProtoLen); 02918 if (user->authProtocol == NULL) { 02919 usm_free_user(user); 02920 return SNMPERR_GENERR; 02921 } 02922 user->authProtocolLen = session->securityAuthProtoLen; 02923 } 02924 02925 /* 02926 * copy the priv protocol 02927 */ 02928 if (user->privProtocol == NULL && session->securityPrivProto != NULL) { 02929 SNMP_FREE(user->privProtocol); 02930 user->privProtocol = 02931 snmp_duplicate_objid(session->securityPrivProto, 02932 session->securityPrivProtoLen); 02933 if (user->privProtocol == NULL) { 02934 usm_free_user(user); 02935 return SNMPERR_GENERR; 02936 } 02937 user->privProtocolLen = session->securityPrivProtoLen; 02938 } 02939 02940 /* 02941 * copy in the authentication Key. If not localized, localize it 02942 */ 02943 if (user->authKey == NULL) { 02944 if (session->securityAuthLocalKey != NULL 02945 && session->securityAuthLocalKeyLen != 0) { 02946 /* already localized key passed in. use it */ 02947 SNMP_FREE(user->authKey); 02948 if (memdup(&user->authKey, session->securityAuthLocalKey, 02949 session->securityAuthLocalKeyLen) != SNMPERR_SUCCESS) { 02950 usm_free_user(user); 02951 return SNMPERR_GENERR; 02952 } 02953 user->authKeyLen = session->securityAuthLocalKeyLen; 02954 } else if (session->securityAuthKey != NULL 02955 && session->securityAuthKeyLen != 0) { 02956 SNMP_FREE(user->authKey); 02957 user->authKey = (u_char *) calloc(1, USM_LENGTH_KU_HASHBLOCK); 02958 if (user->authKey == NULL) { 02959 usm_free_user(user); 02960 return SNMPERR_GENERR; 02961 } 02962 user->authKeyLen = USM_LENGTH_KU_HASHBLOCK; 02963 if (generate_kul(user->authProtocol, user->authProtocolLen, 02964 session->securityEngineID, 02965 session->securityEngineIDLen, 02966 session->securityAuthKey, 02967 session->securityAuthKeyLen, user->authKey, 02968 &user->authKeyLen) != SNMPERR_SUCCESS) { 02969 usm_free_user(user); 02970 return SNMPERR_GENERR; 02971 } 02972 } else if ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 02973 NETSNMP_DS_LIB_AUTHLOCALIZEDKEY))) { 02974 size_t buflen = USM_AUTH_KU_LEN; 02975 SNMP_FREE(user->authKey); 02976 user->authKey = (u_char *)malloc(buflen); /* max length needed */ 02977 user->authKeyLen = 0; 02978 /* it will be a hex string */ 02979 if (!snmp_hex_to_binary(&user->authKey, &buflen, &user->authKeyLen, 02980 0, cp)) { 02981 usm_free_user(user); 02982 return SNMPERR_GENERR; 02983 } 02984 } 02985 } 02986 02987 /* 02988 * copy in the privacy Key. If not localized, localize it 02989 */ 02990 if (user->privKey == NULL) { 02991 if (session->securityPrivLocalKey != NULL 02992 && session->securityPrivLocalKeyLen != 0) { 02993 /* already localized key passed in. use it */ 02994 SNMP_FREE(user->privKey); 02995 if (memdup(&user->privKey, session->securityPrivLocalKey, 02996 session->securityPrivLocalKeyLen) != SNMPERR_SUCCESS) { 02997 usm_free_user(user); 02998 return SNMPERR_GENERR; 02999 } 03000 user->privKeyLen = session->securityPrivLocalKeyLen; 03001 } else if (session->securityPrivKey != NULL 03002 && session->securityPrivKeyLen != 0) { 03003 SNMP_FREE(user->privKey); 03004 user->privKey = (u_char *) calloc(1, USM_LENGTH_KU_HASHBLOCK); 03005 if (user->privKey == NULL) { 03006 usm_free_user(user); 03007 return SNMPERR_GENERR; 03008 } 03009 user->privKeyLen = USM_LENGTH_KU_HASHBLOCK; 03010 if (generate_kul(user->authProtocol, user->authProtocolLen, 03011 session->securityEngineID, 03012 session->securityEngineIDLen, 03013 session->securityPrivKey, 03014 session->securityPrivKeyLen, user->privKey, 03015 &user->privKeyLen) != SNMPERR_SUCCESS) { 03016 usm_free_user(user); 03017 return SNMPERR_GENERR; 03018 } 03019 } else if ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 03020 NETSNMP_DS_LIB_PRIVLOCALIZEDKEY))) { 03021 size_t buflen = USM_PRIV_KU_LEN; 03022 SNMP_FREE(user->privKey); 03023 user->privKey = (u_char *)malloc(buflen); /* max length needed */ 03024 user->privKeyLen = 0; 03025 /* it will be a hex string */ 03026 if (!snmp_hex_to_binary(&user->privKey, &buflen, &user->privKeyLen, 03027 0, cp)) { 03028 usm_free_user(user); 03029 return SNMPERR_GENERR; 03030 } 03031 } 03032 } 03033 03034 if (user_just_created) { 03035 /* 03036 * add the user into the database 03037 */ 03038 user->userStatus = RS_ACTIVE; 03039 user->userStorageType = ST_READONLY; 03040 usm_add_user(user); 03041 } 03042 03043 return SNMPERR_SUCCESS; 03044 03045 03046 } 03047 03048 /* A wrapper around the hook */ 03049 int 03050 usm_create_user_from_session_hook(void *slp, netsnmp_session *session) 03051 { 03052 DEBUGMSGTL(("usm", "potentially bootstrapping the USM table from session data\n")); 03053 return usm_create_user_from_session(session); 03054 } 03055 03056 static int 03057 usm_build_probe_pdu(netsnmp_pdu **pdu) 03058 { 03059 struct usmUser *user; 03060 03061 /* 03062 * create the pdu 03063 */ 03064 if (!pdu) 03065 return -1; 03066 *pdu = snmp_pdu_create(SNMP_MSG_GET); 03067 if (!(*pdu)) 03068 return -1; 03069 (*pdu)->version = SNMP_VERSION_3; 03070 (*pdu)->securityName = strdup(""); 03071 (*pdu)->securityNameLen = strlen((*pdu)->securityName); 03072 (*pdu)->securityLevel = SNMP_SEC_LEVEL_NOAUTH; 03073 (*pdu)->securityModel = SNMP_SEC_MODEL_USM; 03074 03075 /* 03076 * create the empty user 03077 */ 03078 user = usm_get_user(NULL, 0, (*pdu)->securityName); 03079 if (user == NULL) { 03080 user = (struct usmUser *) calloc(1, sizeof(struct usmUser)); 03081 if (user == NULL) { 03082 snmp_free_pdu(*pdu); 03083 *pdu = (netsnmp_pdu *) NULL; 03084 return -1; 03085 } 03086 user->name = strdup((*pdu)->securityName); 03087 user->secName = strdup((*pdu)->securityName); 03088 user->authProtocolLen = sizeof(usmNoAuthProtocol) / sizeof(oid); 03089 user->authProtocol = 03090 snmp_duplicate_objid(usmNoAuthProtocol, user->authProtocolLen); 03091 user->privProtocolLen = sizeof(usmNoPrivProtocol) / sizeof(oid); 03092 user->privProtocol = 03093 snmp_duplicate_objid(usmNoPrivProtocol, user->privProtocolLen); 03094 usm_add_user(user); 03095 } 03096 return 0; 03097 } 03098 03099 int usm_discover_engineid(void *slpv, netsnmp_session *session) { 03100 netsnmp_pdu *pdu = NULL, *response = NULL; 03101 int status, i; 03102 struct session_list *slp = (struct session_list *) slpv; 03103 03104 if (usm_build_probe_pdu(&pdu) != 0) { 03105 DEBUGMSGTL(("snmp_api", "unable to create probe PDU\n")); 03106 return SNMP_ERR_GENERR; 03107 } 03108 DEBUGMSGTL(("snmp_api", "probing for engineID...\n")); 03109 session->flags |= SNMP_FLAGS_DONT_PROBE; /* prevent recursion */ 03110 status = snmp_sess_synch_response(slp, pdu, &response); 03111 03112 if ((response == NULL) && (status == STAT_SUCCESS)) { 03113 status = STAT_ERROR; 03114 } 03115 03116 switch (status) { 03117 case STAT_SUCCESS: 03118 session->s_snmp_errno = SNMPERR_INVALID_MSG; /* XX?? */ 03119 DEBUGMSGTL(("snmp_sess_open", 03120 "error: expected Report as response to probe: %s (%ld)\n", 03121 snmp_errstring(response->errstat), 03122 response->errstat)); 03123 break; 03124 case STAT_ERROR: /* this is what we expected -> Report == STAT_ERROR */ 03125 session->s_snmp_errno = SNMPERR_UNKNOWN_ENG_ID; 03126 break; 03127 case STAT_TIMEOUT: 03128 session->s_snmp_errno = SNMPERR_TIMEOUT; 03129 default: 03130 DEBUGMSGTL(("snmp_sess_open", 03131 "unable to connect with remote engine: %s (%d)\n", 03132 snmp_api_errstring(session->s_snmp_errno), 03133 session->s_snmp_errno)); 03134 break; 03135 } 03136 03137 if (slp->session->securityEngineIDLen == 0) { 03138 DEBUGMSGTL(("snmp_api", 03139 "unable to determine remote engine ID\n")); 03140 /* clear the flag so that probe occurs on next inform */ 03141 session->flags &= ~SNMP_FLAGS_DONT_PROBE; 03142 return SNMP_ERR_GENERR; 03143 } 03144 03145 session->s_snmp_errno = SNMPERR_SUCCESS; 03146 if (snmp_get_do_debugging()) { 03147 DEBUGMSGTL(("snmp_sess_open", 03148 " probe found engineID: ")); 03149 for (i = 0; i < slp->session->securityEngineIDLen; i++) 03150 DEBUGMSG(("snmp_sess_open", "%02x", 03151 slp->session->securityEngineID[i])); 03152 DEBUGMSG(("snmp_sess_open", "\n")); 03153 } 03154 03155 /* 03156 * if boot/time supplied set it for this engineID 03157 */ 03158 if (session->engineBoots || session->engineTime) { 03159 set_enginetime(session->securityEngineID, 03160 session->securityEngineIDLen, 03161 session->engineBoots, session->engineTime, 03162 TRUE); 03163 } 03164 return SNMPERR_SUCCESS; 03165 } 03166 03167 void 03168 init_usm(void) 03169 { 03170 struct snmp_secmod_def *def; 03171 char *type; 03172 03173 DEBUGMSGTL(("init_usm", "unit_usm: %" NETSNMP_PRIo "u %" NETSNMP_PRIo "u\n", 03174 usmNoPrivProtocol[0], usmNoPrivProtocol[1])); 03175 03176 sc_init(); /* initalize scapi code */ 03177 03178 /* 03179 * register ourselves as a security service 03180 */ 03181 def = SNMP_MALLOC_STRUCT(snmp_secmod_def); 03182 if (def == NULL) 03183 return; 03184 /* 03185 * XXX: def->init_sess_secmod move stuff from snmp_api.c 03186 */ 03187 def->encode_reverse = usm_secmod_rgenerate_out_msg; 03188 def->encode_forward = usm_secmod_generate_out_msg; 03189 def->decode = usm_secmod_process_in_msg; 03190 def->pdu_free_state_ref = usm_free_usmStateReference; 03191 def->session_setup = usm_session_init; 03192 def->handle_report = usm_handle_report; 03193 def->probe_engineid = usm_discover_engineid; 03194 def->post_probe_engineid = usm_create_user_from_session_hook; 03195 register_sec_mod(USM_SEC_MODEL_NUMBER, "usm", def); 03196 03197 snmp_register_callback(SNMP_CALLBACK_LIBRARY, 03198 SNMP_CALLBACK_POST_PREMIB_READ_CONFIG, 03199 init_usm_post_config, NULL); 03200 03201 snmp_register_callback(SNMP_CALLBACK_LIBRARY, 03202 SNMP_CALLBACK_SHUTDOWN, 03203 deinit_usm_post_config, NULL); 03204 03205 snmp_register_callback(SNMP_CALLBACK_LIBRARY, 03206 SNMP_CALLBACK_SHUTDOWN, 03207 free_engineID, NULL); 03208 03209 register_config_handler("snmp", "defAuthType", snmpv3_authtype_conf, 03210 NULL, "MD5|SHA"); 03211 register_config_handler("snmp", "defPrivType", snmpv3_privtype_conf, 03212 NULL, 03213 #ifdef HAVE_AES 03214 "DES|AES" 03215 #else 03216 "DES (AES support not available)" 03217 #endif 03218 ); 03219 03220 /* 03221 * Free stuff at shutdown time 03222 */ 03223 snmp_register_callback(SNMP_CALLBACK_LIBRARY, 03224 SNMP_CALLBACK_SHUTDOWN, 03225 free_enginetime_on_shutdown, NULL); 03226 03227 03228 type = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_APPTYPE); 03229 03230 register_config_handler(type, "userSetAuthPass", usm_set_password, 03231 NULL, NULL); 03232 register_config_handler(type, "userSetPrivPass", usm_set_password, 03233 NULL, NULL); 03234 register_config_handler(type, "userSetAuthKey", usm_set_password, NULL, 03235 NULL); 03236 register_config_handler(type, "userSetPrivKey", usm_set_password, NULL, 03237 NULL); 03238 register_config_handler(type, "userSetAuthLocalKey", usm_set_password, 03239 NULL, NULL); 03240 register_config_handler(type, "userSetPrivLocalKey", usm_set_password, 03241 NULL, NULL); 03242 } 03243 03244 void 03245 init_usm_conf(const char *app) 03246 { 03247 register_config_handler(app, "usmUser", 03248 usm_parse_config_usmUser, NULL, NULL); 03249 register_config_handler(app, "createUser", 03250 usm_parse_create_usmUser, NULL, 03251 "username [-e ENGINEID] (MD5|SHA) authpassphrase [DES [privpassphrase]]"); 03252 03253 /* 03254 * we need to be called back later 03255 */ 03256 snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA, 03257 usm_store_users, NULL); 03258 } 03259 03260 /* 03261 * initializations for the USM. 03262 * 03263 * Should be called after the (engineid) configuration files have been read. 03264 * 03265 * Set "arbitrary" portion of salt to a random number. 03266 */ 03267 int 03268 init_usm_post_config(int majorid, int minorid, void *serverarg, 03269 void *clientarg) 03270 { 03271 size_t salt_integer_len = sizeof(salt_integer); 03272 03273 if (sc_random((u_char *) & salt_integer, &salt_integer_len) != 03274 SNMPERR_SUCCESS) { 03275 DEBUGMSGTL(("usm", "sc_random() failed: using time() as salt.\n")); 03276 salt_integer = (u_int) time(NULL); 03277 } 03278 03279 #ifdef HAVE_AES 03280 salt_integer_len = sizeof (salt_integer64_1); 03281 if (sc_random((u_char *) & salt_integer64_1, &salt_integer_len) != 03282 SNMPERR_SUCCESS) { 03283 DEBUGMSGTL(("usm", "sc_random() failed: using time() as aes1 salt.\n")); 03284 salt_integer64_1 = (u_int) time(NULL); 03285 } 03286 salt_integer_len = sizeof (salt_integer64_1); 03287 if (sc_random((u_char *) & salt_integer64_2, &salt_integer_len) != 03288 SNMPERR_SUCCESS) { 03289 DEBUGMSGTL(("usm", "sc_random() failed: using time() as aes2 salt.\n")); 03290 salt_integer64_2 = (u_int) time(NULL); 03291 } 03292 #endif 03293 03294 #ifndef NETSNMP_DISABLE_MD5 03295 noNameUser = usm_create_initial_user("", usmHMACMD5AuthProtocol, 03296 USM_LENGTH_OID_TRANSFORM, 03297 #ifndef NETSNMP_DISABLE_DES 03298 usmDESPrivProtocol, 03299 #else 03300 usmAESPrivProtocol, 03301 #endif 03302 USM_LENGTH_OID_TRANSFORM); 03303 #else 03304 noNameUser = usm_create_initial_user("", usmHMACSHA1AuthProtocol, 03305 USM_LENGTH_OID_TRANSFORM, 03306 #ifndef NETSNMP_DISABLE_DES 03307 usmDESPrivProtocol, 03308 #else 03309 usmAESPrivProtocol, 03310 #endif 03311 USM_LENGTH_OID_TRANSFORM); 03312 #endif 03313 03314 if ( noNameUser ) { 03315 SNMP_FREE(noNameUser->engineID); 03316 noNameUser->engineIDLen = 0; 03317 } 03318 03319 return SNMPERR_SUCCESS; 03320 } /* end init_usm_post_config() */ 03321 03322 int 03323 deinit_usm_post_config(int majorid, int minorid, void *serverarg, 03324 void *clientarg) 03325 { 03326 if (usm_free_user(noNameUser) != NULL) { 03327 DEBUGMSGTL(("deinit_usm_post_config", "could not free initial user\n")); 03328 return SNMPERR_GENERR; 03329 } 03330 noNameUser = NULL; 03331 03332 DEBUGMSGTL(("deinit_usm_post_config", "initial user removed\n")); 03333 return SNMPERR_SUCCESS; 03334 } /* end deinit_usm_post_config() */ 03335 03336 void 03337 clear_user_list(void) 03338 { 03339 struct usmUser *tmp = userList, *next = NULL; 03340 03341 while (tmp != NULL) { 03342 next = tmp->next; 03343 usm_free_user(tmp); 03344 tmp = next; 03345 } 03346 userList = NULL; 03347 03348 } 03349 03350 void 03351 shutdown_usm(void) 03352 { 03353 free_etimelist(); 03354 clear_user_list(); 03355 } 03356 03357 /*******************************************************************-o-****** 03358 * usm_check_secLevel 03359 * 03360 * Parameters: 03361 * level 03362 * *user 03363 * 03364 * Returns: 03365 * 0 On success, 03366 * -1 Otherwise. 03367 * 03368 * Checks that a given security level is valid for a given user. 03369 */ 03370 int 03371 usm_check_secLevel(int level, struct usmUser *user) 03372 { 03373 03374 if (user->userStatus != RS_ACTIVE) 03375 return -1; 03376 03377 DEBUGMSGTL(("comparex", "Comparing: %" NETSNMP_PRIo "u %" NETSNMP_PRIo "u ", 03378 usmNoPrivProtocol[0], usmNoPrivProtocol[1])); 03379 DEBUGMSGOID(("comparex", usmNoPrivProtocol, 03380 sizeof(usmNoPrivProtocol) / sizeof(oid))); 03381 DEBUGMSG(("comparex", "\n")); 03382 if (level == SNMP_SEC_LEVEL_AUTHPRIV 03383 && (netsnmp_oid_equals(user->privProtocol, user->privProtocolLen, 03384 usmNoPrivProtocol, 03385 sizeof(usmNoPrivProtocol) / sizeof(oid)) == 03386 0)) { 03387 DEBUGMSGTL(("usm", "Level: %d\n", level)); 03388 DEBUGMSGTL(("usm", "User (%s) Auth Protocol: ", user->name)); 03389 DEBUGMSGOID(("usm", user->authProtocol, user->authProtocolLen)); 03390 DEBUGMSG(("usm", ", User Priv Protocol: ")); 03391 DEBUGMSGOID(("usm", user->privProtocol, user->privProtocolLen)); 03392 DEBUGMSG(("usm", "\n")); 03393 return 1; 03394 } 03395 if ((level == SNMP_SEC_LEVEL_AUTHPRIV 03396 || level == SNMP_SEC_LEVEL_AUTHNOPRIV) 03397 && 03398 (netsnmp_oid_equals 03399 (user->authProtocol, user->authProtocolLen, usmNoAuthProtocol, 03400 sizeof(usmNoAuthProtocol) / sizeof(oid)) == 0)) { 03401 DEBUGMSGTL(("usm", "Level: %d\n", level)); 03402 DEBUGMSGTL(("usm", "User (%s) Auth Protocol: ", user->name)); 03403 DEBUGMSGOID(("usm", user->authProtocol, user->authProtocolLen)); 03404 DEBUGMSG(("usm", ", User Priv Protocol: ")); 03405 DEBUGMSGOID(("usm", user->privProtocol, user->privProtocolLen)); 03406 DEBUGMSG(("usm", "\n")); 03407 return 1; 03408 } 03409 03410 return 0; 03411 03412 } /* end usm_check_secLevel() */ 03413 03414 03415 03416 03417 /*******************************************************************-o-****** 03418 * usm_check_secLevel_vs_protocols 03419 * 03420 * Parameters: 03421 * level 03422 * *authProtocol 03423 * authProtocolLen 03424 * *privProtocol 03425 * privProtocolLen 03426 * 03427 * Returns: 03428 * 0 On success, 03429 * 1 Otherwise. 03430 * 03431 * Same as above but with explicitly named transform types instead of taking 03432 * from the usmUser structure. 03433 */ 03434 int 03435 usm_check_secLevel_vs_protocols(int level, 03436 const oid * authProtocol, 03437 u_int authProtocolLen, 03438 const oid * privProtocol, 03439 u_int privProtocolLen) 03440 { 03441 03442 if (level == SNMP_SEC_LEVEL_AUTHPRIV 03443 && 03444 (netsnmp_oid_equals 03445 (privProtocol, privProtocolLen, usmNoPrivProtocol, 03446 sizeof(usmNoPrivProtocol) / sizeof(oid)) == 0)) { 03447 DEBUGMSGTL(("usm", "Level: %d\n", level)); 03448 DEBUGMSGTL(("usm", "Auth Protocol: ")); 03449 DEBUGMSGOID(("usm", authProtocol, authProtocolLen)); 03450 DEBUGMSG(("usm", ", Priv Protocol: ")); 03451 DEBUGMSGOID(("usm", privProtocol, privProtocolLen)); 03452 DEBUGMSG(("usm", "\n")); 03453 return 1; 03454 } 03455 if ((level == SNMP_SEC_LEVEL_AUTHPRIV 03456 || level == SNMP_SEC_LEVEL_AUTHNOPRIV) 03457 && 03458 (netsnmp_oid_equals 03459 (authProtocol, authProtocolLen, usmNoAuthProtocol, 03460 sizeof(usmNoAuthProtocol) / sizeof(oid)) == 0)) { 03461 DEBUGMSGTL(("usm", "Level: %d\n", level)); 03462 DEBUGMSGTL(("usm", "Auth Protocol: ")); 03463 DEBUGMSGOID(("usm", authProtocol, authProtocolLen)); 03464 DEBUGMSG(("usm", ", Priv Protocol: ")); 03465 DEBUGMSGOID(("usm", privProtocol, privProtocolLen)); 03466 DEBUGMSG(("usm", "\n")); 03467 return 1; 03468 } 03469 03470 return 0; 03471 03472 } /* end usm_check_secLevel_vs_protocols() */ 03473 03474 03475 03476 03477 /* 03478 * usm_get_user(): Returns a user from userList based on the engineID, 03479 * engineIDLen and name of the requested user. 03480 */ 03481 03482 struct usmUser * 03483 usm_get_user(u_char * engineID, size_t engineIDLen, char *name) 03484 { 03485 DEBUGMSGTL(("usm", "getting user %s\n", name)); 03486 return usm_get_user_from_list(engineID, engineIDLen, name, userList, 03487 1); 03488 } 03489 03490 struct usmUser * 03491 usm_get_user_from_list(u_char * engineID, size_t engineIDLen, 03492 char *name, struct usmUser *puserList, 03493 int use_default) 03494 { 03495 struct usmUser *ptr; 03496 char noName[] = ""; 03497 if (name == NULL) 03498 name = noName; 03499 for (ptr = puserList; ptr != NULL; ptr = ptr->next) { 03500 if (ptr->name && !strcmp(ptr->name, name)) { 03501 DEBUGMSGTL(("usm", "match on user %s\n", ptr->name)); 03502 if (ptr->engineIDLen == engineIDLen && 03503 ((ptr->engineID == NULL && engineID == NULL) || 03504 (ptr->engineID != NULL && engineID != NULL && 03505 memcmp(ptr->engineID, engineID, engineIDLen) == 0))) 03506 return ptr; 03507 DEBUGMSGTL(("usm", "no match on engineID (")); 03508 if (engineID) { 03509 DEBUGMSGHEX(("usm", engineID, engineIDLen)); 03510 } else { 03511 DEBUGMSGTL(("usm", "Empty EngineID")); 03512 } 03513 DEBUGMSG(("usm", ")\n")); 03514 } 03515 } 03516 03517 /* 03518 * return "" user used to facilitate engineID discovery 03519 */ 03520 if (use_default && !strcmp(name, "")) 03521 return noNameUser; 03522 return NULL; 03523 } 03524 03525 /* 03526 * usm_add_user(): Add's a user to the userList, sorted by the 03527 * engineIDLength then the engineID then the name length then the name 03528 * to facilitate getNext calls on a usmUser table which is indexed by 03529 * these values. 03530 * 03531 * returns the head of the list (which could change due to this add). 03532 */ 03533 03534 struct usmUser * 03535 usm_add_user(struct usmUser *user) 03536 { 03537 struct usmUser *uptr; 03538 uptr = usm_add_user_to_list(user, userList); 03539 if (uptr != NULL) 03540 userList = uptr; 03541 return uptr; 03542 } 03543 03544 struct usmUser * 03545 usm_add_user_to_list(struct usmUser *user, struct usmUser *puserList) 03546 { 03547 struct usmUser *nptr, *pptr, *optr; 03548 03549 /* 03550 * loop through puserList till we find the proper, sorted place to 03551 * insert the new user 03552 */ 03553 /* XXX - how to handle a NULL user->name ?? */ 03554 /* XXX - similarly for a NULL nptr->name ?? */ 03555 for (nptr = puserList, pptr = NULL; nptr != NULL; 03556 pptr = nptr, nptr = nptr->next) { 03557 if (nptr->engineIDLen > user->engineIDLen) 03558 break; 03559 03560 if (user->engineID == NULL && nptr->engineID != NULL) 03561 break; 03562 03563 if (nptr->engineIDLen == user->engineIDLen && 03564 (nptr->engineID != NULL && user->engineID != NULL && 03565 memcmp(nptr->engineID, user->engineID, 03566 user->engineIDLen) > 0)) 03567 break; 03568 03569 if (!(nptr->engineID == NULL && user->engineID != NULL)) { 03570 if (nptr->engineIDLen == user->engineIDLen && 03571 ((nptr->engineID == NULL && user->engineID == NULL) || 03572 memcmp(nptr->engineID, user->engineID, 03573 user->engineIDLen) == 0) 03574 && strlen(nptr->name) > strlen(user->name)) 03575 break; 03576 03577 if (nptr->engineIDLen == user->engineIDLen && 03578 ((nptr->engineID == NULL && user->engineID == NULL) || 03579 memcmp(nptr->engineID, user->engineID, 03580 user->engineIDLen) == 0) 03581 && strlen(nptr->name) == strlen(user->name) 03582 && strcmp(nptr->name, user->name) > 0) 03583 break; 03584 03585 if (nptr->engineIDLen == user->engineIDLen && 03586 ((nptr->engineID == NULL && user->engineID == NULL) || 03587 memcmp(nptr->engineID, user->engineID, 03588 user->engineIDLen) == 0) 03589 && strlen(nptr->name) == strlen(user->name) 03590 && strcmp(nptr->name, user->name) == 0) { 03591 /* 03592 * the user is an exact match of a previous entry. 03593 * Credentials may be different, though, so remove 03594 * the old entry (and add the new one)! 03595 */ 03596 if (pptr) { /* change prev's next pointer */ 03597 pptr->next = nptr->next; 03598 } 03599 if (nptr->next) { /* change next's prev pointer */ 03600 nptr->next->prev = pptr; 03601 } 03602 optr = nptr; 03603 nptr = optr->next; /* add new user at this position */ 03604 /* free the old user */ 03605 optr->next=NULL; 03606 optr->prev=NULL; 03607 usm_free_user(optr); 03608 break; /* new user will be added below */ 03609 } 03610 } 03611 } 03612 03613 /* 03614 * nptr should now point to the user that we need to add ourselves 03615 * in front of, and pptr should be our new 'prev'. 03616 */ 03617 03618 /* 03619 * change our pointers 03620 */ 03621 user->prev = pptr; 03622 user->next = nptr; 03623 03624 /* 03625 * change the next's prev pointer 03626 */ 03627 if (user->next) 03628 user->next->prev = user; 03629 03630 /* 03631 * change the prev's next pointer 03632 */ 03633 if (user->prev) 03634 user->prev->next = user; 03635 03636 /* 03637 * rewind to the head of the list and return it (since the new head 03638 * could be us, we need to notify the above routine who the head now is. 03639 */ 03640 for (pptr = user; pptr->prev != NULL; pptr = pptr->prev); 03641 return pptr; 03642 } 03643 03644 /* 03645 * usm_remove_user(): finds and removes a user from a list 03646 */ 03647 struct usmUser * 03648 usm_remove_user(struct usmUser *user) 03649 { 03650 return usm_remove_user_from_list(user, &userList); 03651 } 03652 03653 struct usmUser * 03654 usm_remove_user_from_list(struct usmUser *user, 03655 struct usmUser **ppuserList) 03656 { 03657 struct usmUser *nptr, *pptr; 03658 03659 /* 03660 * NULL pointers aren't allowed 03661 */ 03662 if (ppuserList == NULL) 03663 return NULL; 03664 03665 if (*ppuserList == NULL) 03666 return NULL; 03667 03668 /* 03669 * find the user in the list 03670 */ 03671 for (nptr = *ppuserList, pptr = NULL; nptr != NULL; 03672 pptr = nptr, nptr = nptr->next) { 03673 if (nptr == user) 03674 break; 03675 } 03676 03677 if (nptr) { 03678 /* 03679 * remove the user from the linked list 03680 */ 03681 if (pptr) { 03682 pptr->next = nptr->next; 03683 } 03684 if (nptr->next) { 03685 nptr->next->prev = pptr; 03686 } 03687 } else { 03688 /* 03689 * user didn't exist 03690 */ 03691 return NULL; 03692 } 03693 if (nptr == *ppuserList) /* we're the head of the list, need to change 03694 * * the head to the next user */ 03695 *ppuserList = nptr->next; 03696 return *ppuserList; 03697 } /* end usm_remove_user_from_list() */ 03698 03699 03700 03701 03702 /* 03703 * usm_free_user(): calls free() on all needed parts of struct usmUser and 03704 * the user himself. 03705 * 03706 * Note: This should *not* be called on an object in a list (IE, 03707 * remove it from the list first, and set next and prev to NULL), but 03708 * will try to reconnect the list pieces again if it is called this 03709 * way. If called on the head of the list, the entire list will be 03710 * lost. 03711 */ 03712 struct usmUser * 03713 usm_free_user(struct usmUser *user) 03714 { 03715 if (user == NULL) 03716 return NULL; 03717 03718 SNMP_FREE(user->engineID); 03719 SNMP_FREE(user->name); 03720 SNMP_FREE(user->secName); 03721 SNMP_FREE(user->cloneFrom); 03722 SNMP_FREE(user->userPublicString); 03723 SNMP_FREE(user->authProtocol); 03724 SNMP_FREE(user->privProtocol); 03725 03726 if (user->authKey != NULL) { 03727 SNMP_ZERO(user->authKey, user->authKeyLen); 03728 SNMP_FREE(user->authKey); 03729 } 03730 03731 if (user->privKey != NULL) { 03732 SNMP_ZERO(user->privKey, user->privKeyLen); 03733 SNMP_FREE(user->privKey); 03734 } 03735 03736 03737 /* 03738 * FIX Why not put this check *first?* 03739 */ 03740 if (user->prev != NULL) { /* ack, this shouldn't happen */ 03741 user->prev->next = user->next; 03742 } 03743 if (user->next != NULL) { 03744 user->next->prev = user->prev; 03745 if (user->prev != NULL) /* ack this is really bad, because it means 03746 * * we'll loose the head of some structure tree */ 03747 DEBUGMSGTL(("usm", 03748 "Severe: Asked to free the head of a usmUser tree somewhere.")); 03749 } 03750 03751 03752 SNMP_ZERO(user, sizeof(*user)); 03753 SNMP_FREE(user); 03754 03755 return NULL; /* for convenience to returns from calling functions */ 03756 03757 } /* end usm_free_user() */ 03758 03759 03760 03761 03762 #ifndef NETSNMP_NO_WRITE_SUPPORT 03763 /* 03764 * take a given user and clone the security info into another 03765 */ 03766 struct usmUser * 03767 usm_cloneFrom_user(struct usmUser *from, struct usmUser *to) 03768 { 03769 /* 03770 * copy the authProtocol oid row pointer 03771 */ 03772 SNMP_FREE(to->authProtocol); 03773 03774 if ((to->authProtocol = 03775 snmp_duplicate_objid(from->authProtocol, 03776 from->authProtocolLen)) != NULL) 03777 to->authProtocolLen = from->authProtocolLen; 03778 else 03779 to->authProtocolLen = 0; 03780 03781 03782 /* 03783 * copy the authKey 03784 */ 03785 SNMP_FREE(to->authKey); 03786 03787 if (from->authKeyLen > 0 && 03788 (to->authKey = (u_char *) malloc(from->authKeyLen)) 03789 != NULL) { 03790 to->authKeyLen = from->authKeyLen; 03791 memcpy(to->authKey, from->authKey, to->authKeyLen); 03792 } else { 03793 to->authKey = NULL; 03794 to->authKeyLen = 0; 03795 } 03796 03797 03798 /* 03799 * copy the privProtocol oid row pointer 03800 */ 03801 SNMP_FREE(to->privProtocol); 03802 03803 if ((to->privProtocol = 03804 snmp_duplicate_objid(from->privProtocol, 03805 from->privProtocolLen)) != NULL) 03806 to->privProtocolLen = from->privProtocolLen; 03807 else 03808 to->privProtocolLen = 0; 03809 03810 /* 03811 * copy the privKey 03812 */ 03813 SNMP_FREE(to->privKey); 03814 03815 if (from->privKeyLen > 0 && 03816 (to->privKey = (u_char *) malloc(from->privKeyLen)) 03817 != NULL) { 03818 to->privKeyLen = from->privKeyLen; 03819 memcpy(to->privKey, from->privKey, to->privKeyLen); 03820 } else { 03821 to->privKey = NULL; 03822 to->privKeyLen = 0; 03823 } 03824 return to; 03825 } 03826 #endif /* NETSNMP_NO_WRITE_SUPPORT */ 03827 03828 /* 03829 * usm_create_user(void): 03830 * create a default empty user, instantiating only the auth/priv 03831 * protocols to noAuth and noPriv OID pointers 03832 */ 03833 struct usmUser * 03834 usm_create_user(void) 03835 { 03836 struct usmUser *newUser; 03837 03838 /* 03839 * create the new user 03840 */ 03841 newUser = (struct usmUser *) calloc(1, sizeof(struct usmUser)); 03842 if (newUser == NULL) 03843 return NULL; 03844 03845 /* 03846 * fill the auth/priv protocols 03847 */ 03848 if ((newUser->authProtocol = 03849 snmp_duplicate_objid(usmNoAuthProtocol, 03850 sizeof(usmNoAuthProtocol) / sizeof(oid))) == 03851 NULL) 03852 return usm_free_user(newUser); 03853 newUser->authProtocolLen = sizeof(usmNoAuthProtocol) / sizeof(oid); 03854 03855 if ((newUser->privProtocol = 03856 snmp_duplicate_objid(usmNoPrivProtocol, 03857 sizeof(usmNoPrivProtocol) / sizeof(oid))) == 03858 NULL) 03859 return usm_free_user(newUser); 03860 newUser->privProtocolLen = sizeof(usmNoPrivProtocol) / sizeof(oid); 03861 03862 /* 03863 * set the storage type to nonvolatile, and the status to ACTIVE 03864 */ 03865 newUser->userStorageType = ST_NONVOLATILE; 03866 newUser->userStatus = RS_ACTIVE; 03867 return newUser; 03868 03869 } /* end usm_clone_user() */ 03870 03871 03872 03873 03874 /* 03875 * usm_create_initial_user(void): 03876 * creates an initial user, filled with the defaults defined in the 03877 * USM document. 03878 */ 03879 struct usmUser * 03880 usm_create_initial_user(const char *name, 03881 const oid * authProtocol, size_t authProtocolLen, 03882 const oid * privProtocol, size_t privProtocolLen) 03883 { 03884 struct usmUser *newUser = usm_create_user(); 03885 if (newUser == NULL) 03886 return NULL; 03887 03888 if ((newUser->name = strdup(name)) == NULL) 03889 return usm_free_user(newUser); 03890 03891 if ((newUser->secName = strdup(name)) == NULL) 03892 return usm_free_user(newUser); 03893 03894 if ((newUser->engineID = 03895 snmpv3_generate_engineID(&newUser->engineIDLen)) == NULL) 03896 return usm_free_user(newUser); 03897 03898 if ((newUser->cloneFrom = (oid *) malloc(sizeof(oid) * 2)) == NULL) 03899 return usm_free_user(newUser); 03900 newUser->cloneFrom[0] = 0; 03901 newUser->cloneFrom[1] = 0; 03902 newUser->cloneFromLen = 2; 03903 03904 SNMP_FREE(newUser->privProtocol); 03905 if ((newUser->privProtocol = snmp_duplicate_objid(privProtocol, 03906 privProtocolLen)) == 03907 NULL) { 03908 return usm_free_user(newUser); 03909 } 03910 newUser->privProtocolLen = privProtocolLen; 03911 03912 SNMP_FREE(newUser->authProtocol); 03913 if ((newUser->authProtocol = snmp_duplicate_objid(authProtocol, 03914 authProtocolLen)) == 03915 NULL) { 03916 return usm_free_user(newUser); 03917 } 03918 newUser->authProtocolLen = authProtocolLen; 03919 03920 newUser->userStatus = RS_ACTIVE; 03921 newUser->userStorageType = ST_READONLY; 03922 03923 return newUser; 03924 } 03925 03926 /* 03927 * this is a callback that can store all known users based on a 03928 * previously registered application ID 03929 */ 03930 int 03931 usm_store_users(int majorID, int minorID, void *serverarg, void *clientarg) 03932 { 03933 /* 03934 * figure out our application name 03935 */ 03936 char *appname = (char *) clientarg; 03937 if (appname == NULL) { 03938 appname = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 03939 NETSNMP_DS_LIB_APPTYPE); 03940 } 03941 03942 /* 03943 * save the user base 03944 */ 03945 usm_save_users("usmUser", appname); 03946 03947 /* 03948 * never fails 03949 */ 03950 return SNMPERR_SUCCESS; 03951 } 03952 03953 03954 /* 03955 * usm_save_users(): saves a list of users to the persistent cache 03956 */ 03957 void 03958 usm_save_users(const char *token, const char *type) 03959 { 03960 usm_save_users_from_list(userList, token, type); 03961 } 03962 03963 void 03964 usm_save_users_from_list(struct usmUser *puserList, const char *token, 03965 const char *type) 03966 { 03967 struct usmUser *uptr; 03968 for (uptr = puserList; uptr != NULL; uptr = uptr->next) { 03969 if (uptr->userStorageType == ST_NONVOLATILE) 03970 usm_save_user(uptr, token, type); 03971 } 03972 } 03973 03974 /* 03975 * usm_save_user(): saves a user to the persistent cache 03976 */ 03977 void 03978 usm_save_user(struct usmUser *user, const char *token, const char *type) 03979 { 03980 char line[4096]; 03981 char *cptr; 03982 03983 memset(line, 0, sizeof(line)); 03984 03985 sprintf(line, "%s %d %d ", token, user->userStatus, 03986 user->userStorageType); 03987 cptr = &line[strlen(line)]; /* the NULL */ 03988 cptr = 03989 read_config_save_octet_string(cptr, user->engineID, 03990 user->engineIDLen); 03991 *cptr++ = ' '; 03992 cptr = read_config_save_octet_string(cptr, (u_char *) user->name, 03993 (user->name == NULL) ? 0 : 03994 strlen(user->name)); 03995 *cptr++ = ' '; 03996 cptr = read_config_save_octet_string(cptr, (u_char *) user->secName, 03997 (user->secName == NULL) ? 0 : 03998 strlen(user->secName)); 03999 *cptr++ = ' '; 04000 cptr = 04001 read_config_save_objid(cptr, user->cloneFrom, user->cloneFromLen); 04002 *cptr++ = ' '; 04003 cptr = read_config_save_objid(cptr, user->authProtocol, 04004 user->authProtocolLen); 04005 *cptr++ = ' '; 04006 cptr = 04007 read_config_save_octet_string(cptr, user->authKey, 04008 user->authKeyLen); 04009 *cptr++ = ' '; 04010 cptr = read_config_save_objid(cptr, user->privProtocol, 04011 user->privProtocolLen); 04012 *cptr++ = ' '; 04013 cptr = 04014 read_config_save_octet_string(cptr, user->privKey, 04015 user->privKeyLen); 04016 *cptr++ = ' '; 04017 cptr = read_config_save_octet_string(cptr, user->userPublicString, 04018 user->userPublicStringLen); 04019 04020 read_config_store(type, line); 04021 } 04022 04023 /* 04024 * usm_parse_user(): reads in a line containing a saved user profile 04025 * and returns a pointer to a newly created struct usmUser. 04026 */ 04027 struct usmUser * 04028 usm_read_user(const char *line) 04029 { 04030 struct usmUser *user; 04031 size_t len; 04032 size_t expected_privKeyLen = 0; 04033 04034 user = usm_create_user(); 04035 if (user == NULL) 04036 return NULL; 04037 04038 user->userStatus = atoi(line); 04039 line = skip_token_const(line); 04040 user->userStorageType = atoi(line); 04041 line = skip_token_const(line); 04042 line = read_config_read_octet_string_const(line, &user->engineID, 04043 &user->engineIDLen); 04044 04045 /* 04046 * set the lcd entry for this engineID to the minimum boots/time 04047 * values so that its a known engineid and won't return a report pdu. 04048 * This is mostly important when receiving v3 traps so that the usm 04049 * will at least continue processing them. 04050 */ 04051 set_enginetime(user->engineID, user->engineIDLen, 1, 0, 0); 04052 04053 line = read_config_read_octet_string(line, (u_char **) & user->name, 04054 &len); 04055 line = read_config_read_octet_string(line, (u_char **) & user->secName, 04056 &len); 04057 SNMP_FREE(user->cloneFrom); 04058 user->cloneFromLen = 0; 04059 04060 line = read_config_read_objid_const(line, &user->cloneFrom, 04061 &user->cloneFromLen); 04062 04063 SNMP_FREE(user->authProtocol); 04064 user->authProtocolLen = 0; 04065 04066 line = read_config_read_objid_const(line, &user->authProtocol, 04067 &user->authProtocolLen); 04068 line = read_config_read_octet_string_const(line, &user->authKey, 04069 &user->authKeyLen); 04070 SNMP_FREE(user->privProtocol); 04071 user->privProtocolLen = 0; 04072 04073 line = read_config_read_objid_const(line, &user->privProtocol, 04074 &user->privProtocolLen); 04075 line = read_config_read_octet_string(line, &user->privKey, 04076 &user->privKeyLen); 04077 #ifndef NETSNMP_DISABLE_DES 04078 if (ISTRANSFORM(user->privProtocol, DESPriv)) { 04079 /* DES uses a 128 bit key, 64 bits of which is a salt */ 04080 expected_privKeyLen = 16; 04081 } 04082 #endif 04083 #ifdef HAVE_AES 04084 if (ISTRANSFORM(user->privProtocol, AESPriv)) { 04085 expected_privKeyLen = 16; 04086 } 04087 #endif 04088 /* For backwards compatibility */ 04089 if (user->privKeyLen > expected_privKeyLen) { 04090 user->privKeyLen = expected_privKeyLen; 04091 } 04092 04093 line = read_config_read_octet_string(line, &user->userPublicString, 04094 &user->userPublicStringLen); 04095 return user; 04096 } 04097 04098 /* 04099 * snmpd.conf parsing routines 04100 */ 04101 void 04102 usm_parse_config_usmUser(const char *token, char *line) 04103 { 04104 struct usmUser *uptr; 04105 04106 uptr = usm_read_user(line); 04107 if ( uptr) 04108 usm_add_user(uptr); 04109 } 04110 04111 04112 04113 04114 /*******************************************************************-o-****** 04115 * usm_set_password 04116 * 04117 * Parameters: 04118 * *token 04119 * *line 04120 * 04121 * 04122 * format: userSetAuthPass secname engineIDLen engineID pass 04123 * or: userSetPrivPass secname engineIDLen engineID pass 04124 * or: userSetAuthKey secname engineIDLen engineID KuLen Ku 04125 * or: userSetPrivKey secname engineIDLen engineID KuLen Ku 04126 * or: userSetAuthLocalKey secname engineIDLen engineID KulLen Kul 04127 * or: userSetPrivLocalKey secname engineIDLen engineID KulLen Kul 04128 * 04129 * type is: 1=passphrase; 2=Ku; 3=Kul. 04130 * 04131 * 04132 * ASSUMES Passwords are null-terminated printable strings. 04133 */ 04134 void 04135 usm_set_password(const char *token, char *line) 04136 { 04137 char *cp; 04138 char nameBuf[SNMP_MAXBUF]; 04139 u_char *engineID; 04140 size_t engineIDLen; 04141 struct usmUser *user; 04142 04143 cp = copy_nword(line, nameBuf, sizeof(nameBuf)); 04144 if (cp == NULL) { 04145 config_perror("invalid name specifier"); 04146 return; 04147 } 04148 04149 DEBUGMSGTL(("usm", "comparing: %s and %s\n", cp, WILDCARDSTRING)); 04150 if (strncmp(cp, WILDCARDSTRING, strlen(WILDCARDSTRING)) == 0) { 04151 /* 04152 * match against all engineIDs we know about 04153 */ 04154 cp = skip_token(cp); 04155 for (user = userList; user != NULL; user = user->next) { 04156 if (user->secName && strcmp(user->secName, nameBuf) == 0) { 04157 usm_set_user_password(user, token, cp); 04158 } 04159 } 04160 } else { 04161 cp = read_config_read_octet_string(cp, &engineID, &engineIDLen); 04162 if (cp == NULL) { 04163 config_perror("invalid engineID specifier"); 04164 return; 04165 } 04166 04167 user = usm_get_user(engineID, engineIDLen, nameBuf); 04168 if (user == NULL) { 04169 config_perror("not a valid user/engineID pair"); 04170 return; 04171 } 04172 usm_set_user_password(user, token, cp); 04173 } 04174 } 04175 04176 /* 04177 * uses the rest of LINE to configure USER's password of type TOKEN 04178 */ 04179 void 04180 usm_set_user_password(struct usmUser *user, const char *token, char *line) 04181 { 04182 char *cp = line; 04183 u_char *engineID = user->engineID; 04184 size_t engineIDLen = user->engineIDLen; 04185 04186 u_char **key; 04187 size_t *keyLen; 04188 u_char userKey[SNMP_MAXBUF_SMALL]; 04189 size_t userKeyLen = SNMP_MAXBUF_SMALL; 04190 u_char *userKeyP = userKey; 04191 int type, ret; 04192 04193 /* 04194 * Retrieve the "old" key and set the key type. 04195 */ 04196 if (!token) { 04197 return; 04198 } else if (strcmp(token, "userSetAuthPass") == 0) { 04199 key = &user->authKey; 04200 keyLen = &user->authKeyLen; 04201 type = 0; 04202 } else if (strcmp(token, "userSetPrivPass") == 0) { 04203 key = &user->privKey; 04204 keyLen = &user->privKeyLen; 04205 type = 0; 04206 } else if (strcmp(token, "userSetAuthKey") == 0) { 04207 key = &user->authKey; 04208 keyLen = &user->authKeyLen; 04209 type = 1; 04210 } else if (strcmp(token, "userSetPrivKey") == 0) { 04211 key = &user->privKey; 04212 keyLen = &user->privKeyLen; 04213 type = 1; 04214 } else if (strcmp(token, "userSetAuthLocalKey") == 0) { 04215 key = &user->authKey; 04216 keyLen = &user->authKeyLen; 04217 type = 2; 04218 } else if (strcmp(token, "userSetPrivLocalKey") == 0) { 04219 key = &user->privKey; 04220 keyLen = &user->privKeyLen; 04221 type = 2; 04222 } else { 04223 /* 04224 * no old key, or token was not recognized 04225 */ 04226 return; 04227 } 04228 04229 if (*key) { 04230 /* 04231 * (destroy and) free the old key 04232 */ 04233 memset(*key, 0, *keyLen); 04234 SNMP_FREE(*key); 04235 } 04236 04237 if (type == 0) { 04238 /* 04239 * convert the password into a key 04240 */ 04241 if (cp == NULL) { 04242 config_perror("missing user password"); 04243 return; 04244 } 04245 ret = generate_Ku(user->authProtocol, user->authProtocolLen, 04246 (u_char *) cp, strlen(cp), userKey, &userKeyLen); 04247 04248 if (ret != SNMPERR_SUCCESS) { 04249 config_perror("setting key failed (in sc_genKu())"); 04250 return; 04251 } 04252 } else if (type == 1) { 04253 cp = read_config_read_octet_string(cp, &userKeyP, &userKeyLen); 04254 04255 if (cp == NULL) { 04256 config_perror("invalid user key"); 04257 return; 04258 } 04259 } 04260 04261 if (type < 2) { 04262 *key = (u_char *) malloc(SNMP_MAXBUF_SMALL); 04263 *keyLen = SNMP_MAXBUF_SMALL; 04264 ret = generate_kul(user->authProtocol, user->authProtocolLen, 04265 engineID, engineIDLen, 04266 userKey, userKeyLen, *key, keyLen); 04267 if (ret != SNMPERR_SUCCESS) { 04268 config_perror("setting key failed (in generate_kul())"); 04269 return; 04270 } 04271 04272 /* 04273 * (destroy and) free the old key 04274 */ 04275 memset(userKey, 0, sizeof(userKey)); 04276 04277 } else { 04278 /* 04279 * the key is given, copy it in 04280 */ 04281 cp = read_config_read_octet_string(cp, key, keyLen); 04282 04283 if (cp == NULL) { 04284 config_perror("invalid localized user key"); 04285 return; 04286 } 04287 } 04288 } /* end usm_set_password() */ 04289 04290 void 04291 usm_parse_create_usmUser(const char *token, char *line) 04292 { 04293 char *cp; 04294 char buf[SNMP_MAXBUF_MEDIUM]; 04295 struct usmUser *newuser; 04296 u_char userKey[SNMP_MAXBUF_SMALL], *tmpp; 04297 size_t userKeyLen = SNMP_MAXBUF_SMALL; 04298 size_t privKeyLen = 0; 04299 size_t ret; 04300 int ret2; 04301 int testcase; 04302 04303 newuser = usm_create_user(); 04304 04305 /* 04306 * READ: Security Name 04307 */ 04308 cp = copy_nword(line, buf, sizeof(buf)); 04309 04310 /* 04311 * might be a -e ENGINEID argument 04312 */ 04313 if (strcmp(buf, "-e") == 0) { 04314 size_t ebuf_len = 32, eout_len = 0; 04315 u_char *ebuf = (u_char *) malloc(ebuf_len); 04316 04317 if (ebuf == NULL) { 04318 config_perror("malloc failure processing -e flag"); 04319 usm_free_user(newuser); 04320 return; 04321 } 04322 04323 /* 04324 * Get the specified engineid from the line. 04325 */ 04326 cp = copy_nword(cp, buf, sizeof(buf)); 04327 if (!snmp_hex_to_binary(&ebuf, &ebuf_len, &eout_len, 1, buf)) { 04328 config_perror("invalid EngineID argument to -e"); 04329 usm_free_user(newuser); 04330 SNMP_FREE(ebuf); 04331 return; 04332 } 04333 04334 newuser->engineID = ebuf; 04335 newuser->engineIDLen = eout_len; 04336 cp = copy_nword(cp, buf, sizeof(buf)); 04337 } else { 04338 newuser->engineID = snmpv3_generate_engineID(&ret); 04339 if (ret == 0) { 04340 usm_free_user(newuser); 04341 return; 04342 } 04343 newuser->engineIDLen = ret; 04344 } 04345 04346 newuser->secName = strdup(buf); 04347 newuser->name = strdup(buf); 04348 04349 if (!cp) 04350 goto add; /* no authentication or privacy type */ 04351 04352 /* 04353 * READ: Authentication Type 04354 */ 04355 #ifndef NETSNMP_DISABLE_MD5 04356 if (strncmp(cp, "MD5", 3) == 0) { 04357 memcpy(newuser->authProtocol, usmHMACMD5AuthProtocol, 04358 sizeof(usmHMACMD5AuthProtocol)); 04359 } else 04360 #endif 04361 if (strncmp(cp, "SHA", 3) == 0) { 04362 memcpy(newuser->authProtocol, usmHMACSHA1AuthProtocol, 04363 sizeof(usmHMACSHA1AuthProtocol)); 04364 } else { 04365 config_perror("Unknown authentication protocol"); 04366 usm_free_user(newuser); 04367 return; 04368 } 04369 04370 cp = skip_token(cp); 04371 04372 /* 04373 * READ: Authentication Pass Phrase or key 04374 */ 04375 if (!cp) { 04376 config_perror("no authentication pass phrase"); 04377 usm_free_user(newuser); 04378 return; 04379 } 04380 cp = copy_nword(cp, buf, sizeof(buf)); 04381 if (strcmp(buf,"-m") == 0) { 04382 /* a master key is specified */ 04383 cp = copy_nword(cp, buf, sizeof(buf)); 04384 ret = sizeof(userKey); 04385 tmpp = userKey; 04386 userKeyLen = 0; 04387 if (!snmp_hex_to_binary(&tmpp, &ret, &userKeyLen, 0, buf)) { 04388 config_perror("invalid key value argument to -m"); 04389 usm_free_user(newuser); 04390 return; 04391 } 04392 } else if (strcmp(buf,"-l") != 0) { 04393 /* a password is specified */ 04394 userKeyLen = sizeof(userKey); 04395 ret2 = generate_Ku(newuser->authProtocol, newuser->authProtocolLen, 04396 (u_char *) buf, strlen(buf), userKey, &userKeyLen); 04397 if (ret2 != SNMPERR_SUCCESS) { 04398 config_perror("could not generate the authentication key from the " 04399 "supplied pass phrase."); 04400 usm_free_user(newuser); 04401 return; 04402 } 04403 } 04404 04405 /* 04406 * And turn it into a localized key 04407 */ 04408 ret2 = sc_get_properlength(newuser->authProtocol, 04409 newuser->authProtocolLen); 04410 if (ret2 <= 0) { 04411 config_perror("Could not get proper authentication protocol key length"); 04412 usm_free_user(newuser); 04413 return; 04414 } 04415 newuser->authKey = (u_char *) malloc(ret2); 04416 04417 if (strcmp(buf,"-l") == 0) { 04418 /* a local key is directly specified */ 04419 cp = copy_nword(cp, buf, sizeof(buf)); 04420 newuser->authKeyLen = 0; 04421 ret = ret2; 04422 if (!snmp_hex_to_binary(&newuser->authKey, &ret, 04423 &newuser->authKeyLen, 0, buf)) { 04424 config_perror("invalid key value argument to -l"); 04425 usm_free_user(newuser); 04426 return; 04427 } 04428 if (ret != newuser->authKeyLen) { 04429 config_perror("improper key length to -l"); 04430 usm_free_user(newuser); 04431 return; 04432 } 04433 } else { 04434 newuser->authKeyLen = ret2; 04435 ret2 = generate_kul(newuser->authProtocol, newuser->authProtocolLen, 04436 newuser->engineID, newuser->engineIDLen, 04437 userKey, userKeyLen, 04438 newuser->authKey, &newuser->authKeyLen); 04439 if (ret2 != SNMPERR_SUCCESS) { 04440 config_perror("could not generate localized authentication key " 04441 "(Kul) from the master key (Ku)."); 04442 usm_free_user(newuser); 04443 return; 04444 } 04445 } 04446 04447 if (!cp) 04448 goto add; /* no privacy type (which is legal) */ 04449 04450 /* 04451 * READ: Privacy Type 04452 */ 04453 testcase = 0; 04454 #ifndef NETSNMP_DISABLE_DES 04455 if (strncmp(cp, "DES", 3) == 0) { 04456 memcpy(newuser->privProtocol, usmDESPrivProtocol, 04457 sizeof(usmDESPrivProtocol)); 04458 testcase = 1; 04459 /* DES uses a 128 bit key, 64 bits of which is a salt */ 04460 privKeyLen = 16; 04461 } 04462 #endif 04463 #ifdef HAVE_AES 04464 if (strncmp(cp, "AES128", 6) == 0 || 04465 strncmp(cp, "AES", 3) == 0) { 04466 memcpy(newuser->privProtocol, usmAESPrivProtocol, 04467 sizeof(usmAESPrivProtocol)); 04468 testcase = 1; 04469 privKeyLen = 16; 04470 } 04471 #endif 04472 if (testcase == 0) { 04473 config_perror("Unknown privacy protocol"); 04474 usm_free_user(newuser); 04475 return; 04476 } 04477 04478 cp = skip_token(cp); 04479 /* 04480 * READ: Encryption Pass Phrase or key 04481 */ 04482 if (!cp) { 04483 /* 04484 * assume the same as the authentication key 04485 */ 04486 memdup(&newuser->privKey, newuser->authKey, newuser->authKeyLen); 04487 newuser->privKeyLen = newuser->authKeyLen; 04488 } else { 04489 cp = copy_nword(cp, buf, sizeof(buf)); 04490 04491 if (strcmp(buf,"-m") == 0) { 04492 /* a master key is specified */ 04493 cp = copy_nword(cp, buf, sizeof(buf)); 04494 ret = sizeof(userKey); 04495 tmpp = userKey; 04496 userKeyLen = 0; 04497 if (!snmp_hex_to_binary(&tmpp, &ret, &userKeyLen, 0, buf)) { 04498 config_perror("invalid key value argument to -m"); 04499 usm_free_user(newuser); 04500 return; 04501 } 04502 } else if (strcmp(buf,"-l") != 0) { 04503 /* a password is specified */ 04504 userKeyLen = sizeof(userKey); 04505 ret2 = generate_Ku(newuser->authProtocol, newuser->authProtocolLen, 04506 (u_char *) buf, strlen(buf), userKey, &userKeyLen); 04507 if (ret2 != SNMPERR_SUCCESS) { 04508 config_perror("could not generate the privacy key from the " 04509 "supplied pass phrase."); 04510 usm_free_user(newuser); 04511 return; 04512 } 04513 } 04514 04515 /* 04516 * And turn it into a localized key 04517 */ 04518 ret2 = sc_get_properlength(newuser->authProtocol, 04519 newuser->authProtocolLen); 04520 if (ret2 < 0) { 04521 config_perror("could not get proper key length to use for the " 04522 "privacy algorithm."); 04523 usm_free_user(newuser); 04524 return; 04525 } 04526 newuser->privKey = (u_char *) malloc(ret2); 04527 04528 if (strcmp(buf,"-l") == 0) { 04529 /* a local key is directly specified */ 04530 cp = copy_nword(cp, buf, sizeof(buf)); 04531 ret = ret2; 04532 newuser->privKeyLen = 0; 04533 if (!snmp_hex_to_binary(&newuser->privKey, &ret, 04534 &newuser->privKeyLen, 0, buf)) { 04535 config_perror("invalid key value argument to -l"); 04536 usm_free_user(newuser); 04537 return; 04538 } 04539 } else { 04540 newuser->privKeyLen = ret2; 04541 ret2 = generate_kul(newuser->authProtocol, newuser->authProtocolLen, 04542 newuser->engineID, newuser->engineIDLen, 04543 userKey, userKeyLen, 04544 newuser->privKey, &newuser->privKeyLen); 04545 if (ret2 != SNMPERR_SUCCESS) { 04546 config_perror("could not generate localized privacy key " 04547 "(Kul) from the master key (Ku)."); 04548 usm_free_user(newuser); 04549 return; 04550 } 04551 } 04552 } 04553 04554 if ((newuser->privKeyLen >= privKeyLen) || (privKeyLen == 0)){ 04555 newuser->privKeyLen = privKeyLen; 04556 } 04557 else { 04558 /* The privKey length is smaller than required by privProtocol */ 04559 usm_free_user(newuser); 04560 return; 04561 } 04562 04563 add: 04564 usm_add_user(newuser); 04565 DEBUGMSGTL(("usmUser", "created a new user %s at ", newuser->secName)); 04566 DEBUGMSGHEX(("usmUser", newuser->engineID, newuser->engineIDLen)); 04567 DEBUGMSG(("usmUser", "\n")); 04568 } 04569 04570 void 04571 snmpv3_authtype_conf(const char *word, char *cptr) 04572 { 04573 #ifndef NETSNMP_DISABLE_MD5 04574 if (strcasecmp(cptr, "MD5") == 0) 04575 defaultAuthType = usmHMACMD5AuthProtocol; 04576 else 04577 #endif 04578 if (strcasecmp(cptr, "SHA") == 0) 04579 defaultAuthType = usmHMACSHA1AuthProtocol; 04580 else 04581 config_perror("Unknown authentication type"); 04582 defaultAuthTypeLen = USM_LENGTH_OID_TRANSFORM; 04583 DEBUGMSGTL(("snmpv3", "set default authentication type: %s\n", cptr)); 04584 } 04585 04586 const oid * 04587 get_default_authtype(size_t * len) 04588 { 04589 if (defaultAuthType == NULL) { 04590 defaultAuthType = SNMP_DEFAULT_AUTH_PROTO; 04591 defaultAuthTypeLen = SNMP_DEFAULT_AUTH_PROTOLEN; 04592 } 04593 if (len) 04594 *len = defaultAuthTypeLen; 04595 return defaultAuthType; 04596 } 04597 04598 void 04599 snmpv3_privtype_conf(const char *word, char *cptr) 04600 { 04601 int testcase = 0; 04602 04603 #ifndef NETSNMP_DISABLE_DES 04604 if (strcasecmp(cptr, "DES") == 0) { 04605 testcase = 1; 04606 defaultPrivType = usmDESPrivProtocol; 04607 } 04608 #endif 04609 04610 #if HAVE_AES 04611 /* XXX AES: assumes oid length == des oid length */ 04612 if (strcasecmp(cptr, "AES128") == 0 || 04613 strcasecmp(cptr, "AES") == 0) { 04614 testcase = 1; 04615 defaultPrivType = usmAES128PrivProtocol; 04616 } 04617 #endif 04618 if (testcase == 0) 04619 config_perror("Unknown privacy type"); 04620 defaultPrivTypeLen = SNMP_DEFAULT_PRIV_PROTOLEN; 04621 DEBUGMSGTL(("snmpv3", "set default privacy type: %s\n", cptr)); 04622 } 04623 04624 const oid * 04625 get_default_privtype(size_t * len) 04626 { 04627 if (defaultPrivType == NULL) { 04628 #ifndef NETSNMP_DISABLE_DES 04629 defaultPrivType = usmDESPrivProtocol; 04630 #else 04631 defaultPrivType = usmAESPrivProtocol; 04632 #endif 04633 defaultPrivTypeLen = USM_LENGTH_OID_TRANSFORM; 04634 } 04635 if (len) 04636 *len = defaultPrivTypeLen; 04637 return defaultPrivType; 04638 } 04639