00001 /* 00002 * snmpv3.c 00003 */ 00004 00005 #include <net-snmp/net-snmp-config.h> 00006 #include <errno.h> 00007 #ifdef HAVE_LIMITS_H 00008 #include <limits.h> 00009 #endif 00010 #include <stdio.h> 00011 #include <sys/types.h> 00012 00013 #if TIME_WITH_SYS_TIME 00014 # ifdef WIN32 00015 # include <sys/timeb.h> 00016 # else 00017 # include <sys/time.h> 00018 # endif 00019 # include <time.h> 00020 #else 00021 # if HAVE_SYS_TIME_H 00022 # include <sys/time.h> 00023 # else 00024 # include <time.h> 00025 # endif 00026 #endif 00027 #if HAVE_SYS_TIMES_H 00028 #include <sys/times.h> 00029 #endif 00030 #if HAVE_STRING_H 00031 #include <string.h> 00032 #else 00033 #include <strings.h> 00034 #endif 00035 #include <ctype.h> 00036 #if HAVE_NETINET_IN_H 00037 #include <netinet/in.h> 00038 #endif 00039 #if HAVE_UNISTD_H 00040 #include <unistd.h> 00041 #endif 00042 #if HAVE_WINSOCK_H 00043 #include <winsock.h> 00044 #endif 00045 #if HAVE_SYS_SOCKET_H 00046 #include <sys/socket.h> 00047 #endif 00048 #if HAVE_NETDB_H 00049 #include <netdb.h> 00050 #endif 00051 #if HAVE_STDLIB_H 00052 # include <stdlib.h> 00053 #endif 00054 00055 /* 00056 * Stuff needed for getHwAddress(...) 00057 */ 00058 #ifdef HAVE_SYS_IOCTL_H 00059 # include <sys/ioctl.h> 00060 #endif 00061 #ifdef HAVE_NET_IF_H 00062 # include <net/if.h> 00063 #endif 00064 00065 #if HAVE_DMALLOC_H 00066 #include <dmalloc.h> 00067 #endif 00068 00069 #include <net-snmp/types.h> 00070 #include <net-snmp/output_api.h> 00071 #include <net-snmp/config_api.h> 00072 #include <net-snmp/utilities.h> 00073 00074 #include <net-snmp/library/snmpv3.h> 00075 #include <net-snmp/library/callback.h> 00076 #include <net-snmp/library/snmp_api.h> 00077 #include <net-snmp/library/lcd_time.h> 00078 #include <net-snmp/library/scapi.h> 00079 #include <net-snmp/library/keytools.h> 00080 #include <net-snmp/library/lcd_time.h> 00081 #include <net-snmp/library/snmp_secmod.h> 00082 #include <net-snmp/library/snmpusm.h> 00083 #include <net-snmp/library/transform_oids.h> 00084 00085 static u_long engineBoots = 1; 00086 static unsigned int engineIDType = ENGINEID_TYPE_NETSNMP_RND; 00087 static unsigned char *engineID = NULL; 00088 static size_t engineIDLength = 0; 00089 static unsigned char *engineIDNic = NULL; 00090 static unsigned int engineIDIsSet = 0; /* flag if ID set by config */ 00091 static unsigned char *oldEngineID = NULL; 00092 static size_t oldEngineIDLength = 0; 00093 static struct timeval snmpv3starttime; 00094 00095 /* 00096 * Set up default snmpv3 parameter value storage. 00097 */ 00098 static const oid *defaultAuthType = NULL; 00099 static size_t defaultAuthTypeLen = 0; 00100 static const oid *defaultPrivType = NULL; 00101 static size_t defaultPrivTypeLen = 0; 00102 00103 /* this is probably an over-kill ifdef, but why not */ 00104 #if defined(HAVE_SYS_TIMES_H) && defined(HAVE_UNISTD_H) && defined(HAVE_TIMES) && defined(_SC_CLK_TCK) && defined(HAVE_SYSCONF) && defined(UINT_MAX) 00105 00106 #define SNMP_USE_TIMES 1 00107 00108 static clock_t snmpv3startClock; 00109 static long clockticks = 0; 00110 static unsigned int lastcalltime = 0; 00111 static unsigned int wrapcounter = 0; 00112 00113 #endif /* times() tests */ 00114 00115 #if defined(IFHWADDRLEN) && defined(SIOCGIFHWADDR) 00116 static int getHwAddress(const char *networkDevice, char *addressOut); 00117 #endif 00118 00119 void 00120 snmpv3_authtype_conf(const char *word, char *cptr) 00121 { 00122 #ifndef NETSNMP_DISABLE_MD5 00123 if (strcasecmp(cptr, "MD5") == 0) 00124 defaultAuthType = usmHMACMD5AuthProtocol; 00125 else 00126 #endif 00127 if (strcasecmp(cptr, "SHA") == 0) 00128 defaultAuthType = usmHMACSHA1AuthProtocol; 00129 else 00130 config_perror("Unknown authentication type"); 00131 defaultAuthTypeLen = USM_LENGTH_OID_TRANSFORM; 00132 DEBUGMSGTL(("snmpv3", "set default authentication type: %s\n", cptr)); 00133 } 00134 00135 const oid * 00136 get_default_authtype(size_t * len) 00137 { 00138 if (defaultAuthType == NULL) { 00139 defaultAuthType = SNMP_DEFAULT_AUTH_PROTO; 00140 defaultAuthTypeLen = SNMP_DEFAULT_AUTH_PROTOLEN; 00141 } 00142 if (len) 00143 *len = defaultAuthTypeLen; 00144 return defaultAuthType; 00145 } 00146 00147 void 00148 snmpv3_privtype_conf(const char *word, char *cptr) 00149 { 00150 int testcase = 0; 00151 00152 #ifndef NETSNMP_DISABLE_DES 00153 if (strcasecmp(cptr, "DES") == 0) { 00154 testcase = 1; 00155 defaultPrivType = usmDESPrivProtocol; 00156 } 00157 #endif 00158 00159 #if HAVE_AES 00160 /* XXX AES: assumes oid length == des oid length */ 00161 if (strcasecmp(cptr, "AES128") == 0 || 00162 strcasecmp(cptr, "AES") == 0) { 00163 testcase = 1; 00164 defaultPrivType = usmAES128PrivProtocol; 00165 } 00166 #endif 00167 if (testcase == 0) 00168 config_perror("Unknown privacy type"); 00169 defaultPrivTypeLen = SNMP_DEFAULT_PRIV_PROTOLEN; 00170 DEBUGMSGTL(("snmpv3", "set default privacy type: %s\n", cptr)); 00171 } 00172 00173 const oid * 00174 get_default_privtype(size_t * len) 00175 { 00176 if (defaultPrivType == NULL) { 00177 #ifndef NETSNMP_DISABLE_DES 00178 defaultPrivType = usmDESPrivProtocol; 00179 #else 00180 defaultPrivType = usmAESPrivProtocol; 00181 #endif 00182 defaultPrivTypeLen = USM_LENGTH_OID_TRANSFORM; 00183 } 00184 if (len) 00185 *len = defaultPrivTypeLen; 00186 return defaultPrivType; 00187 } 00188 00189 /*******************************************************************-o-****** 00190 * snmpv3_secLevel_conf 00191 * 00192 * Parameters: 00193 * *word 00194 * *cptr 00195 * 00196 * Line syntax: 00197 * defSecurityLevel "noAuthNoPriv" | "authNoPriv" | "authPriv" 00198 */ 00199 00200 int 00201 parse_secLevel_conf(const char *word, char *cptr) { 00202 if (strcasecmp(cptr, "noAuthNoPriv") == 0 || strcmp(cptr, "1") == 0 || 00203 strcasecmp(cptr, "nanp") == 0) { 00204 return SNMP_SEC_LEVEL_NOAUTH; 00205 } else if (strcasecmp(cptr, "authNoPriv") == 0 || strcmp(cptr, "2") == 0 || 00206 strcasecmp(cptr, "anp") == 0) { 00207 return SNMP_SEC_LEVEL_AUTHNOPRIV; 00208 } else if (strcasecmp(cptr, "authPriv") == 0 || strcmp(cptr, "3") == 0 || 00209 strcasecmp(cptr, "ap") == 0) { 00210 return SNMP_SEC_LEVEL_AUTHPRIV; 00211 } else { 00212 return -1; 00213 } 00214 } 00215 00216 void 00217 snmpv3_secLevel_conf(const char *word, char *cptr) 00218 { 00219 int secLevel; 00220 00221 if ((secLevel = parse_secLevel_conf( word, cptr )) >= 0 ) { 00222 netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, 00223 NETSNMP_DS_LIB_SECLEVEL, secLevel); 00224 } else { 00225 netsnmp_config_error("Unknown security level: %s", cptr); 00226 } 00227 DEBUGMSGTL(("snmpv3", "default secLevel set to: %s = %d\n", cptr, 00228 netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 00229 NETSNMP_DS_LIB_SECLEVEL))); 00230 } 00231 00232 00233 int 00234 snmpv3_options(char *optarg, netsnmp_session * session, char **Apsz, 00235 char **Xpsz, int argc, char *const *argv) 00236 { 00237 char *cp = optarg; 00238 int testcase; 00239 optarg++; 00240 /* 00241 * Support '... -3x=value ....' syntax 00242 */ 00243 if (*optarg == '=') { 00244 optarg++; 00245 } 00246 /* 00247 * and '.... "-3x value" ....' (*with* the quotes) 00248 */ 00249 while (*optarg && isspace(*optarg)) { 00250 optarg++; 00251 } 00252 /* 00253 * Finally, handle ".... -3x value ...." syntax 00254 * (*without* surrounding quotes) 00255 */ 00256 if (!*optarg) { 00257 /* 00258 * We've run off the end of the argument 00259 * so move on the the next. 00260 */ 00261 optarg = argv[optind++]; 00262 if (optind > argc) { 00263 fprintf(stderr, 00264 "Missing argument after SNMPv3 '-3%c' option.\n", *cp); 00265 return (-1); 00266 } 00267 } 00268 00269 switch (*cp) { 00270 00271 case 'Z': 00272 errno=0; 00273 session->engineBoots = strtoul(optarg, &cp, 10); 00274 if (errno || cp == optarg) { 00275 fprintf(stderr, "Need engine boots value after -3Z flag.\n"); 00276 return (-1); 00277 } 00278 if (*cp == ',') { 00279 char *endptr; 00280 cp++; 00281 session->engineTime = strtoul(cp, &endptr, 10); 00282 if (errno || cp == endptr) { 00283 fprintf(stderr, "Need engine time after \"-3Z engineBoot,\".\n"); 00284 return (-1); 00285 } 00286 } else { 00287 fprintf(stderr, "Need engine time after \"-3Z engineBoot,\".\n"); 00288 return (-1); 00289 } 00290 break; 00291 00292 case 'e':{ 00293 size_t ebuf_len = 32, eout_len = 0; 00294 u_char *ebuf = (u_char *) malloc(ebuf_len); 00295 00296 if (ebuf == NULL) { 00297 fprintf(stderr, "malloc failure processing -3e flag.\n"); 00298 return (-1); 00299 } 00300 if (!snmp_hex_to_binary 00301 (&ebuf, &ebuf_len, &eout_len, 1, optarg)) { 00302 fprintf(stderr, "Bad engine ID value after -3e flag.\n"); 00303 SNMP_FREE(ebuf); 00304 return (-1); 00305 } 00306 session->securityEngineID = ebuf; 00307 session->securityEngineIDLen = eout_len; 00308 break; 00309 } 00310 00311 case 'E':{ 00312 size_t ebuf_len = 32, eout_len = 0; 00313 u_char *ebuf = (u_char *) malloc(ebuf_len); 00314 00315 if (ebuf == NULL) { 00316 fprintf(stderr, "malloc failure processing -3E flag.\n"); 00317 return (-1); 00318 } 00319 if (!snmp_hex_to_binary 00320 (&ebuf, &ebuf_len, &eout_len, 1, optarg)) { 00321 fprintf(stderr, "Bad engine ID value after -3E flag.\n"); 00322 SNMP_FREE(ebuf); 00323 return (-1); 00324 } 00325 session->contextEngineID = ebuf; 00326 session->contextEngineIDLen = eout_len; 00327 break; 00328 } 00329 00330 case 'n': 00331 session->contextName = optarg; 00332 session->contextNameLen = strlen(optarg); 00333 break; 00334 00335 case 'u': 00336 session->securityName = optarg; 00337 session->securityNameLen = strlen(optarg); 00338 break; 00339 00340 case 'l': 00341 if (!strcasecmp(optarg, "noAuthNoPriv") || !strcmp(optarg, "1") || 00342 !strcasecmp(optarg, "nanp")) { 00343 session->securityLevel = SNMP_SEC_LEVEL_NOAUTH; 00344 } else if (!strcasecmp(optarg, "authNoPriv") 00345 || !strcmp(optarg, "2") || !strcasecmp(optarg, "anp")) { 00346 session->securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV; 00347 } else if (!strcasecmp(optarg, "authPriv") || !strcmp(optarg, "3") 00348 || !strcasecmp(optarg, "ap")) { 00349 session->securityLevel = SNMP_SEC_LEVEL_AUTHPRIV; 00350 } else { 00351 fprintf(stderr, 00352 "Invalid security level specified after -3l flag: %s\n", 00353 optarg); 00354 return (-1); 00355 } 00356 00357 break; 00358 00359 case 'a': 00360 #ifndef NETSNMP_DISABLE_MD5 00361 if (!strcasecmp(optarg, "MD5")) { 00362 session->securityAuthProto = usmHMACMD5AuthProtocol; 00363 session->securityAuthProtoLen = USM_AUTH_PROTO_MD5_LEN; 00364 } else 00365 #endif 00366 if (!strcasecmp(optarg, "SHA")) { 00367 session->securityAuthProto = usmHMACSHA1AuthProtocol; 00368 session->securityAuthProtoLen = USM_AUTH_PROTO_SHA_LEN; 00369 } else { 00370 fprintf(stderr, 00371 "Invalid authentication protocol specified after -3a flag: %s\n", 00372 optarg); 00373 return (-1); 00374 } 00375 break; 00376 00377 case 'x': 00378 testcase = 0; 00379 #ifndef NETSNMP_DISABLE_DES 00380 if (!strcasecmp(optarg, "DES")) { 00381 session->securityPrivProto = usmDESPrivProtocol; 00382 session->securityPrivProtoLen = USM_PRIV_PROTO_DES_LEN; 00383 testcase = 1; 00384 } 00385 #endif 00386 #ifdef HAVE_AES 00387 if (!strcasecmp(optarg, "AES128") || 00388 strcasecmp(optarg, "AES")) { 00389 session->securityPrivProto = usmAES128PrivProtocol; 00390 session->securityPrivProtoLen = USM_PRIV_PROTO_AES128_LEN; 00391 testcase = 1; 00392 } 00393 #endif 00394 if (testcase == 0) { 00395 fprintf(stderr, 00396 "Invalid privacy protocol specified after -3x flag: %s\n", 00397 optarg); 00398 return (-1); 00399 } 00400 break; 00401 00402 case 'A': 00403 *Apsz = optarg; 00404 break; 00405 00406 case 'X': 00407 *Xpsz = optarg; 00408 break; 00409 00410 case 'm': { 00411 size_t bufSize = sizeof(session->securityAuthKey); 00412 u_char *tmpp = session->securityAuthKey; 00413 if (!snmp_hex_to_binary(&tmpp, &bufSize, 00414 &session->securityAuthKeyLen, 0, optarg)) { 00415 fprintf(stderr, "Bad key value after -3m flag.\n"); 00416 return (-1); 00417 } 00418 break; 00419 } 00420 00421 case 'M': { 00422 size_t bufSize = sizeof(session->securityPrivKey); 00423 u_char *tmpp = session->securityPrivKey; 00424 if (!snmp_hex_to_binary(&tmpp, &bufSize, 00425 &session->securityPrivKeyLen, 0, optarg)) { 00426 fprintf(stderr, "Bad key value after -3M flag.\n"); 00427 return (-1); 00428 } 00429 break; 00430 } 00431 00432 case 'k': { 00433 size_t kbuf_len = 32, kout_len = 0; 00434 u_char *kbuf = (u_char *) malloc(kbuf_len); 00435 00436 if (kbuf == NULL) { 00437 fprintf(stderr, "malloc failure processing -3k flag.\n"); 00438 return (-1); 00439 } 00440 if (!snmp_hex_to_binary 00441 (&kbuf, &kbuf_len, &kout_len, 1, optarg)) { 00442 fprintf(stderr, "Bad key value after -3k flag.\n"); 00443 SNMP_FREE(kbuf); 00444 return (-1); 00445 } 00446 session->securityAuthLocalKey = kbuf; 00447 session->securityAuthLocalKeyLen = kout_len; 00448 break; 00449 } 00450 00451 case 'K': { 00452 size_t kbuf_len = 32, kout_len = 0; 00453 u_char *kbuf = (u_char *) malloc(kbuf_len); 00454 00455 if (kbuf == NULL) { 00456 fprintf(stderr, "malloc failure processing -3K flag.\n"); 00457 return (-1); 00458 } 00459 if (!snmp_hex_to_binary 00460 (&kbuf, &kbuf_len, &kout_len, 1, optarg)) { 00461 fprintf(stderr, "Bad key value after -3K flag.\n"); 00462 SNMP_FREE(kbuf); 00463 return (-1); 00464 } 00465 session->securityPrivLocalKey = kbuf; 00466 session->securityPrivLocalKeyLen = kout_len; 00467 break; 00468 } 00469 00470 default: 00471 fprintf(stderr, "Unknown SNMPv3 option passed to -3: %c.\n", *cp); 00472 return -1; 00473 } 00474 return 0; 00475 } 00476 00477 /*******************************************************************-o-****** 00478 * setup_engineID 00479 * 00480 * Parameters: 00481 * **eidp 00482 * *text Printable (?) text to be plugged into the snmpEngineID. 00483 * 00484 * Return: 00485 * Length of allocated engineID string in bytes, -OR- 00486 * -1 on error. 00487 * 00488 * 00489 * Create an snmpEngineID using text and the local IP address. If eidp 00490 * is defined, use it to return a pointer to the newly allocated data. 00491 * Otherwise, use the result to define engineID defined in this module. 00492 * 00493 * Line syntax: 00494 * engineID <text> | NULL 00495 * 00496 * XXX What if a node has multiple interfaces? 00497 * XXX What if multiple engines all choose the same address? 00498 * (answer: You're screwed, because you might need a kul database 00499 * which is dependant on the current engineID. Enumeration and other 00500 * tricks won't work). 00501 */ 00502 int 00503 setup_engineID(u_char ** eidp, const char *text) 00504 { 00505 int enterpriseid = htonl(NETSNMP_ENTERPRISE_OID), 00506 netsnmpoid = htonl(NETSNMP_OID), 00507 localsetup = (eidp) ? 0 : 1; 00508 00509 /* 00510 * Use local engineID if *eidp == NULL. 00511 */ 00512 #ifdef HAVE_GETHOSTNAME 00513 u_char buf[SNMP_MAXBUF_SMALL]; 00514 struct hostent *hent = NULL; 00515 #endif 00516 u_char *bufp = NULL; 00517 size_t len; 00518 int localEngineIDType = engineIDType; 00519 int tmpint; 00520 time_t tmptime; 00521 00522 engineIDIsSet = 1; 00523 00524 #ifdef HAVE_GETHOSTNAME 00525 #ifdef AF_INET6 00526 /* 00527 * see if they selected IPV4 or IPV6 support 00528 */ 00529 if ((ENGINEID_TYPE_IPV6 == localEngineIDType) || 00530 (ENGINEID_TYPE_IPV4 == localEngineIDType)) { 00531 /* 00532 * get the host name and save the information 00533 */ 00534 gethostname((char *) buf, sizeof(buf)); 00535 hent = gethostbyname((char *) buf); 00536 if (hent && hent->h_addrtype == AF_INET6) { 00537 localEngineIDType = ENGINEID_TYPE_IPV6; 00538 } else { 00539 /* 00540 * Not IPV6 so we go with default 00541 */ 00542 localEngineIDType = ENGINEID_TYPE_IPV4; 00543 } 00544 } 00545 #else 00546 /* 00547 * No IPV6 support. Check if they selected IPV6 engineID type. 00548 * If so make it IPV4 instead 00549 */ 00550 if (ENGINEID_TYPE_IPV6 == localEngineIDType) { 00551 localEngineIDType = ENGINEID_TYPE_IPV4; 00552 } 00553 if (ENGINEID_TYPE_IPV4 == localEngineIDType) { 00554 /* 00555 * get the host name and save the information 00556 */ 00557 gethostname((char *) buf, sizeof(buf)); 00558 hent = gethostbyname((char *) buf); 00559 } 00560 #endif 00561 #endif /* HAVE_GETHOSTNAME */ 00562 00563 /* 00564 * Determine if we have text and if so setup our localEngineIDType 00565 * * appropriately. 00566 */ 00567 if (NULL != text) { 00568 engineIDType = localEngineIDType = ENGINEID_TYPE_TEXT; 00569 } 00570 /* 00571 * Determine length of the engineID string. 00572 */ 00573 len = 5; /* always have 5 leading bytes */ 00574 switch (localEngineIDType) { 00575 case ENGINEID_TYPE_TEXT: 00576 if (NULL == text) { 00577 snmp_log(LOG_ERR, 00578 "Can't set up engineID of type text from an empty string.\n"); 00579 return -1; 00580 } 00581 len += strlen(text); /* 5 leading bytes+text. No NULL char */ 00582 break; 00583 #if defined(IFHWADDRLEN) && defined(SIOCGIFHWADDR) 00584 case ENGINEID_TYPE_MACADDR: /* MAC address */ 00585 len += 6; /* + 6 bytes for MAC address */ 00586 break; 00587 #endif 00588 case ENGINEID_TYPE_IPV4: /* IPv4 */ 00589 len += 4; /* + 4 byte IPV4 address */ 00590 break; 00591 case ENGINEID_TYPE_IPV6: /* IPv6 */ 00592 len += 16; /* + 16 byte IPV6 address */ 00593 break; 00594 case ENGINEID_TYPE_NETSNMP_RND: /* Net-SNMP specific encoding */ 00595 if (engineID) /* already setup, keep current value */ 00596 return engineIDLength; 00597 if (oldEngineID) { 00598 len = oldEngineIDLength; 00599 } else { 00600 len += sizeof(int) + sizeof(time_t); 00601 } 00602 break; 00603 default: 00604 snmp_log(LOG_ERR, 00605 "Unknown EngineID type requested for setup (%d). Using IPv4.\n", 00606 localEngineIDType); 00607 localEngineIDType = ENGINEID_TYPE_IPV4; /* make into IPV4 */ 00608 len += 4; /* + 4 byte IPv4 address */ 00609 break; 00610 } /* switch */ 00611 00612 00613 /* 00614 * Allocate memory and store enterprise ID. 00615 */ 00616 if ((bufp = (u_char *) malloc(len)) == NULL) { 00617 snmp_log_perror("setup_engineID malloc"); 00618 return -1; 00619 } 00620 if (localEngineIDType == ENGINEID_TYPE_NETSNMP_RND) 00621 /* 00622 * we must use the net-snmp enterprise id here, regardless 00623 */ 00624 memcpy(bufp, &netsnmpoid, sizeof(netsnmpoid)); /* XXX Must be 4 bytes! */ 00625 else 00626 memcpy(bufp, &enterpriseid, sizeof(enterpriseid)); /* XXX Must be 4 bytes! */ 00627 00628 bufp[0] |= 0x80; 00629 00630 00631 /* 00632 * Store the given text -OR- the first found IP address 00633 * -OR- the MAC address -OR- random elements 00634 * (the latter being the recommended default) 00635 */ 00636 switch (localEngineIDType) { 00637 case ENGINEID_TYPE_NETSNMP_RND: 00638 if (oldEngineID) { 00639 /* 00640 * keep our previous notion of the engineID 00641 */ 00642 memcpy(bufp, oldEngineID, oldEngineIDLength); 00643 } else { 00644 /* 00645 * Here we've desigend our own ENGINEID that is not based on 00646 * an address which may change and may even become conflicting 00647 * in the future like most of the default v3 engineID types 00648 * suffer from. 00649 * 00650 * Ours is built from 2 fairly random elements: a random number and 00651 * the current time in seconds. This method suffers from boxes 00652 * that may not have a correct clock setting and random number 00653 * seed at startup, but few OSes should have that problem. 00654 */ 00655 bufp[4] = ENGINEID_TYPE_NETSNMP_RND; 00656 tmpint = random(); 00657 memcpy(bufp + 5, &tmpint, sizeof(tmpint)); 00658 tmptime = time(NULL); 00659 memcpy(bufp + 5 + sizeof(tmpint), &tmptime, sizeof(tmptime)); 00660 } 00661 break; 00662 case ENGINEID_TYPE_TEXT: 00663 bufp[4] = ENGINEID_TYPE_TEXT; 00664 memcpy((char *) bufp + 5, (text), strlen(text)); 00665 break; 00666 #ifdef HAVE_GETHOSTNAME 00667 #ifdef AF_INET6 00668 case ENGINEID_TYPE_IPV6: 00669 bufp[4] = ENGINEID_TYPE_IPV6; 00670 memcpy(bufp + 5, hent->h_addr_list[0], hent->h_length); 00671 break; 00672 #endif 00673 #endif 00674 #if defined(IFHWADDRLEN) && defined(SIOCGIFHWADDR) 00675 case ENGINEID_TYPE_MACADDR: 00676 { 00677 int x; 00678 bufp[4] = ENGINEID_TYPE_MACADDR; 00679 /* 00680 * use default NIC if none provided 00681 */ 00682 if (NULL == engineIDNic) { 00683 x = getHwAddress(DEFAULT_NIC, (char *)&bufp[5]); 00684 } else { 00685 x = getHwAddress((char *)engineIDNic, (char *)&bufp[5]); 00686 } 00687 if (0 != x) 00688 /* 00689 * function failed fill MAC address with zeros 00690 */ 00691 { 00692 memset(&bufp[5], 0, 6); 00693 } 00694 } 00695 break; 00696 #endif 00697 case ENGINEID_TYPE_IPV4: 00698 default: 00699 bufp[4] = ENGINEID_TYPE_IPV4; 00700 #ifdef HAVE_GETHOSTNAME 00701 if (hent && hent->h_addrtype == AF_INET) { 00702 memcpy(bufp + 5, hent->h_addr_list[0], hent->h_length); 00703 } else { /* Unknown address type. Default to 127.0.0.1. */ 00704 00705 bufp[5] = 127; 00706 bufp[6] = 0; 00707 bufp[7] = 0; 00708 bufp[8] = 1; 00709 } 00710 #else /* HAVE_GETHOSTNAME */ 00711 /* 00712 * Unknown address type. Default to 127.0.0.1. 00713 */ 00714 bufp[5] = 127; 00715 bufp[6] = 0; 00716 bufp[7] = 0; 00717 bufp[8] = 1; 00718 #endif /* HAVE_GETHOSTNAME */ 00719 break; 00720 } 00721 00722 /* 00723 * Pass the string back to the calling environment, or use it for 00724 * our local engineID. 00725 */ 00726 if (localsetup) { 00727 SNMP_FREE(engineID); 00728 engineID = bufp; 00729 engineIDLength = len; 00730 00731 } else { 00732 *eidp = bufp; 00733 } 00734 00735 00736 return len; 00737 00738 } /* end setup_engineID() */ 00739 00740 int 00741 free_engineID(int majorid, int minorid, void *serverarg, 00742 void *clientarg) 00743 { 00744 SNMP_FREE(engineID); 00745 SNMP_FREE(engineIDNic); 00746 SNMP_FREE(oldEngineID); 00747 engineIDIsSet = 0; 00748 return 0; 00749 } 00750 00751 int 00752 free_enginetime_on_shutdown(int majorid, int minorid, void *serverarg, 00753 void *clientarg) 00754 { 00755 DEBUGMSGTL(("snmpv3", "free enginetime callback called\n")); 00756 if (engineID != NULL) 00757 free_enginetime(engineID, engineIDLength); 00758 return 0; 00759 } 00760 00761 void 00762 usm_parse_create_usmUser(const char *token, char *line) 00763 { 00764 char *cp; 00765 char buf[SNMP_MAXBUF_MEDIUM]; 00766 struct usmUser *newuser; 00767 u_char userKey[SNMP_MAXBUF_SMALL], *tmpp; 00768 size_t userKeyLen = SNMP_MAXBUF_SMALL; 00769 size_t privKeyLen = 0; 00770 size_t ret; 00771 int ret2; 00772 int testcase; 00773 00774 newuser = usm_create_user(); 00775 00776 /* 00777 * READ: Security Name 00778 */ 00779 cp = copy_nword(line, buf, sizeof(buf)); 00780 00781 /* 00782 * might be a -e ENGINEID argument 00783 */ 00784 if (strcmp(buf, "-e") == 0) { 00785 size_t ebuf_len = 32, eout_len = 0; 00786 u_char *ebuf = (u_char *) malloc(ebuf_len); 00787 00788 if (ebuf == NULL) { 00789 config_perror("malloc failure processing -e flag"); 00790 usm_free_user(newuser); 00791 return; 00792 } 00793 00794 /* 00795 * Get the specified engineid from the line. 00796 */ 00797 cp = copy_nword(cp, buf, sizeof(buf)); 00798 if (!snmp_hex_to_binary(&ebuf, &ebuf_len, &eout_len, 1, buf)) { 00799 config_perror("invalid EngineID argument to -e"); 00800 usm_free_user(newuser); 00801 SNMP_FREE(ebuf); 00802 return; 00803 } 00804 00805 newuser->engineID = ebuf; 00806 newuser->engineIDLen = eout_len; 00807 cp = copy_nword(cp, buf, sizeof(buf)); 00808 } else { 00809 newuser->engineID = snmpv3_generate_engineID(&ret); 00810 if (ret == 0) { 00811 usm_free_user(newuser); 00812 return; 00813 } 00814 newuser->engineIDLen = ret; 00815 } 00816 00817 newuser->secName = strdup(buf); 00818 newuser->name = strdup(buf); 00819 00820 if (!cp) 00821 goto add; /* no authentication or privacy type */ 00822 00823 /* 00824 * READ: Authentication Type 00825 */ 00826 #ifndef NETSNMP_DISABLE_MD5 00827 if (strncmp(cp, "MD5", 3) == 0) { 00828 memcpy(newuser->authProtocol, usmHMACMD5AuthProtocol, 00829 sizeof(usmHMACMD5AuthProtocol)); 00830 } else 00831 #endif 00832 if (strncmp(cp, "SHA", 3) == 0) { 00833 memcpy(newuser->authProtocol, usmHMACSHA1AuthProtocol, 00834 sizeof(usmHMACSHA1AuthProtocol)); 00835 } else { 00836 config_perror("Unknown authentication protocol"); 00837 usm_free_user(newuser); 00838 return; 00839 } 00840 00841 cp = skip_token(cp); 00842 00843 /* 00844 * READ: Authentication Pass Phrase or key 00845 */ 00846 if (!cp) { 00847 config_perror("no authentication pass phrase"); 00848 usm_free_user(newuser); 00849 return; 00850 } 00851 cp = copy_nword(cp, buf, sizeof(buf)); 00852 if (strcmp(buf,"-m") == 0) { 00853 /* a master key is specified */ 00854 cp = copy_nword(cp, buf, sizeof(buf)); 00855 ret = sizeof(userKey); 00856 tmpp = userKey; 00857 userKeyLen = 0; 00858 if (!snmp_hex_to_binary(&tmpp, &ret, &userKeyLen, 0, buf)) { 00859 config_perror("invalid key value argument to -m"); 00860 usm_free_user(newuser); 00861 return; 00862 } 00863 } else if (strcmp(buf,"-l") != 0) { 00864 /* a password is specified */ 00865 userKeyLen = sizeof(userKey); 00866 ret2 = generate_Ku(newuser->authProtocol, newuser->authProtocolLen, 00867 (u_char *) buf, strlen(buf), userKey, &userKeyLen); 00868 if (ret2 != SNMPERR_SUCCESS) { 00869 config_perror("could not generate the authentication key from the " 00870 "supplied pass phrase."); 00871 usm_free_user(newuser); 00872 return; 00873 } 00874 } 00875 00876 /* 00877 * And turn it into a localized key 00878 */ 00879 ret2 = sc_get_properlength(newuser->authProtocol, 00880 newuser->authProtocolLen); 00881 if (ret2 <= 0) { 00882 config_perror("Could not get proper authentication protocol key length"); 00883 usm_free_user(newuser); 00884 return; 00885 } 00886 newuser->authKey = (u_char *) malloc(ret2); 00887 00888 if (strcmp(buf,"-l") == 0) { 00889 /* a local key is directly specified */ 00890 cp = copy_nword(cp, buf, sizeof(buf)); 00891 newuser->authKeyLen = 0; 00892 ret = ret2; 00893 if (!snmp_hex_to_binary(&newuser->authKey, &ret, 00894 &newuser->authKeyLen, 0, buf)) { 00895 config_perror("invalid key value argument to -l"); 00896 usm_free_user(newuser); 00897 return; 00898 } 00899 if (ret != newuser->authKeyLen) { 00900 config_perror("improper key length to -l"); 00901 usm_free_user(newuser); 00902 return; 00903 } 00904 } else { 00905 newuser->authKeyLen = ret2; 00906 ret2 = generate_kul(newuser->authProtocol, newuser->authProtocolLen, 00907 newuser->engineID, newuser->engineIDLen, 00908 userKey, userKeyLen, 00909 newuser->authKey, &newuser->authKeyLen); 00910 if (ret2 != SNMPERR_SUCCESS) { 00911 config_perror("could not generate localized authentication key " 00912 "(Kul) from the master key (Ku)."); 00913 usm_free_user(newuser); 00914 return; 00915 } 00916 } 00917 00918 if (!cp) 00919 goto add; /* no privacy type (which is legal) */ 00920 00921 /* 00922 * READ: Privacy Type 00923 */ 00924 testcase = 0; 00925 #ifndef NETSNMP_DISABLE_DES 00926 if (strncmp(cp, "DES", 3) == 0) { 00927 memcpy(newuser->privProtocol, usmDESPrivProtocol, 00928 sizeof(usmDESPrivProtocol)); 00929 testcase = 1; 00930 /* DES uses a 128 bit key, 64 bits of which is a salt */ 00931 privKeyLen = 16; 00932 } 00933 #endif 00934 #ifdef HAVE_AES 00935 if (strncmp(cp, "AES128", 6) == 0 || 00936 strncmp(cp, "AES", 3) == 0) { 00937 memcpy(newuser->privProtocol, usmAESPrivProtocol, 00938 sizeof(usmAESPrivProtocol)); 00939 testcase = 1; 00940 privKeyLen = 16; 00941 } 00942 #endif 00943 if (testcase == 0) { 00944 config_perror("Unknown privacy protocol"); 00945 usm_free_user(newuser); 00946 return; 00947 } 00948 00949 cp = skip_token(cp); 00950 /* 00951 * READ: Encryption Pass Phrase or key 00952 */ 00953 if (!cp) { 00954 /* 00955 * assume the same as the authentication key 00956 */ 00957 memdup(&newuser->privKey, newuser->authKey, newuser->authKeyLen); 00958 newuser->privKeyLen = newuser->authKeyLen; 00959 } else { 00960 cp = copy_nword(cp, buf, sizeof(buf)); 00961 00962 if (strcmp(buf,"-m") == 0) { 00963 /* a master key is specified */ 00964 cp = copy_nword(cp, buf, sizeof(buf)); 00965 ret = sizeof(userKey); 00966 tmpp = userKey; 00967 userKeyLen = 0; 00968 if (!snmp_hex_to_binary(&tmpp, &ret, &userKeyLen, 0, buf)) { 00969 config_perror("invalid key value argument to -m"); 00970 usm_free_user(newuser); 00971 return; 00972 } 00973 } else if (strcmp(buf,"-l") != 0) { 00974 /* a password is specified */ 00975 userKeyLen = sizeof(userKey); 00976 ret2 = generate_Ku(newuser->authProtocol, newuser->authProtocolLen, 00977 (u_char *) buf, strlen(buf), userKey, &userKeyLen); 00978 if (ret2 != SNMPERR_SUCCESS) { 00979 config_perror("could not generate the privacy key from the " 00980 "supplied pass phrase."); 00981 usm_free_user(newuser); 00982 return; 00983 } 00984 } 00985 00986 /* 00987 * And turn it into a localized key 00988 */ 00989 ret2 = sc_get_properlength(newuser->authProtocol, 00990 newuser->authProtocolLen); 00991 if (ret2 < 0) { 00992 config_perror("could not get proper key length to use for the " 00993 "privacy algorithm."); 00994 usm_free_user(newuser); 00995 return; 00996 } 00997 newuser->privKey = (u_char *) malloc(ret2); 00998 00999 if (strcmp(buf,"-l") == 0) { 01000 /* a local key is directly specified */ 01001 cp = copy_nword(cp, buf, sizeof(buf)); 01002 ret = ret2; 01003 newuser->privKeyLen = 0; 01004 if (!snmp_hex_to_binary(&newuser->privKey, &ret, 01005 &newuser->privKeyLen, 0, buf)) { 01006 config_perror("invalid key value argument to -l"); 01007 usm_free_user(newuser); 01008 return; 01009 } 01010 } else { 01011 newuser->privKeyLen = ret2; 01012 ret2 = generate_kul(newuser->authProtocol, newuser->authProtocolLen, 01013 newuser->engineID, newuser->engineIDLen, 01014 userKey, userKeyLen, 01015 newuser->privKey, &newuser->privKeyLen); 01016 if (ret2 != SNMPERR_SUCCESS) { 01017 config_perror("could not generate localized privacy key " 01018 "(Kul) from the master key (Ku)."); 01019 usm_free_user(newuser); 01020 return; 01021 } 01022 } 01023 } 01024 01025 if ((newuser->privKeyLen >= privKeyLen) || (privKeyLen == 0)){ 01026 newuser->privKeyLen = privKeyLen; 01027 } 01028 else { 01029 /* The privKey length is smaller than required by privProtocol */ 01030 usm_free_user(newuser); 01031 return; 01032 } 01033 01034 add: 01035 usm_add_user(newuser); 01036 DEBUGMSGTL(("usmUser", "created a new user %s at ", newuser->secName)); 01037 DEBUGMSGHEX(("usmUser", newuser->engineID, newuser->engineIDLen)); 01038 DEBUGMSG(("usmUser", "\n")); 01039 } 01040 01041 /*******************************************************************-o-****** 01042 * engineBoots_conf 01043 * 01044 * Parameters: 01045 * *word 01046 * *cptr 01047 * 01048 * Line syntax: 01049 * engineBoots <num_boots> 01050 */ 01051 void 01052 engineBoots_conf(const char *word, char *cptr) 01053 { 01054 engineBoots = atoi(cptr) + 1; 01055 DEBUGMSGTL(("snmpv3", "engineBoots: %lu\n", engineBoots)); 01056 } 01057 01058 /*******************************************************************-o-****** 01059 * engineIDType_conf 01060 * 01061 * Parameters: 01062 * *word 01063 * *cptr 01064 * 01065 * Line syntax: 01066 * engineIDType <1 or 3> 01067 * 1 is default for IPv4 engine ID type. Will automatically 01068 * chose between IPv4 & IPv6 if either 1 or 2 is specified. 01069 * 2 is for IPv6. 01070 * 3 is hardware (MAC) address, currently supported under Linux 01071 */ 01072 void 01073 engineIDType_conf(const char *word, char *cptr) 01074 { 01075 engineIDType = atoi(cptr); 01076 /* 01077 * verify valid type selected 01078 */ 01079 switch (engineIDType) { 01080 case ENGINEID_TYPE_IPV4: /* IPv4 */ 01081 case ENGINEID_TYPE_IPV6: /* IPv6 */ 01082 /* 01083 * IPV? is always good 01084 */ 01085 break; 01086 #if defined(IFHWADDRLEN) && defined(SIOCGIFHWADDR) 01087 case ENGINEID_TYPE_MACADDR: /* MAC address */ 01088 break; 01089 #endif 01090 default: 01091 /* 01092 * unsupported one chosen 01093 */ 01094 config_perror("Unsupported enginedIDType, forcing IPv4"); 01095 engineIDType = ENGINEID_TYPE_IPV4; 01096 } 01097 DEBUGMSGTL(("snmpv3", "engineIDType: %d\n", engineIDType)); 01098 } 01099 01100 /*******************************************************************-o-****** 01101 * engineIDNic_conf 01102 * 01103 * Parameters: 01104 * *word 01105 * *cptr 01106 * 01107 * Line syntax: 01108 * engineIDNic <string> 01109 * eth0 is default 01110 */ 01111 void 01112 engineIDNic_conf(const char *word, char *cptr) 01113 { 01114 /* 01115 * Make sure they haven't already specified the engineID via the 01116 * * configuration file 01117 */ 01118 if (0 == engineIDIsSet) 01119 /* 01120 * engineID has NOT been set via configuration file 01121 */ 01122 { 01123 /* 01124 * See if already set if so erase & release it 01125 */ 01126 if (NULL != engineIDNic) { 01127 SNMP_FREE(engineIDNic); 01128 } 01129 engineIDNic = (u_char *) malloc(strlen(cptr) + 1); 01130 if (NULL != engineIDNic) { 01131 strcpy((char *) engineIDNic, cptr); 01132 DEBUGMSGTL(("snmpv3", "Initializing engineIDNic: %s\n", 01133 engineIDNic)); 01134 } else { 01135 DEBUGMSGTL(("snmpv3", 01136 "Error allocating memory for engineIDNic!\n")); 01137 } 01138 } else { 01139 DEBUGMSGTL(("snmpv3", 01140 "NOT setting engineIDNic, engineID already set\n")); 01141 } 01142 } 01143 01144 /*******************************************************************-o-****** 01145 * engineID_conf 01146 * 01147 * Parameters: 01148 * *word 01149 * *cptr 01150 * 01151 * This function reads a string from the configuration file and uses that 01152 * string to initialize the engineID. It's assumed to be human readable. 01153 */ 01154 void 01155 engineID_conf(const char *word, char *cptr) 01156 { 01157 setup_engineID(NULL, cptr); 01158 DEBUGMSGTL(("snmpv3", "initialized engineID with: %s\n", cptr)); 01159 } 01160 01161 void 01162 version_conf(const char *word, char *cptr) 01163 { 01164 int valid = 0; 01165 #ifndef NETSNMP_DISABLE_SNMPV1 01166 if ((strcmp(cptr, "1") == 0) || 01167 (strcmp(cptr, "v1") == 0)) { 01168 netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_SNMPVERSION, 01169 NETSNMP_DS_SNMP_VERSION_1); /* bogus value */ 01170 valid = 1; 01171 } 01172 #endif 01173 #ifndef NETSNMP_DISABLE_SNMPV2C 01174 if ((strcasecmp(cptr, "2c") == 0) || 01175 (strcasecmp(cptr, "v2c") == 0)) { 01176 netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_SNMPVERSION, 01177 NETSNMP_DS_SNMP_VERSION_2c); 01178 valid = 1; 01179 } 01180 #endif 01181 if ((strcasecmp(cptr, "3" ) == 0) || 01182 (strcasecmp(cptr, "v3" ) == 0)) { 01183 netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_SNMPVERSION, 01184 NETSNMP_DS_SNMP_VERSION_3); 01185 valid = 1; 01186 } 01187 if (!valid) { 01188 config_perror("Unknown version specification"); 01189 return; 01190 } 01191 DEBUGMSGTL(("snmpv3", "set default version to %d\n", 01192 netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 01193 NETSNMP_DS_LIB_SNMPVERSION))); 01194 } 01195 01196 /* 01197 * oldengineID_conf(const char *, char *): 01198 * 01199 * Reads a octet string encoded engineID into the oldEngineID and 01200 * oldEngineIDLen pointers. 01201 */ 01202 void 01203 oldengineID_conf(const char *word, char *cptr) 01204 { 01205 read_config_read_octet_string(cptr, &oldEngineID, &oldEngineIDLength); 01206 } 01207 01208 /* 01209 * exactEngineID_conf(const char *, char *): 01210 * 01211 * Reads a octet string encoded engineID into the engineID and 01212 * engineIDLen pointers. 01213 */ 01214 void 01215 exactEngineID_conf(const char *word, char *cptr) 01216 { 01217 read_config_read_octet_string(cptr, &engineID, &engineIDLength); 01218 if (engineIDLength > MAX_ENGINEID_LENGTH) { 01219 netsnmp_config_error( 01220 "exactEngineID '%s' too long; truncating to %d bytes", 01221 cptr, MAX_ENGINEID_LENGTH); 01222 engineID[MAX_ENGINEID_LENGTH - 1] = '\0'; 01223 engineIDLength = MAX_ENGINEID_LENGTH; 01224 } 01225 engineIDIsSet = 1; 01226 engineIDType = ENGINEID_TYPE_EXACT; 01227 } 01228 01229 01230 /* 01231 * merely call 01232 */ 01233 void 01234 get_enginetime_alarm(unsigned int regnum, void *clientargs) 01235 { 01236 /* we do this every so (rarely) often just to make sure we watch 01237 wrapping of the times() output */ 01238 snmpv3_local_snmpEngineTime(); 01239 } 01240 01241 /*******************************************************************-o-****** 01242 * init_snmpv3 01243 * 01244 * Parameters: 01245 * *type Label for the config file "type" used by calling entity. 01246 * 01247 * Set time and engineID. 01248 * Set parsing functions for config file tokens. 01249 * Initialize SNMP Crypto API (SCAPI). 01250 */ 01251 void 01252 init_snmpv3(const char *type) 01253 { 01254 #if SNMP_USE_TIMES 01255 struct tms dummy; 01256 01257 /* fixme: -1 is fault code... */ 01258 snmpv3startClock = times(&dummy); 01259 01260 /* remember how many ticks per second there are, since times() returns this */ 01261 01262 clockticks = sysconf(_SC_CLK_TCK); 01263 01264 #endif /* SNMP_USE_TIMES */ 01265 01266 gettimeofday(&snmpv3starttime, NULL); 01267 01268 if (!type) 01269 type = "__snmpapp__"; 01270 01271 /* 01272 * we need to be called back later 01273 */ 01274 snmp_register_callback(SNMP_CALLBACK_LIBRARY, 01275 SNMP_CALLBACK_POST_READ_CONFIG, 01276 init_snmpv3_post_config, NULL); 01277 01278 snmp_register_callback(SNMP_CALLBACK_LIBRARY, 01279 SNMP_CALLBACK_POST_PREMIB_READ_CONFIG, 01280 init_snmpv3_post_premib_config, NULL); 01281 /* 01282 * we need to be called back later 01283 */ 01284 snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA, 01285 snmpv3_store, (void *) strdup(type)); 01286 01287 /* 01288 * Free stuff at shutdown time 01289 */ 01290 snmp_register_callback(SNMP_CALLBACK_LIBRARY, 01291 SNMP_CALLBACK_SHUTDOWN, 01292 free_enginetime_on_shutdown, NULL); 01293 01294 /* 01295 * initialize submodules 01296 */ 01297 /* 01298 * NOTE: this must be after the callbacks are registered above, 01299 * since they need to be called before the USM callbacks. 01300 */ 01301 init_secmod(); 01302 01303 /* 01304 * register all our configuration handlers (ack, there's a lot) 01305 */ 01306 01307 /* 01308 * handle engineID setup before everything else which may depend on it 01309 */ 01310 register_prenetsnmp_mib_handler(type, "engineID", engineID_conf, NULL, 01311 "string"); 01312 register_prenetsnmp_mib_handler(type, "oldEngineID", oldengineID_conf, 01313 NULL, NULL); 01314 register_prenetsnmp_mib_handler(type, "exactEngineID", exactEngineID_conf, 01315 NULL, NULL); 01316 register_prenetsnmp_mib_handler(type, "engineIDType", 01317 engineIDType_conf, NULL, "num"); 01318 register_prenetsnmp_mib_handler(type, "engineIDNic", engineIDNic_conf, 01319 NULL, "string"); 01320 register_config_handler(type, "engineBoots", engineBoots_conf, NULL, 01321 NULL); 01322 01323 /* 01324 * default store config entries 01325 */ 01326 netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "defSecurityName", 01327 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_SECNAME); 01328 netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "defContext", 01329 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_CONTEXT); 01330 netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "defPassphrase", 01331 NETSNMP_DS_LIBRARY_ID, 01332 NETSNMP_DS_LIB_PASSPHRASE); 01333 netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "defAuthPassphrase", 01334 NETSNMP_DS_LIBRARY_ID, 01335 NETSNMP_DS_LIB_AUTHPASSPHRASE); 01336 netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "defPrivPassphrase", 01337 NETSNMP_DS_LIBRARY_ID, 01338 NETSNMP_DS_LIB_PRIVPASSPHRASE); 01339 netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "defAuthMasterKey", 01340 NETSNMP_DS_LIBRARY_ID, 01341 NETSNMP_DS_LIB_AUTHMASTERKEY); 01342 netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "defPrivMasterKey", 01343 NETSNMP_DS_LIBRARY_ID, 01344 NETSNMP_DS_LIB_PRIVMASTERKEY); 01345 netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "defAuthLocalizedKey", 01346 NETSNMP_DS_LIBRARY_ID, 01347 NETSNMP_DS_LIB_AUTHLOCALIZEDKEY); 01348 netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "defPrivLocalizedKey", 01349 NETSNMP_DS_LIBRARY_ID, 01350 NETSNMP_DS_LIB_PRIVLOCALIZEDKEY); 01351 register_config_handler("snmp", "defVersion", version_conf, NULL, 01352 "1|2c|3"); 01353 01354 register_config_handler("snmp", "defAuthType", snmpv3_authtype_conf, 01355 NULL, "MD5|SHA"); 01356 register_config_handler("snmp", "defPrivType", snmpv3_privtype_conf, 01357 NULL, 01358 #ifdef HAVE_AES 01359 "DES|AES"); 01360 #else 01361 "DES (AES support not available)"); 01362 #endif 01363 register_config_handler("snmp", "defSecurityLevel", 01364 snmpv3_secLevel_conf, NULL, 01365 "noAuthNoPriv|authNoPriv|authPriv"); 01366 register_config_handler(type, "userSetAuthPass", usm_set_password, 01367 NULL, NULL); 01368 register_config_handler(type, "userSetPrivPass", usm_set_password, 01369 NULL, NULL); 01370 register_config_handler(type, "userSetAuthKey", usm_set_password, NULL, 01371 NULL); 01372 register_config_handler(type, "userSetPrivKey", usm_set_password, NULL, 01373 NULL); 01374 register_config_handler(type, "userSetAuthLocalKey", usm_set_password, 01375 NULL, NULL); 01376 register_config_handler(type, "userSetPrivLocalKey", usm_set_password, 01377 NULL, NULL); 01378 } 01379 01380 /* 01381 * initializations for SNMPv3 to be called after the configuration files 01382 * have been read. 01383 */ 01384 01385 int 01386 init_snmpv3_post_config(int majorid, int minorid, void *serverarg, 01387 void *clientarg) 01388 { 01389 01390 size_t engineIDLen; 01391 u_char *c_engineID; 01392 01393 c_engineID = snmpv3_generate_engineID(&engineIDLen); 01394 01395 if (engineIDLen == 0 || !c_engineID) { 01396 /* 01397 * Somethine went wrong - help! 01398 */ 01399 SNMP_FREE(c_engineID); 01400 return SNMPERR_GENERR; 01401 } 01402 01403 /* 01404 * if our engineID has changed at all, the boots record must be set to 1 01405 */ 01406 if (engineIDLen != (int) oldEngineIDLength || 01407 oldEngineID == NULL || c_engineID == NULL || 01408 memcmp(oldEngineID, c_engineID, engineIDLen) != 0) { 01409 engineBoots = 1; 01410 } 01411 01412 /* 01413 * set our local engineTime in the LCD timing cache 01414 */ 01415 set_enginetime(c_engineID, engineIDLen, 01416 snmpv3_local_snmpEngineBoots(), 01417 snmpv3_local_snmpEngineTime(), TRUE); 01418 01419 SNMP_FREE(c_engineID); 01420 return SNMPERR_SUCCESS; 01421 } 01422 01423 int 01424 init_snmpv3_post_premib_config(int majorid, int minorid, void *serverarg, 01425 void *clientarg) 01426 { 01427 if (!engineIDIsSet) 01428 setup_engineID(NULL, NULL); 01429 01430 return SNMPERR_SUCCESS; 01431 } 01432 01433 /*******************************************************************-o-****** 01434 * store_snmpv3 01435 * 01436 * Parameters: 01437 * *type 01438 */ 01439 int 01440 snmpv3_store(int majorID, int minorID, void *serverarg, void *clientarg) 01441 { 01442 char line[SNMP_MAXBUF_SMALL]; 01443 u_char c_engineID[SNMP_MAXBUF_SMALL]; 01444 int engineIDLen; 01445 const char *type = (const char *) clientarg; 01446 01447 if (type == NULL) /* should never happen, since the arg is ours */ 01448 type = "unknown"; 01449 01450 sprintf(line, "engineBoots %ld", engineBoots); 01451 read_config_store(type, line); 01452 01453 engineIDLen = snmpv3_get_engineID(c_engineID, SNMP_MAXBUF_SMALL); 01454 01455 if (engineIDLen) { 01456 /* 01457 * store the engineID used for this run 01458 */ 01459 sprintf(line, "oldEngineID "); 01460 read_config_save_octet_string(line + strlen(line), c_engineID, 01461 engineIDLen); 01462 read_config_store(type, line); 01463 } 01464 return SNMPERR_SUCCESS; 01465 } /* snmpv3_store() */ 01466 01467 u_long 01468 snmpv3_local_snmpEngineBoots(void) 01469 { 01470 return engineBoots; 01471 } 01472 01473 01474 /*******************************************************************-o-****** 01475 * snmpv3_get_engineID 01476 * 01477 * Parameters: 01478 * *buf 01479 * buflen 01480 * 01481 * Returns: 01482 * Length of engineID On Success 01483 * SNMPERR_GENERR Otherwise. 01484 * 01485 * 01486 * Store engineID in buf; return the length. 01487 * 01488 */ 01489 size_t 01490 snmpv3_get_engineID(u_char * buf, size_t buflen) 01491 { 01492 /* 01493 * Sanity check. 01494 */ 01495 if (!buf || (buflen < engineIDLength)) { 01496 return 0; 01497 } 01498 01499 memcpy(buf, engineID, engineIDLength); 01500 return engineIDLength; 01501 01502 } /* end snmpv3_get_engineID() */ 01503 01504 /*******************************************************************-o-****** 01505 * snmpv3_clone_engineID 01506 * 01507 * Parameters: 01508 * **dest 01509 * *dest_len 01510 * src 01511 * srclen 01512 * 01513 * Returns: 01514 * Length of engineID On Success 01515 * 0 Otherwise. 01516 * 01517 * 01518 * Clones engineID, creates memory 01519 * 01520 */ 01521 int 01522 snmpv3_clone_engineID(u_char ** dest, size_t * destlen, u_char * src, 01523 size_t srclen) 01524 { 01525 if (!dest || !destlen) 01526 return 0; 01527 01528 if (*dest) { 01529 SNMP_FREE(*dest); 01530 *dest = NULL; 01531 } 01532 *destlen = 0; 01533 01534 if (srclen && src) { 01535 *dest = (u_char *) malloc(srclen); 01536 if (*dest == NULL) 01537 return 0; 01538 memmove(*dest, src, srclen); 01539 *destlen = srclen; 01540 } 01541 return *destlen; 01542 } /* end snmpv3_clone_engineID() */ 01543 01544 01545 /*******************************************************************-o-****** 01546 * snmpv3_generate_engineID 01547 * 01548 * Parameters: 01549 * *length 01550 * 01551 * Returns: 01552 * Pointer to copy of engineID On Success. 01553 * NULL If malloc() or snmpv3_get_engineID() 01554 * fail. 01555 * 01556 * Generates a malloced copy of our engineID. 01557 * 01558 * 'length' is set to the length of engineID -OR- < 0 on failure. 01559 */ 01560 u_char * 01561 snmpv3_generate_engineID(size_t * length) 01562 { 01563 u_char *newID; 01564 newID = (u_char *) malloc(engineIDLength); 01565 01566 if (newID) { 01567 *length = snmpv3_get_engineID(newID, engineIDLength); 01568 } 01569 01570 if (*length == 0) { 01571 SNMP_FREE(newID); 01572 newID = NULL; 01573 } 01574 01575 return newID; 01576 01577 } /* end snmpv3_generate_engineID() */ 01578 01579 /* 01580 * snmpv3_local_snmpEngineTime(): return the number of seconds since the 01581 * snmpv3 engine last incremented engine_boots 01582 */ 01583 u_long 01584 snmpv3_local_snmpEngineTime(void) 01585 { 01586 #ifdef SNMP_USE_TIMES 01587 struct tms dummy; 01588 clock_t now = times(&dummy); 01589 /* fixme: -1 is fault code... */ 01590 unsigned int result; 01591 01592 if (now < snmpv3startClock) { 01593 result = UINT_MAX - (snmpv3startClock - now); 01594 } else { 01595 result = now - snmpv3startClock; 01596 } 01597 if (result < lastcalltime) { 01598 /* wrapped */ 01599 wrapcounter++; 01600 } 01601 lastcalltime = result; 01602 result = (UINT_MAX/clockticks)*wrapcounter + result/clockticks; 01603 01604 return result; 01605 #else /* !SNMP_USE_TIMES */ 01606 struct timeval now; 01607 01608 gettimeofday(&now, NULL); 01609 return calculate_sectime_diff(&now, &snmpv3starttime); 01610 #endif /* HAVE_SYS_TIMES_H */ 01611 } 01612 01613 01614 01615 /* 01616 * Code only for Linux systems 01617 */ 01618 #if defined(IFHWADDRLEN) && defined(SIOCGIFHWADDR) 01619 static int 01620 getHwAddress(const char *networkDevice, /* e.g. "eth0", "eth1" */ 01621 char *addressOut) 01622 { /* return address. Len=IFHWADDRLEN */ 01623 /* 01624 * getHwAddress(...) 01625 * * 01626 * * This function will return a Network Interfaces Card's Hardware 01627 * * address (aka MAC address). 01628 * * 01629 * * Input Parameter(s): 01630 * * networkDevice - a null terminated string with the name of a network 01631 * * device. Examples: eth0, eth1, etc... 01632 * * 01633 * * Output Parameter(s): 01634 * * addressOut - This is the binary value of the hardware address. 01635 * * This value is NOT converted into a hexadecimal string. 01636 * * The caller must pre-allocate for a return value of 01637 * * length IFHWADDRLEN 01638 * * 01639 * * Return value: This function will return zero (0) for success. If 01640 * * an error occurred the function will return -1. 01641 * * 01642 * * Caveats: This has only been tested on Ethernet networking cards. 01643 */ 01644 int sock; /* our socket */ 01645 struct ifreq request; /* struct which will have HW address */ 01646 01647 if ((NULL == networkDevice) || (NULL == addressOut)) { 01648 return -1; 01649 } 01650 /* 01651 * In order to find out the hardware (MAC) address of our system under 01652 * * Linux we must do the following: 01653 * * 1. Create a socket 01654 * * 2. Do an ioctl(...) call with the SIOCGIFHWADDRLEN operation. 01655 */ 01656 sock = socket(AF_INET, SOCK_DGRAM, 0); 01657 if (sock < 0) { 01658 return -1; 01659 } 01660 /* 01661 * erase the request block 01662 */ 01663 memset(&request, 0, sizeof(request)); 01664 /* 01665 * copy the name of the net device we want to find the HW address for 01666 */ 01667 strncpy(request.ifr_name, networkDevice, IFNAMSIZ - 1); 01668 /* 01669 * Get the HW address 01670 */ 01671 if (ioctl(sock, SIOCGIFHWADDR, &request)) { 01672 close(sock); 01673 return -1; 01674 } 01675 close(sock); 01676 memcpy(addressOut, request.ifr_hwaddr.sa_data, IFHWADDRLEN); 01677 return 0; 01678 } 01679 #endif 01680 01681 #ifdef NETSNMP_ENABLE_TESTING_CODE 01682 /* 01683 * snmpv3_set_engineBootsAndTime(): this function does not exist. Go away. 01684 */ 01685 /* 01686 * It certainly should never be used, unless in a testing scenero, 01687 * which is why it was created 01688 */ 01689 void 01690 snmpv3_set_engineBootsAndTime(int boots, int ttime) 01691 { 01692 engineBoots = boots; 01693 gettimeofday(&snmpv3starttime, NULL); 01694 snmpv3starttime.tv_sec -= ttime; 01695 } 01696 #endif
Last modified: Wednesday, 01-Aug-2018 04:41:28 UTC
For questions regarding web content and site functionality, please write to the net-snmp-users mail list.