/** clones a data row. DOES NOT CLONE THE CONTAINED DATA. */ netsnmp_table_row * netsnmp_table_data_clone_row(netsnmp_table_row *row) { netsnmp_table_row *newrow = NULL; if (!row) return NULL; newrow = (netsnmp_table_row *) netsnmp_memdup(row, sizeof(netsnmp_table_row)); if (!newrow) return NULL; if (row->indexes) { newrow->indexes = snmp_clone_varbind(newrow->indexes); if (!newrow->indexes) { free(newrow); return NULL; } } if (row->index_oid) { newrow->index_oid = snmp_duplicate_objid(row->index_oid, row->index_oid_len); if (!newrow->index_oid) { free(newrow->indexes); free(newrow); return NULL; } } return newrow; }
netsnmp_tdata_row *netsnmp_tdata_clone_row (netsnmp_tdata_row * row) { netsnmp_tdata_row *newrow = NULL; if (!row) return NULL; memdup ((u_char **) & newrow, (u_char *) row, sizeof (netsnmp_tdata_row)); if (!newrow) return NULL; if (row->indexes) { newrow->indexes = snmp_clone_varbind (newrow->indexes); if (!newrow->indexes) { SNMP_FREE (newrow); return NULL; } } if (row->oid_index.oids) { newrow->oid_index.oids = snmp_duplicate_objid (row->oid_index.oids, row->oid_index.len); if (!newrow->oid_index.oids) { if (newrow->indexes) snmp_free_varbind (newrow->indexes); SNMP_FREE (newrow); return NULL; } } return newrow; }
int open_agentx_session(netsnmp_session * session, netsnmp_pdu *pdu) { netsnmp_session *sp; struct timeval now; DEBUGMSGTL(("agentx/master", "open %08p\n", session)); sp = (netsnmp_session *) malloc(sizeof(netsnmp_session)); if (sp == NULL) { session->s_snmp_errno = AGENTX_ERR_OPEN_FAILED; return -1; } memcpy(sp, session, sizeof(netsnmp_session)); sp->sessid = snmp_get_next_sessid(); sp->version = pdu->version; sp->timeout = pdu->time; /* * Be careful with fields: if these aren't zeroed, they will get free()d * more than once when the session is closed -- once in the main session, * and once in each subsession. Basically, if it's not being used for * some AgentX-specific purpose, it ought to be zeroed here. */ sp->community = NULL; sp->peername = NULL; sp->contextEngineID = NULL; sp->contextName = NULL; sp->securityEngineID = NULL; sp->securityPrivProto = NULL; /* * This next bit utilises unused SNMPv3 fields * to store the subagent OID and description. * This really ought to use AgentX-specific fields, * but it hardly seems worth it for a one-off use. * * But I'm willing to be persuaded otherwise.... */ sp->securityAuthProto = snmp_duplicate_objid(pdu->variables->name, pdu->variables-> name_length); sp->securityAuthProtoLen = pdu->variables->name_length; sp->securityName = strdup((char *) pdu->variables->val.string); gettimeofday(&now, NULL); sp->engineTime = calculate_time_diff(&now, &starttime); sp->subsession = session; /* link back to head */ sp->flags |= SNMP_FLAGS_SUBSESSION; sp->flags &= ~AGENTX_MSG_FLAG_NETWORK_BYTE_ORDER; sp->flags |= (pdu->flags & AGENTX_MSG_FLAG_NETWORK_BYTE_ORDER); sp->next = session->subsession; session->subsession = sp; DEBUGMSGTL(("agentx/master", "opened %08p = %d with flags = %02x\n", sp, sp->sessid, sp->flags & AGENTX_MSG_FLAGS_MASK)); return sp->sessid; }
struct header_complex_index * _header_complex_add_between(struct header_complex_index **thedata, struct header_complex_index *hciptrp, struct header_complex_index *hciptrn, oid * newoid, size_t newoid_len, void *data) { struct header_complex_index *ourself; /* * nptr should now point to the spot that we need to add ourselves * in front of, and pptr should be our new 'prev'. */ /* * create ourselves */ ourself = (struct header_complex_index *) SNMP_MALLOC_STRUCT(header_complex_index); if (ourself == NULL) return NULL; /* * change our pointers */ ourself->prev = hciptrp; ourself->next = hciptrn; if (ourself->next) ourself->next->prev = ourself; if (ourself->prev) ourself->prev->next = ourself; ourself->data = data; ourself->name = snmp_duplicate_objid(newoid, newoid_len); ourself->namelen = newoid_len; /* * rewind to the head of the list and return it (since the new head * could be us, we need to notify the above routine who the head now is. */ for (hciptrp = ourself; hciptrp->prev != NULL; hciptrp = hciptrp->prev); *thedata = hciptrp; DEBUGMSGTL(("header_complex_add_data", "adding something...\n")); return hciptrp; }
netsnmp_subtree * find_extensible(netsnmp_subtree *tp, oid *tname, size_t tnamelen, int exact) { size_t tmp; int i; struct extensible *exten = 0; struct variable myvp; oid name[MAX_OID_LEN]; static netsnmp_subtree mysubtree[2] = { { NULL, 0, NULL, 0, NULL, 0, NULL, 0, 0, NULL, NULL, 0, 0, 0, NULL, NULL, NULL, 0, 0, NULL, 0, 0 }, { NULL, 0, NULL, 0, NULL, 0, NULL, 0, 0, NULL, NULL, 0, 0, 0, NULL, NULL, NULL, 0, 0, NULL, 0, 0 } }; for (i = 1; i <= (int) numrelocs; i++) { exten = get_exten_instance(relocs, i); if (!exten) continue; if (exten->miblen != 0) { memcpy(myvp.name, exten->miboid, exten->miblen * sizeof(oid)); memcpy(name, tname, tnamelen * sizeof(oid)); myvp.name[exten->miblen] = name[exten->miblen]; myvp.namelen = exten->miblen + 1; tmp = exten->miblen + 1; if (!header_simple_table(&myvp, name, &tmp, -1, NULL, NULL, numrelocs)) { break; } } } if (i > (int)numrelocs || exten == NULL) { return (tp); } if (mysubtree[0].name_a != NULL) { free(mysubtree[0].name_a); mysubtree[0].name_a = NULL; } mysubtree[0].name_a = snmp_duplicate_objid(exten->miboid, exten->miblen); mysubtree[0].namelen = exten->miblen; mysubtree[0].variables = (struct variable *)extensible_relocatable_variables; mysubtree[0].variables_len = sizeof(extensible_relocatable_variables) / sizeof(*extensible_relocatable_variables); mysubtree[0].variables_width = sizeof(*extensible_relocatable_variables); mysubtree[1].namelen = 0; return (mysubtree); }
int netsnmp_table_data_copy_row( netsnmp_table_row *old_row, netsnmp_table_row *new_row ) { if (!old_row || !new_row) return -1; memcpy(new_row, old_row, sizeof(netsnmp_table_row)); if (old_row->indexes) new_row->indexes = snmp_clone_varbind(old_row->indexes); if (old_row->index_oid) new_row->index_oid = snmp_duplicate_objid(old_row->index_oid, old_row->index_oid_len); /* XXX - Doesn't copy table-specific row structure */ return 0; }
/** returns a cache */ netsnmp_cache * netsnmp_cache_create(int timeout, NetsnmpCacheLoad * load_hook, NetsnmpCacheFree * free_hook, const oid * rootoid, int rootoid_len) { netsnmp_cache *cache = NULL; cache = SNMP_MALLOC_TYPEDEF(netsnmp_cache); if (NULL == cache) { snmp_log(LOG_ERR,"malloc error in netsnmp_cache_create\n"); return NULL; } cache->timeout = timeout; cache->load_cache = load_hook; cache->free_cache = free_hook; cache->enabled = 1; if(0 == cache->timeout) cache->timeout = netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_CACHE_TIMEOUT); /* * Add the registered OID information, and tack * this onto the list for cache SNMP management * * Note that this list is not ordered. * table_iterator rules again! */ if (rootoid) { cache->rootoid = snmp_duplicate_objid(rootoid, rootoid_len); cache->rootoid_len = rootoid_len; cache->next = cache_head; if (cache_head) cache_head->prev = cache; cache_head = cache; } return cache; }
int netsnmp_tdata_copy_row (netsnmp_tdata_row * dst_row, netsnmp_tdata_row * src_row) { if (!src_row || !dst_row) return -1; memcpy ((u_char *) dst_row, (u_char *) src_row, sizeof (netsnmp_tdata_row)); if (src_row->indexes) { dst_row->indexes = snmp_clone_varbind (src_row->indexes); if (!dst_row->indexes) return -1; } if (src_row->oid_index.oids) { dst_row->oid_index.oids = snmp_duplicate_objid (src_row->oid_index.oids, src_row->oid_index.len); if (!dst_row->oid_index.oids) return -1; } return 0; }
int snmp_parse_args(int argc, char *const *argv, netsnmp_session * session, const char *localOpts, void (*proc) (int, char *const *, int)) { int arg; char *cp; char *Apsz = NULL; char *Xpsz = NULL; char *Cpsz = NULL; char Opts[BUF_SIZE]; /* * initialize session to default values */ snmp_sess_init(session); strcpy(Opts, "Y:VhHm:M:O:I:P:D:dv:r:t:c:Z:e:E:n:u:l:x:X:a:A:p:T:-:3:"); if (localOpts) strcat(Opts, localOpts); /* * get the options */ DEBUGMSGTL(("snmp_parse_args", "starting: %d/%d\n", optind, argc)); for (arg = 0; arg < argc; arg++) { DEBUGMSGTL(("snmp_parse_args", " arg %d = %s\n", arg, argv[arg])); } optind = 1; while ((arg = getopt(argc, argv, Opts)) != EOF) { DEBUGMSGTL(("snmp_parse_args", "handling (#%d): %c\n", optind, arg)); switch (arg) { case '-': if (strcasecmp(optarg, "help") == 0) { return (-1); } if (strcasecmp(optarg, "version") == 0) { fprintf(stderr, "NET-SNMP version: %s\n", netsnmp_get_version()); return (-2); } handle_long_opt(optarg); break; case 'V': fprintf(stderr, "NET-SNMP version: %s\n", netsnmp_get_version()); return (-2); case 'h': return (-1); break; case 'H': init_snmp("snmpapp"); fprintf(stderr, "Configuration directives understood:\n"); read_config_print_usage(" "); return (-2); case 'Y': netsnmp_config_remember(optarg); break; case 'm': setenv("MIBS", optarg, 1); break; case 'M': setenv("MIBDIRS", optarg, 1); break; case 'O': cp = snmp_out_toggle_options(optarg); if (cp != NULL) { fprintf(stderr, "Unknown output option passed to -O: %c.\n", *cp); return (-1); } break; case 'I': cp = snmp_in_toggle_options(optarg); if (cp != NULL) { fprintf(stderr, "Unknown input option passed to -I: %c.\n", *cp); return (-1); } break; case 'P': cp = snmp_mib_toggle_options(optarg); if (cp != NULL) { fprintf(stderr, "Unknown parsing option passed to -P: %c.\n", *cp); return (-1); } break; case 'D': debug_register_tokens(optarg); snmp_set_do_debugging(1); break; case 'd': ds_set_boolean(DS_LIBRARY_ID, DS_LIB_DUMP_PACKET, 1); break; case 'v': if (!strcmp(optarg, "1")) { session->version = SNMP_VERSION_1; } else if (!strcasecmp(optarg, "2c")) { session->version = SNMP_VERSION_2c; } else if (!strcasecmp(optarg, "3")) { session->version = SNMP_VERSION_3; } else { fprintf(stderr, "Invalid version specified after -v flag: %s\n", optarg); return (-1); } break; case 'p': fprintf(stderr, "Warning: -p option is no longer used - "); fprintf(stderr, "specify the remote host as HOST:PORT\n"); return (-1); break; case 'T': fprintf(stderr, "Warning: -T option is no longer used - "); fprintf(stderr, "specify the remote host as TRANSPORT:HOST\n"); return (-1); break; case 't': session->timeout = atoi(optarg) * 1000000L; if (session->timeout < 0 || !isdigit(optarg[0])) { fprintf(stderr, "Invalid timeout in seconds after -t flag.\n"); return (-1); } break; case 'r': session->retries = atoi(optarg); if (session->retries < 0 || !isdigit(optarg[0])) { fprintf(stderr, "Invalid number of retries after -r flag.\n"); return (-1); } break; case 'c': Cpsz = optarg; break; case '3': if (snmpv3_options(optarg, session, &Apsz, &Xpsz, argc, argv) < 0) { return (-1); } break; #define SNMPV3_CMD_OPTIONS #ifdef SNMPV3_CMD_OPTIONS case 'Z': session->engineBoots = strtoul(optarg, NULL, 10); if (session->engineBoots == 0 || !isdigit(optarg[0])) { fprintf(stderr, "Need engine boots value after -Z flag.\n"); return (-1); } cp = strchr(optarg, ','); if (cp && *(++cp) && isdigit(*cp)) session->engineTime = strtoul(cp, NULL, 10); /* * Handle previous '-Z boot time' syntax */ else if ((optind < argc) && isdigit(argv[optind][0])) session->engineTime = strtoul(argv[optind], NULL, 10); else { fprintf(stderr, "Need engine time value after -Z flag.\n"); return (-1); } break; case 'e':{ size_t ebuf_len = 32, eout_len = 0; u_char *ebuf = (u_char *) malloc(ebuf_len); if (ebuf == NULL) { fprintf(stderr, "malloc failure processing -e flag.\n"); return (-1); } if (!snmp_hex_to_binary (&ebuf, &ebuf_len, &eout_len, 1, optarg)) { fprintf(stderr, "Bad engine ID value after -e flag.\n"); free(ebuf); return (-1); } session->securityEngineID = ebuf; session->securityEngineIDLen = eout_len; break; } case 'E':{ size_t ebuf_len = 32, eout_len = 0; u_char *ebuf = (u_char *) malloc(ebuf_len); if (ebuf == NULL) { fprintf(stderr, "malloc failure processing -E flag.\n"); return (-1); } if (!snmp_hex_to_binary (&ebuf, &ebuf_len, &eout_len, 1, optarg)) { fprintf(stderr, "Bad engine ID value after -E flag.\n"); free(ebuf); return (-1); } session->contextEngineID = ebuf; session->contextEngineIDLen = eout_len; break; } case 'n': session->contextName = optarg; session->contextNameLen = strlen(optarg); break; case 'u': session->securityName = optarg; session->securityNameLen = strlen(optarg); break; case 'l': if (!strcasecmp(optarg, "noAuthNoPriv") || !strcmp(optarg, "1") || !strcasecmp(optarg, "nanp")) { session->securityLevel = SNMP_SEC_LEVEL_NOAUTH; } else if (!strcasecmp(optarg, "authNoPriv") || !strcmp(optarg, "2") || !strcasecmp(optarg, "anp")) { session->securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV; } else if (!strcasecmp(optarg, "authPriv") || !strcmp(optarg, "3") || !strcasecmp(optarg, "ap")) { session->securityLevel = SNMP_SEC_LEVEL_AUTHPRIV; } else { fprintf(stderr, "Invalid security level specified after -l flag: %s\n", optarg); return (-1); } break; case 'a': if (!strcasecmp(optarg, "MD5")) { session->securityAuthProto = usmHMACMD5AuthProtocol; session->securityAuthProtoLen = USM_AUTH_PROTO_MD5_LEN; } else if (!strcasecmp(optarg, "SHA")) { session->securityAuthProto = usmHMACSHA1AuthProtocol; session->securityAuthProtoLen = USM_AUTH_PROTO_SHA_LEN; } else { fprintf(stderr, "Invalid authentication protocol specified after -a flag: %s\n", optarg); return (-1); } break; case 'x': if (!strcasecmp(optarg, "DES")) { session->securityPrivProto = usmDESPrivProtocol; session->securityPrivProtoLen = USM_PRIV_PROTO_DES_LEN; } else { fprintf(stderr, "Invalid privacy protocol specified after -x flag: %s\n", optarg); return (-1); } break; case 'A': Apsz = optarg; break; case 'X': Xpsz = optarg; break; #endif /* SNMPV3_CMD_OPTIONS */ case '?': return (-1); break; default: proc(argc, argv, arg); break; } } DEBUGMSGTL(("snmp_parse_args", "finished: %d/%d\n", optind, argc)); /* * read in MIB database and initialize the snmp library */ init_snmp("snmpapp"); /* * session default version */ if (session->version == SNMP_DEFAULT_VERSION) { /* * run time default version */ session->version = ds_get_int(DS_LIBRARY_ID, DS_LIB_SNMPVERSION); /* * compile time default version */ if (!session->version) { switch (SNMP_DEFAULT_VERSION) { case 1: session->version = SNMP_VERSION_1; break; case 2: session->version = SNMP_VERSION_2c; break; case 3: session->version = SNMP_VERSION_3; break; } } else { if (session->version == DS_SNMP_VERSION_1) /* bogus value. version 1 actually = 0 */ session->version = SNMP_VERSION_1; } } /* * make master key from pass phrases */ if (Apsz) { session->securityAuthKeyLen = USM_AUTH_KU_LEN; if (session->securityAuthProto == NULL) { /* * get .conf set default */ const oid *def = get_default_authtype(&session->securityAuthProtoLen); session->securityAuthProto = snmp_duplicate_objid(def, session->securityAuthProtoLen); } if (session->securityAuthProto == NULL) { /* * assume MD5 */ session->securityAuthProto = snmp_duplicate_objid(usmHMACMD5AuthProtocol, USM_AUTH_PROTO_MD5_LEN); session->securityAuthProtoLen = USM_AUTH_PROTO_MD5_LEN; } if (generate_Ku(session->securityAuthProto, session->securityAuthProtoLen, (u_char *) Apsz, strlen(Apsz), session->securityAuthKey, &session->securityAuthKeyLen) != SNMPERR_SUCCESS) { snmp_perror(argv[0]); fprintf(stderr, "Error generating a key (Ku) from the supplied authentication pass phrase. \n"); return (-2); } } if (Xpsz) { session->securityPrivKeyLen = USM_PRIV_KU_LEN; if (session->securityPrivProto == NULL) { /* * get .conf set default */ const oid *def = get_default_privtype(&session->securityPrivProtoLen); session->securityPrivProto = snmp_duplicate_objid(def, session->securityPrivProtoLen); } if (session->securityPrivProto == NULL) { /* * assume DES */ session->securityPrivProto = snmp_duplicate_objid(usmDESPrivProtocol, USM_PRIV_PROTO_DES_LEN); session->securityPrivProtoLen = USM_PRIV_PROTO_DES_LEN; } if (generate_Ku(session->securityAuthProto, session->securityAuthProtoLen, (u_char *) Xpsz, strlen(Xpsz), session->securityPrivKey, &session->securityPrivKeyLen) != SNMPERR_SUCCESS) { snmp_perror(argv[0]); fprintf(stderr, "Error generating a key (Ku) from the supplied privacy pass phrase. \n"); return (-2); } } /* * get the hostname */ if (optind == argc) { fprintf(stderr, "No hostname specified.\n"); return (-1); } session->peername = argv[optind++]; /* hostname */ /* * If v1 or v2c, check community has been set, either by a -c option above, * or via a default token somewhere. */ if (session->version == SNMP_VERSION_1 || session->version == SNMP_VERSION_2c) { if (Cpsz == NULL) { Cpsz = ds_get_string(DS_LIBRARY_ID, DS_LIB_COMMUNITY); } if (Cpsz == NULL) { fprintf(stderr, "No community name specified.\n"); return (-1); } session->community = (unsigned char *) Cpsz; session->community_len = strlen(Cpsz); } return optind; }
struct header_complex_index * header_complex_add_data_by_oid(struct header_complex_index **thedata, oid * newoid, size_t newoid_len, void *data) { struct header_complex_index *hciptrn, *hciptrp, *ourself; int rc; if (thedata == NULL || newoid == NULL || data == NULL) return NULL; for (hciptrn = *thedata, hciptrp = NULL; hciptrn != NULL; hciptrp = hciptrn, hciptrn = hciptrn->next) { /* * XXX: check for == and error (overlapping table entries) * 8/2005 rks Ok, I added duplicate entry check, but only log * warning and continue, because it seems that nobody * that calls this fucntion does error checking!. */ rc = snmp_oid_compare(hciptrn->name, hciptrn->namelen, newoid, newoid_len); if (rc > 0) break; else if (0 == rc) { snmp_log(LOG_WARNING, "header_complex_add_data_by_oid with " "duplicate index.\n"); /** uncomment null return when callers do error checking */ /** return NULL; */ } } /* * nptr should now point to the spot that we need to add ourselves * in front of, and pptr should be our new 'prev'. */ /* * create ourselves */ ourself = (struct header_complex_index *) SNMP_MALLOC_STRUCT(header_complex_index); if (ourself == NULL) return NULL; /* * change our pointers */ ourself->prev = hciptrp; ourself->next = hciptrn; if (ourself->next) ourself->next->prev = ourself; if (ourself->prev) ourself->prev->next = ourself; ourself->data = data; ourself->name = snmp_duplicate_objid(newoid, newoid_len); ourself->namelen = newoid_len; /* * rewind to the head of the list and return it (since the new head * could be us, we need to notify the above routine who the head now is. */ for (hciptrp = ourself; hciptrp->prev != NULL; hciptrp = hciptrp->prev); *thedata = hciptrp; DEBUGMSGTL(("header_complex_add_data", "adding something...\n")); return hciptrp; }
int netsnmp_parse_args(int argc, char **argv, netsnmp_session * session, const char *localOpts, void (*proc) (int, char *const *, int), int flags) { static char *sensitive[4] = { NULL, NULL, NULL, NULL }; int arg, sp = 0, testcase = 0; char *cp; char *Apsz = NULL; char *Xpsz = NULL; char *Cpsz = NULL; char Opts[BUF_SIZE]; int zero_sensitive = !( flags & NETSNMP_PARSE_ARGS_NOZERO ); char *backup_NETSNMP_DS_LIB_OUTPUT_PRECISION = NULL; /* * initialize session to default values */ snmp_sess_init(session); strcpy(Opts, "Y:VhHm:M:O:I:P:D:dv:r:t:c:Z:e:E:n:u:l:x:X:a:A:p:T:-:3:s:S:L:"); if (localOpts) { if (strlen(localOpts) + strlen(Opts) >= sizeof(Opts)) { snmp_log(LOG_ERR, "Too many localOpts in snmp_parse_args()\n"); return -1; } strcat(Opts, localOpts); } /* * get the options */ DEBUGMSGTL(("snmp_parse_args", "starting: %d/%d\n", optind, argc)); for (arg = 0; arg < argc; arg++) { DEBUGMSGTL(("snmp_parse_args", " arg %d = %s\n", arg, argv[arg])); } optind = 1; while ((arg = getopt(argc, argv, Opts)) != EOF) { DEBUGMSGTL(("snmp_parse_args", "handling (#%d): %c\n", optind, arg)); switch (arg) { case '-': if (strcasecmp(optarg, "help") == 0) { return (NETSNMP_PARSE_ARGS_ERROR_USAGE); } if (strcasecmp(optarg, "version") == 0) { fprintf(stderr,"NET-SNMP version: %s\n",netsnmp_get_version()); return (NETSNMP_PARSE_ARGS_SUCCESS_EXIT); } handle_long_opt(optarg); break; case 'V': fprintf(stderr, "NET-SNMP version: %s\n", netsnmp_get_version()); return (NETSNMP_PARSE_ARGS_SUCCESS_EXIT); case 'h': return (NETSNMP_PARSE_ARGS_ERROR_USAGE); break; case 'H': init_snmp("snmpapp"); fprintf(stderr, "Configuration directives understood:\n"); read_config_print_usage(" "); return (NETSNMP_PARSE_ARGS_SUCCESS_EXIT); case 'Y': netsnmp_config_remember(optarg); break; #ifndef NETSNMP_DISABLE_MIB_LOADING case 'm': setenv("MIBS", optarg, 1); break; case 'M': netsnmp_get_mib_directory(); /* prepare the default directories */ netsnmp_set_mib_directory(optarg); break; #endif /* NETSNMP_DISABLE_MIB_LOADING */ case 'O': cp = snmp_out_options(optarg, argc, argv); if (cp != NULL) { fprintf(stderr, "Unknown output option passed to -O: %c.\n", *cp); return (NETSNMP_PARSE_ARGS_ERROR_USAGE); } break; case 'I': cp = snmp_in_options(optarg, argc, argv); if (cp != NULL) { fprintf(stderr, "Unknown input option passed to -I: %c.\n", *cp); return (NETSNMP_PARSE_ARGS_ERROR_USAGE); } break; #ifndef NETSNMP_DISABLE_MIB_LOADING case 'P': cp = snmp_mib_toggle_options(optarg); if (cp != NULL) { fprintf(stderr, "Unknown parsing option passed to -P: %c.\n", *cp); return (NETSNMP_PARSE_ARGS_ERROR_USAGE); } break; #endif /* NETSNMP_DISABLE_MIB_LOADING */ case 'D': debug_register_tokens(optarg); snmp_set_do_debugging(1); break; case 'd': netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DUMP_PACKET, 1); break; case 'v': session->version = -1; #ifndef NETSNMP_DISABLE_SNMPV1 if (!strcmp(optarg, "1")) { session->version = SNMP_VERSION_1; } #endif #ifndef NETSNMP_DISABLE_SNMPV2C if (!strcasecmp(optarg, "2c")) { session->version = SNMP_VERSION_2c; } #endif if (!strcasecmp(optarg, "3")) { session->version = SNMP_VERSION_3; } if (session->version == -1) { fprintf(stderr, "Invalid version specified after -v flag: %s\n", optarg); return (NETSNMP_PARSE_ARGS_ERROR_USAGE); } break; case 'p': fprintf(stderr, "Warning: -p option is no longer used - "); fprintf(stderr, "specify the remote host as HOST:PORT\n"); return (NETSNMP_PARSE_ARGS_ERROR_USAGE); break; case 'T': { char leftside[SNMP_MAXBUF_MEDIUM], rightside[SNMP_MAXBUF_MEDIUM]; char *tmpcp, *tmpopt; /* ensure we have a proper argument */ tmpopt = strdup(optarg); tmpcp = strchr(tmpopt, '='); if (!tmpcp) { fprintf(stderr, "-T expects a NAME=VALUE pair.\n"); return (NETSNMP_PARSE_ARGS_ERROR_USAGE); } *tmpcp++ = '\0'; /* create the transport config container if this is the first */ if (!session->transport_configuration) { netsnmp_container_init_list(); session->transport_configuration = netsnmp_container_find("transport_configuration:fifo"); if (!session->transport_configuration) { fprintf(stderr, "failed to initialize the transport configuration container\n"); free(tmpopt); return (NETSNMP_PARSE_ARGS_ERROR); } session->transport_configuration->compare = (netsnmp_container_compare*) netsnmp_transport_config_compare; } /* set the config */ strlcpy(leftside, tmpopt, sizeof(leftside)); strlcpy(rightside, tmpcp, sizeof(rightside)); CONTAINER_INSERT(session->transport_configuration, netsnmp_transport_create_config(leftside, rightside)); free(tmpopt); } break; case 't': session->timeout = (long)(atof(optarg) * 1000000L); if (session->timeout <= 0) { fprintf(stderr, "Invalid timeout in seconds after -t flag.\n"); return (NETSNMP_PARSE_ARGS_ERROR_USAGE); } break; case 'r': session->retries = atoi(optarg); if (session->retries < 0 || !isdigit((unsigned char)(optarg[0]))) { fprintf(stderr, "Invalid number of retries after -r flag.\n"); return (NETSNMP_PARSE_ARGS_ERROR_USAGE); } break; case 'c': if (zero_sensitive) { if ((sensitive[sp] = strdup(optarg)) != NULL) { Cpsz = sensitive[sp]; memset(optarg, '\0', strlen(optarg)); sp++; } else { fprintf(stderr, "malloc failure processing -c flag.\n"); return NETSNMP_PARSE_ARGS_ERROR; } } else { Cpsz = optarg; } break; case '3': /* TODO: This needs to zero things too. */ if (snmpv3_options(optarg, session, &Apsz, &Xpsz, argc, argv) < 0){ return (NETSNMP_PARSE_ARGS_ERROR_USAGE); } break; case 'L': if (snmp_log_options(optarg, argc, argv) < 0) { return (NETSNMP_PARSE_ARGS_ERROR_USAGE); } break; #define SNMPV3_CMD_OPTIONS #ifdef SNMPV3_CMD_OPTIONS case 'Z': errno = 0; session->engineBoots = strtoul(optarg, &cp, 10); if (errno || cp == optarg) { fprintf(stderr, "Need engine boots value after -Z flag.\n"); return (NETSNMP_PARSE_ARGS_ERROR_USAGE); } if (*cp == ',') { char *endptr; cp++; session->engineTime = strtoul(cp, &endptr, 10); if (errno || cp == endptr) { fprintf(stderr, "Need engine time after \"-Z engineBoot,\".\n"); return (NETSNMP_PARSE_ARGS_ERROR_USAGE); } } /* * Handle previous '-Z boot time' syntax */ else if (optind < argc) { session->engineTime = strtoul(argv[optind], &cp, 10); if (errno || cp == argv[optind]) { fprintf(stderr, "Need engine time after \"-Z engineBoot\".\n"); return (NETSNMP_PARSE_ARGS_ERROR_USAGE); } } else { fprintf(stderr, "Need engine time after \"-Z engineBoot\".\n"); return (NETSNMP_PARSE_ARGS_ERROR_USAGE); } break; case 'e':{ size_t ebuf_len = 32, eout_len = 0; u_char *ebuf = (u_char *)malloc(ebuf_len); if (ebuf == NULL) { fprintf(stderr, "malloc failure processing -e flag.\n"); return (NETSNMP_PARSE_ARGS_ERROR); } if (!snmp_hex_to_binary (&ebuf, &ebuf_len, &eout_len, 1, optarg)) { fprintf(stderr, "Bad engine ID value after -e flag.\n"); free(ebuf); return (NETSNMP_PARSE_ARGS_ERROR_USAGE); } if ((eout_len < 5) || (eout_len > 32)) { fprintf(stderr, "Invalid engine ID value after -e flag.\n"); free(ebuf); return (NETSNMP_PARSE_ARGS_ERROR_USAGE); } session->securityEngineID = ebuf; session->securityEngineIDLen = eout_len; break; } case 'E':{ size_t ebuf_len = 32, eout_len = 0; u_char *ebuf = (u_char *)malloc(ebuf_len); if (ebuf == NULL) { fprintf(stderr, "malloc failure processing -E flag.\n"); return (NETSNMP_PARSE_ARGS_ERROR); } if (!snmp_hex_to_binary(&ebuf, &ebuf_len, &eout_len, 1, optarg)) { fprintf(stderr, "Bad engine ID value after -E flag.\n"); free(ebuf); return (NETSNMP_PARSE_ARGS_ERROR_USAGE); } if ((eout_len < 5) || (eout_len > 32)) { fprintf(stderr, "Invalid engine ID value after -E flag.\n"); free(ebuf); return (NETSNMP_PARSE_ARGS_ERROR_USAGE); } session->contextEngineID = ebuf; session->contextEngineIDLen = eout_len; break; } case 'n': session->contextName = optarg; session->contextNameLen = strlen(optarg); break; case 'u': if (zero_sensitive) { if ((sensitive[sp] = strdup(optarg)) != NULL) { session->securityName = sensitive[sp]; session->securityNameLen = strlen(sensitive[sp]); memset(optarg, '\0', strlen(optarg)); sp++; } else { fprintf(stderr, "malloc failure processing -u flag.\n"); return NETSNMP_PARSE_ARGS_ERROR; } } else { session->securityName = optarg; session->securityNameLen = strlen(optarg); } break; case 'l': if (!strcasecmp(optarg, "noAuthNoPriv") || !strcmp(optarg, "1") || !strcasecmp(optarg, "noauth") || !strcasecmp(optarg, "nanp")) { session->securityLevel = SNMP_SEC_LEVEL_NOAUTH; } else if (!strcasecmp(optarg, "authNoPriv") || !strcmp(optarg, "2") || !strcasecmp(optarg, "auth") || !strcasecmp(optarg, "anp")) { session->securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV; } else if (!strcasecmp(optarg, "authPriv") || !strcmp(optarg, "3") || !strcasecmp(optarg, "priv") || !strcasecmp(optarg, "ap")) { session->securityLevel = SNMP_SEC_LEVEL_AUTHPRIV; } else { fprintf(stderr, "Invalid security level specified after -l flag: %s\n", optarg); return (NETSNMP_PARSE_ARGS_ERROR_USAGE); } break; #ifdef NETSNMP_SECMOD_USM case 'a': #ifndef NETSNMP_DISABLE_MD5 if (!strcasecmp(optarg, "MD5")) { session->securityAuthProto = usmHMACMD5AuthProtocol; session->securityAuthProtoLen = USM_AUTH_PROTO_MD5_LEN; } else #endif if (!strcasecmp(optarg, "SHA")) { session->securityAuthProto = usmHMACSHA1AuthProtocol; session->securityAuthProtoLen = USM_AUTH_PROTO_SHA_LEN; } else { fprintf(stderr, "Invalid authentication protocol specified after -a flag: %s\n", optarg); return (NETSNMP_PARSE_ARGS_ERROR_USAGE); } break; case 'x': testcase = 0; #ifndef NETSNMP_DISABLE_DES if (!strcasecmp(optarg, "DES")) { testcase = 1; session->securityPrivProto = usmDESPrivProtocol; session->securityPrivProtoLen = USM_PRIV_PROTO_DES_LEN; } #endif #ifdef HAVE_AES if (!strcasecmp(optarg, "AES128") || !strcasecmp(optarg, "AES")) { testcase = 1; session->securityPrivProto = usmAESPrivProtocol; session->securityPrivProtoLen = USM_PRIV_PROTO_AES_LEN; } #endif if (testcase == 0) { fprintf(stderr, "Invalid privacy protocol specified after -x flag: %s\n", optarg); return (NETSNMP_PARSE_ARGS_ERROR_USAGE); } break; case 'A': if (zero_sensitive) { if ((sensitive[sp] = strdup(optarg)) != NULL) { Apsz = sensitive[sp]; memset(optarg, '\0', strlen(optarg)); sp++; } else { fprintf(stderr, "malloc failure processing -A flag.\n"); return NETSNMP_PARSE_ARGS_ERROR; } } else { Apsz = optarg; } break; case 'X': if (zero_sensitive) { if ((sensitive[sp] = strdup(optarg)) != NULL) { Xpsz = sensitive[sp]; memset(optarg, '\0', strlen(optarg)); sp++; } else { fprintf(stderr, "malloc failure processing -X flag.\n"); return NETSNMP_PARSE_ARGS_ERROR; } } else { Xpsz = optarg; } break; #endif /* SNMPV3_CMD_OPTIONS */ #endif /* NETSNMP_SECMOD_USM */ case '?': return (NETSNMP_PARSE_ARGS_ERROR_USAGE); break; default: proc(argc, argv, arg); break; } } DEBUGMSGTL(("snmp_parse_args", "finished: %d/%d\n", optind, argc)); /* * save command line parameters which should have precedence above config file settings * (There ought to be a more scalable approach than this....) */ if (netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OUTPUT_PRECISION)) { backup_NETSNMP_DS_LIB_OUTPUT_PRECISION = strdup(netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OUTPUT_PRECISION)); } /* * read in MIB database and initialize the snmp library, read the config file */ init_snmp("snmpapp"); /* * restore command line parameters which should have precedence above config file settings */ if(backup_NETSNMP_DS_LIB_OUTPUT_PRECISION) { netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OUTPUT_PRECISION, backup_NETSNMP_DS_LIB_OUTPUT_PRECISION); free(backup_NETSNMP_DS_LIB_OUTPUT_PRECISION); } /* * session default version */ if (session->version == SNMP_DEFAULT_VERSION) { /* * run time default version */ session->version = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_SNMPVERSION); /* * compile time default version */ if (!session->version) { switch (NETSNMP_DEFAULT_SNMP_VERSION) { #ifndef NETSNMP_DISABLE_SNMPV1 case 1: session->version = SNMP_VERSION_1; break; #endif #ifndef NETSNMP_DISABLE_SNMPV2C case 2: session->version = SNMP_VERSION_2c; break; #endif case 3: session->version = SNMP_VERSION_3; break; default: snmp_log(LOG_ERR, "Can't determine a valid SNMP version for the session\n"); return(NETSNMP_PARSE_ARGS_ERROR); } } else { #ifndef NETSNMP_DISABLE_SNMPV1 if (session->version == NETSNMP_DS_SNMP_VERSION_1) /* bogus value. version 1 actually = 0 */ session->version = SNMP_VERSION_1; #endif } } #ifdef NETSNMP_SECMOD_USM /* XXX: this should ideally be moved to snmpusm.c somehow */ /* * make master key from pass phrases */ if (Apsz) { session->securityAuthKeyLen = USM_AUTH_KU_LEN; if (session->securityAuthProto == NULL) { /* * get .conf set default */ const oid *def = get_default_authtype(&session->securityAuthProtoLen); session->securityAuthProto = snmp_duplicate_objid(def, session->securityAuthProtoLen); } if (session->securityAuthProto == NULL) { #ifndef NETSNMP_DISABLE_MD5 /* * assume MD5 */ session->securityAuthProto = snmp_duplicate_objid(usmHMACMD5AuthProtocol, USM_AUTH_PROTO_MD5_LEN); session->securityAuthProtoLen = USM_AUTH_PROTO_MD5_LEN; #else session->securityAuthProto = snmp_duplicate_objid(usmHMACSHA1AuthProtocol, USM_AUTH_PROTO_SHA_LEN); session->securityAuthProtoLen = USM_AUTH_PROTO_SHA_LEN; #endif } if (generate_Ku(session->securityAuthProto, session->securityAuthProtoLen, (u_char *) Apsz, strlen(Apsz), session->securityAuthKey, &session->securityAuthKeyLen) != SNMPERR_SUCCESS) { snmp_perror(argv[0]); fprintf(stderr, "Error generating a key (Ku) from the supplied authentication pass phrase. \n"); return (NETSNMP_PARSE_ARGS_ERROR); } } if (Xpsz) { session->securityPrivKeyLen = USM_PRIV_KU_LEN; if (session->securityPrivProto == NULL) { /* * get .conf set default */ const oid *def = get_default_privtype(&session->securityPrivProtoLen); session->securityPrivProto = snmp_duplicate_objid(def, session->securityPrivProtoLen); } if (session->securityPrivProto == NULL) { /* * assume DES */ #ifndef NETSNMP_DISABLE_DES session->securityPrivProto = snmp_duplicate_objid(usmDESPrivProtocol, USM_PRIV_PROTO_DES_LEN); session->securityPrivProtoLen = USM_PRIV_PROTO_DES_LEN; #else session->securityPrivProto = snmp_duplicate_objid(usmAESPrivProtocol, USM_PRIV_PROTO_AES_LEN); session->securityPrivProtoLen = USM_PRIV_PROTO_AES_LEN; #endif } if (generate_Ku(session->securityAuthProto, session->securityAuthProtoLen, (u_char *) Xpsz, strlen(Xpsz), session->securityPrivKey, &session->securityPrivKeyLen) != SNMPERR_SUCCESS) { snmp_perror(argv[0]); fprintf(stderr, "Error generating a key (Ku) from the supplied privacy pass phrase. \n"); return (NETSNMP_PARSE_ARGS_ERROR); } } #endif /* NETSNMP_SECMOD_USM */ /* * get the hostname */ if (optind == argc) { fprintf(stderr, "No hostname specified.\n"); return (NETSNMP_PARSE_ARGS_ERROR_USAGE); } session->peername = argv[optind++]; /* hostname */ #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C) /* * If v1 or v2c, check community has been set, either by a -c option above, * or via a default token somewhere. * If neither, it will be taken from the incoming request PDU. */ #if defined(NETSNMP_DISABLE_SNMPV1) if (session->version == SNMP_VERSION_2c) #else #if defined(NETSNMP_DISABLE_SNMPV2C) if (session->version == SNMP_VERSION_1) #else if (session->version == SNMP_VERSION_1 || session->version == SNMP_VERSION_2c) #endif #endif { if (Cpsz == NULL) { Cpsz = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_COMMUNITY); if (Cpsz == NULL) { if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_IGNORE_NO_COMMUNITY)){ DEBUGMSGTL(("snmp_parse_args", "ignoring that the community string is not present\n")); session->community = NULL; session->community_len = 0; } else { fprintf(stderr, "No community name specified.\n"); return (NETSNMP_PARSE_ARGS_ERROR_USAGE); } } } else { session->community = (unsigned char *)Cpsz; session->community_len = strlen(Cpsz); } } #endif /* support for community based SNMP */ return optind; }
void netsnmp_parse_override(const char *token, char *line) { char *cp; char buf[SNMP_MAXBUF], namebuf[SNMP_MAXBUF]; int readwrite = 0; oid oidbuf[MAX_OID_LEN]; size_t oidbuf_len = MAX_OID_LEN; int type; override_data *thedata; netsnmp_handler_registration *the_reg; cp = copy_nword(line, namebuf, sizeof(namebuf) - 1); if (strcmp(namebuf, "-rw") == 0) { readwrite = 1; cp = copy_nword(cp, namebuf, sizeof(namebuf) - 1); } if (!cp) { config_perror("no oid specified"); return; } if (!snmp_parse_oid(namebuf, oidbuf, &oidbuf_len)) { config_perror("illegal oid"); return; } cp = copy_nword(cp, buf, sizeof(buf) - 1); if (!cp && strcmp(buf, "null") != 0) { config_perror("no variable value specified"); return; } { struct { const char* key; int value; } const strings[] = { { "counter", ASN_COUNTER }, { "counter64", ASN_COUNTER64 }, { "integer", ASN_INTEGER }, { "ipaddress", ASN_IPADDRESS }, { "nsap", ASN_NSAP }, { "null", ASN_NULL }, { "object_id", ASN_OBJECT_ID }, { "octet_str", ASN_OCTET_STR }, { "opaque", ASN_OPAQUE }, #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES { "opaque_counter64", ASN_OPAQUE_COUNTER64 }, { "opaque_double", ASN_OPAQUE_DOUBLE }, { "opaque_float", ASN_OPAQUE_FLOAT }, { "opaque_i64", ASN_OPAQUE_I64 }, { "opaque_u64", ASN_OPAQUE_U64 }, #endif { "timeticks", ASN_TIMETICKS }, { "uinteger", ASN_GAUGE }, { "unsigned", ASN_UNSIGNED }, { NULL, 0 } }, * run; for(run = strings; run->key && strcasecmp(run->key, buf) < 0; ++run); if(run->key && strcasecmp(run->key, buf) == 0) type = run->value; else { config_perror("unknown type specified"); return; } } if (cp) copy_nword(cp, buf, sizeof(buf) - 1); else buf[0] = 0; thedata = SNMP_MALLOC_TYPEDEF(override_data); if (!thedata) { config_perror("memory allocation failure"); return; } thedata->type = type; switch (type) { case ASN_INTEGER: MALLOC_OR_DIE(sizeof(long)); *((long *) thedata->value) = strtol(buf, NULL, 0); break; case ASN_COUNTER: case ASN_TIMETICKS: case ASN_UNSIGNED: MALLOC_OR_DIE(sizeof(u_long)); *((u_long *) thedata->value) = strtoul(buf, NULL, 0); break; case ASN_OCTET_STR: case ASN_BIT_STR: if (buf[0] == '0' && buf[1] == 'x') { /* * hex */ thedata->value_len = hex_to_binary2((u_char *)(buf + 2), strlen(buf) - 2, (char **) &thedata->value); } else { thedata->value = strdup(buf); thedata->value_len = strlen(buf); } break; case ASN_OBJECT_ID: read_config_read_objid(buf, (oid **) & thedata->value, &thedata->value_len); break; case ASN_NULL: thedata->value_len = 0; break; default: SNMP_FREE(thedata); config_perror("illegal/unsupported type specified"); return; } if (!thedata->value && thedata->type != ASN_NULL) { config_perror("memory allocation failure"); free(thedata); return; } the_reg = SNMP_MALLOC_TYPEDEF(netsnmp_handler_registration); if (!the_reg) { config_perror("memory allocation failure"); free(thedata); return; } the_reg->handlerName = strdup(namebuf); the_reg->priority = 255; the_reg->modes = (readwrite) ? HANDLER_CAN_RWRITE : HANDLER_CAN_RONLY; the_reg->handler = netsnmp_create_handler("override", override_handler); the_reg->rootoid = snmp_duplicate_objid(oidbuf, oidbuf_len); the_reg->rootoid_len = oidbuf_len; if (!the_reg->rootoid || !the_reg->handler || !the_reg->handlerName) { if (the_reg->handler) SNMP_FREE(the_reg->handler->handler_name); SNMP_FREE(the_reg->handler); SNMP_FREE(the_reg->handlerName); SNMP_FREE(the_reg); config_perror("memory allocation failure"); free(thedata); return; } the_reg->handler->myvoid = thedata; if (netsnmp_register_instance(the_reg)) { config_perror("oid registration failed within the agent"); SNMP_FREE(thedata->value); free(thedata); return; } }
int main(int argc, char *argv[]) { netsnmp_session session, *ss; netsnmp_pdu *pdu = NULL, *response = NULL; int arg; size_t name_length = USM_OID_LEN; size_t name_length2 = USM_OID_LEN; int status; int exitval = 1; int rval; int command = 0; long longvar; size_t oldKu_len = SNMP_MAXBUF_SMALL, newKu_len = SNMP_MAXBUF_SMALL, oldkul_len = SNMP_MAXBUF_SMALL, oldkulpriv_len = SNMP_MAXBUF_SMALL, newkulpriv_len = SNMP_MAXBUF_SMALL, newkul_len = SNMP_MAXBUF_SMALL, keychange_len = SNMP_MAXBUF_SMALL, keychangepriv_len = SNMP_MAXBUF_SMALL; char *newpass = NULL, *oldpass = NULL; u_char oldKu[SNMP_MAXBUF_SMALL], newKu[SNMP_MAXBUF_SMALL], oldkul[SNMP_MAXBUF_SMALL], oldkulpriv[SNMP_MAXBUF_SMALL], newkulpriv[SNMP_MAXBUF_SMALL], newkul[SNMP_MAXBUF_SMALL], keychange[SNMP_MAXBUF_SMALL], keychangepriv[SNMP_MAXBUF_SMALL]; SOCK_STARTUP; authKeyChange = authKeyOid; privKeyChange = privKeyOid; /* * get the common command line arguments */ switch (arg = snmp_parse_args(argc, argv, &session, "C:", optProc)) { case NETSNMP_PARSE_ARGS_ERROR: goto out; case NETSNMP_PARSE_ARGS_SUCCESS_EXIT: exitval = 0; goto out; case NETSNMP_PARSE_ARGS_ERROR_USAGE: usage(); goto out; default: break; } if (arg >= argc) { fprintf(stderr, "Please specify an operation to perform.\n"); usage(); goto out; } /* * open an SNMP session */ /* * Note: this needs to obtain the engineID used below */ session.flags &= ~SNMP_FLAGS_DONT_PROBE; ss = snmp_open(&session); if (ss == NULL) { /* * diagnose snmp_open errors with the input netsnmp_session pointer */ snmp_sess_perror("snmpusm", &session); goto out; } /* * set usmUserEngineID from ss->contextEngineID * if not already set (via -CE) */ if (usmUserEngineID == NULL) { usmUserEngineID = ss->contextEngineID; usmUserEngineIDLen = ss->contextEngineIDLen; } /* * create PDU for SET request and add object names and values to request */ pdu = snmp_pdu_create(SNMP_MSG_SET); if (!pdu) { fprintf(stderr, "Failed to create request\n"); goto close_session; } if (strcmp(argv[arg], CMD_PASSWD_NAME) == 0) { /* * passwd: change a users password. * * XXX: Uses the auth type of the calling user, a MD5 user can't * change a SHA user's key. */ char *passwd_user; command = CMD_PASSWD; oldpass = argv[++arg]; newpass = argv[++arg]; passwd_user = argv[++arg]; if (doprivkey == 0 && doauthkey == 0) doprivkey = doauthkey = 1; if (newpass == NULL || strlen(newpass) < USM_LENGTH_P_MIN) { fprintf(stderr, "New passphrase must be greater than %d characters in length.\n", USM_LENGTH_P_MIN); goto close_session; } if (oldpass == NULL || strlen(oldpass) < USM_LENGTH_P_MIN) { fprintf(stderr, "Old passphrase must be greater than %d characters in length.\n", USM_LENGTH_P_MIN); goto close_session; } DEBUGMSGTL(("9:usm:passwd", "oldpass len %" NETSNMP_PRIz "d, newpass len %" NETSNMP_PRIz "d\n", strlen(oldpass), strlen(newpass))); /* * Change the user supplied on command line. */ if ((passwd_user != NULL) && (strlen(passwd_user) > 0)) { session.securityName = passwd_user; } else { /* * Use own key object if no user was supplied. */ authKeyChange = ownAuthKeyOid; privKeyChange = ownPrivKeyOid; } /* * do we have a securityName? If not, copy the default */ if (session.securityName == NULL) { session.securityName = strdup(netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_SECNAME)); } /* * the old Ku is in the session, but we need the new one */ if (session.securityAuthProto == NULL) { /* * get .conf set default */ const oid *def = get_default_authtype(&session.securityAuthProtoLen); session.securityAuthProto = snmp_duplicate_objid(def, session.securityAuthProtoLen); } if (session.securityAuthProto == NULL) { /* * assume MD5 */ #ifndef NETSNMP_DISABLE_MD5 session.securityAuthProtoLen = sizeof(usmHMACMD5AuthProtocol) / sizeof(oid); session.securityAuthProto = snmp_duplicate_objid(usmHMACMD5AuthProtocol, session.securityAuthProtoLen); #else session.securityAuthProtoLen = sizeof(usmHMACSHA1AuthProtocol) / sizeof(oid); session.securityAuthProto = snmp_duplicate_objid(usmHMACSHA1AuthProtocol, session.securityAuthProtoLen); #endif } if (uselocalizedkey && (strncmp(oldpass, "0x", 2) == 0)) { /* * use the localized key from the command line */ u_char *buf; size_t buf_len = SNMP_MAXBUF_SMALL; buf = (u_char *) malloc (buf_len * sizeof(u_char)); oldkul_len = 0; /* initialize the offset */ if (!snmp_hex_to_binary((u_char **) (&buf), &buf_len, &oldkul_len, 0, oldpass)) { snmp_perror(argv[0]); fprintf(stderr, "generating the old Kul from localized key failed\n"); goto close_session; } memcpy(oldkul, buf, oldkul_len); SNMP_FREE(buf); } else { /* * the old Ku is in the session, but we need the new one */ rval = generate_Ku(session.securityAuthProto, session.securityAuthProtoLen, (u_char *) oldpass, strlen(oldpass), oldKu, &oldKu_len); if (rval != SNMPERR_SUCCESS) { snmp_perror(argv[0]); fprintf(stderr, "generating the old Ku failed\n"); goto close_session; } /* * generate the two Kul's */ rval = generate_kul(session.securityAuthProto, session.securityAuthProtoLen, usmUserEngineID, usmUserEngineIDLen, oldKu, oldKu_len, oldkul, &oldkul_len); if (rval != SNMPERR_SUCCESS) { snmp_perror(argv[0]); fprintf(stderr, "generating the old Kul failed\n"); goto close_session; } DEBUGMSGTL(("9:usm:passwd", "oldkul len %" NETSNMP_PRIz "d\n", oldkul_len)); } if (uselocalizedkey && (strncmp(newpass, "0x", 2) == 0)) { /* * use the localized key from the command line */ u_char *buf; size_t buf_len = SNMP_MAXBUF_SMALL; buf = (u_char *) malloc (buf_len * sizeof(u_char)); newkul_len = 0; /* initialize the offset */ if (!snmp_hex_to_binary((u_char **) (&buf), &buf_len, &newkul_len, 0, newpass)) { snmp_perror(argv[0]); fprintf(stderr, "generating the new Kul from localized key failed\n"); goto close_session; } memcpy(newkul, buf, newkul_len); SNMP_FREE(buf); } else { rval = generate_Ku(session.securityAuthProto, session.securityAuthProtoLen, (u_char *) newpass, strlen(newpass), newKu, &newKu_len); if (rval != SNMPERR_SUCCESS) { snmp_perror(argv[0]); fprintf(stderr, "generating the new Ku failed\n"); goto close_session; } rval = generate_kul(session.securityAuthProto, session.securityAuthProtoLen, usmUserEngineID, usmUserEngineIDLen, newKu, newKu_len, newkul, &newkul_len); if (rval != SNMPERR_SUCCESS) { snmp_perror(argv[0]); fprintf(stderr, "generating the new Kul failed\n"); goto close_session; } DEBUGMSGTL(("9:usm:passwd", "newkul len %" NETSNMP_PRIz "d\n", newkul_len)); } /* * for encryption, we may need to truncate the key to the proper length * so we need two copies. For simplicity, we always just copy even if * they're the same lengths. */ if (doprivkey) { int privtype, properlength; u_char *okp = oldkulpriv, *nkp = newkulpriv; if (!session.securityPrivProto) { snmp_log(LOG_ERR, "no encryption type specified, which I need in order to know to change the key\n"); goto close_session; } privtype = sc_get_privtype(session.securityPrivProto, session.securityPrivProtoLen); properlength = sc_get_proper_priv_length_bytype(privtype); if (USM_CREATE_USER_PRIV_DES == privtype) properlength *= 2; /* ?? we store salt with key */ DEBUGMSGTL(("9:usm:passwd", "proper len %d\n", properlength)); oldkulpriv_len = oldkul_len; newkulpriv_len = newkul_len; memcpy(oldkulpriv, oldkul, oldkulpriv_len); memcpy(newkulpriv, newkul, newkulpriv_len); if (oldkulpriv_len > properlength) { oldkulpriv_len = newkulpriv_len = properlength; } else if (oldkulpriv_len < properlength) { rval = netsnmp_extend_kul(properlength, session.securityAuthProto, session.securityAuthProtoLen, privtype, usmUserEngineID, usmUserEngineIDLen, &okp, &oldkulpriv_len, sizeof(oldkulpriv)); rval = netsnmp_extend_kul(properlength, session.securityAuthProto, session.securityAuthProtoLen, privtype, usmUserEngineID, usmUserEngineIDLen, &nkp, &newkulpriv_len, sizeof(newkulpriv)); } } /* * create the keychange string */ if (doauthkey) { rval = encode_keychange(session.securityAuthProto, session.securityAuthProtoLen, oldkul, oldkul_len, newkul, newkul_len, keychange, &keychange_len); if (rval != SNMPERR_SUCCESS) { snmp_perror(argv[0]); fprintf(stderr, "encoding the keychange failed\n"); usage(); goto close_session; } } /* which is slightly different for encryption if lengths are different */ if (doprivkey) { DEBUGMSGTL(("9:usm:passwd:encode", "proper len %" NETSNMP_PRIz "d, old_len %" NETSNMP_PRIz "d, new_len %" NETSNMP_PRIz "d\n", oldkulpriv_len, oldkulpriv_len, newkulpriv_len)); rval = encode_keychange(session.securityAuthProto, session.securityAuthProtoLen, oldkulpriv, oldkulpriv_len, newkulpriv, newkulpriv_len, keychangepriv, &keychangepriv_len); DEBUGMSGTL(("9:usm:passwd:encode", "keychange len %" NETSNMP_PRIz "d\n", keychangepriv_len)); if (rval != SNMPERR_SUCCESS) { snmp_perror(argv[0]); fprintf(stderr, "encoding the keychange failed\n"); usage(); goto close_session; } } /* * add the keychange string to the outgoing packet */ if (doauthkey) { setup_oid(authKeyChange, &name_length, usmUserEngineID, usmUserEngineIDLen, session.securityName); snmp_pdu_add_variable(pdu, authKeyChange, name_length, ASN_OCTET_STR, keychange, keychange_len); } if (doprivkey) { setup_oid(privKeyChange, &name_length2, usmUserEngineID, usmUserEngineIDLen, session.securityName); snmp_pdu_add_variable(pdu, privKeyChange, name_length2, ASN_OCTET_STR, keychangepriv, keychangepriv_len); } } else if (strcmp(argv[arg], CMD_CREATE_NAME) == 0) { /* * create: create a user * * create USER [CLONEFROM] */ if (++arg >= argc) { fprintf(stderr, "You must specify the user name to create\n"); usage(); goto close_session; } command = CMD_CREATE; if (++arg < argc) { /* * clone the new user from an existing user * (and make them active immediately) */ setup_oid(usmUserStatus, &name_length, usmUserEngineID, usmUserEngineIDLen, argv[arg-1]); if (docreateandwait) { longvar = RS_CREATEANDWAIT; } else { longvar = RS_CREATEANDGO; } snmp_pdu_add_variable(pdu, usmUserStatus, name_length, ASN_INTEGER, (u_char *) & longvar, sizeof(longvar)); name_length = USM_OID_LEN; setup_oid(usmUserCloneFrom, &name_length, usmUserEngineID, usmUserEngineIDLen, argv[arg - 1]); setup_oid(usmUserSecurityName, &name_length2, usmUserEngineID, usmUserEngineIDLen, argv[arg]); snmp_pdu_add_variable(pdu, usmUserCloneFrom, name_length, ASN_OBJECT_ID, (u_char *) usmUserSecurityName, sizeof(oid) * name_length2); } else { /* * create a new (unauthenticated) user from scratch * The Net-SNMP agent won't allow such a user to be made active. */ setup_oid(usmUserStatus, &name_length, usmUserEngineID, usmUserEngineIDLen, argv[arg-1]); longvar = RS_CREATEANDWAIT; snmp_pdu_add_variable(pdu, usmUserStatus, name_length, ASN_INTEGER, (u_char *) & longvar, sizeof(longvar)); } } else if (strcmp(argv[arg], CMD_CLONEFROM_NAME) == 0) { /* * create: clone a user from another * * cloneFrom USER FROM */ if (++arg >= argc) { fprintf(stderr, "You must specify the user name to operate on\n"); usage(); goto close_session; } command = CMD_CLONEFROM; setup_oid(usmUserStatus, &name_length, usmUserEngineID, usmUserEngineIDLen, argv[arg]); longvar = RS_ACTIVE; snmp_pdu_add_variable(pdu, usmUserStatus, name_length, ASN_INTEGER, (u_char *) & longvar, sizeof(longvar)); name_length = USM_OID_LEN; setup_oid(usmUserCloneFrom, &name_length, usmUserEngineID, usmUserEngineIDLen, argv[arg]); if (++arg >= argc) { fprintf(stderr, "You must specify the user name to clone from\n"); usage(); goto close_session; } setup_oid(usmUserSecurityName, &name_length2, usmUserEngineID, usmUserEngineIDLen, argv[arg]); snmp_pdu_add_variable(pdu, usmUserCloneFrom, name_length, ASN_OBJECT_ID, (u_char *) usmUserSecurityName, sizeof(oid) * name_length2); } else if (strcmp(argv[arg], CMD_DELETE_NAME) == 0) { /* * delete: delete a user * * delete USER */ if (++arg >= argc) { fprintf(stderr, "You must specify the user name to delete\n"); goto close_session; } command = CMD_DELETE; setup_oid(usmUserStatus, &name_length, usmUserEngineID, usmUserEngineIDLen, argv[arg]); longvar = RS_DESTROY; snmp_pdu_add_variable(pdu, usmUserStatus, name_length, ASN_INTEGER, (u_char *) & longvar, sizeof(longvar)); } else if (strcmp(argv[arg], CMD_ACTIVATE_NAME) == 0) { /* * activate: activate a user * * activate USER */ if (++arg >= argc) { fprintf(stderr, "You must specify the user name to activate\n"); goto close_session; } command = CMD_ACTIVATE; setup_oid(usmUserStatus, &name_length, usmUserEngineID, usmUserEngineIDLen, argv[arg]); longvar = RS_ACTIVE; snmp_pdu_add_variable(pdu, usmUserStatus, name_length, ASN_INTEGER, (u_char *) & longvar, sizeof(longvar)); } else if (strcmp(argv[arg], CMD_DEACTIVATE_NAME) == 0) { /* * deactivate: deactivate a user * * deactivate USER */ if (++arg >= argc) { fprintf(stderr, "You must specify the user name to deactivate\n"); goto close_session; } command = CMD_DEACTIVATE; setup_oid(usmUserStatus, &name_length, usmUserEngineID, usmUserEngineIDLen, argv[arg]); longvar = RS_NOTINSERVICE; snmp_pdu_add_variable(pdu, usmUserStatus, name_length, ASN_INTEGER, (u_char *) & longvar, sizeof(longvar)); #if defined(HAVE_OPENSSL_DH_H) && defined(HAVE_LIBCRYPTO) } else if (strcmp(argv[arg], CMD_CHANGEKEY_NAME) == 0) { /* * change the key of a user if DH is available */ char *passwd_user; netsnmp_pdu *dhpdu, *dhresponse = NULL; netsnmp_variable_list *vars, *dhvar; command = CMD_CHANGEKEY; name_length = DH_USM_OID_LEN; name_length2 = DH_USM_OID_LEN; passwd_user = argv[++arg]; if (doprivkey == 0 && doauthkey == 0) doprivkey = doauthkey = 1; /* * Change the user supplied on command line. */ if ((passwd_user != NULL) && (strlen(passwd_user) > 0)) { session.securityName = passwd_user; } else { /* * Use own key object if no user was supplied. */ dhauthKeyChange = usmDHUserOwnAuthKeyChange; dhprivKeyChange = usmDHUserOwnPrivKeyChange; } /* * do we have a securityName? If not, copy the default */ if (session.securityName == NULL) { session.securityName = strdup(netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_SECNAME)); } /* fetch the needed diffie helman parameters */ dhpdu = snmp_pdu_create(SNMP_MSG_GET); if (!dhpdu) { fprintf(stderr, "Failed to create DH request\n"); goto close_session; } /* get the current DH parameters */ snmp_add_null_var(dhpdu, usmDHParameters, usmDHParameters_len); /* maybe the auth key public value */ if (doauthkey) { setup_oid(dhauthKeyChange, &name_length, usmUserEngineID, usmUserEngineIDLen, session.securityName); snmp_add_null_var(dhpdu, dhauthKeyChange, name_length); } /* maybe the priv key public value */ if (doprivkey) { setup_oid(dhprivKeyChange, &name_length2, usmUserEngineID, usmUserEngineIDLen, session.securityName); snmp_add_null_var(dhpdu, dhprivKeyChange, name_length2); } /* fetch the values */ status = snmp_synch_response(ss, dhpdu, &dhresponse); if (status != SNMPERR_SUCCESS || dhresponse == NULL || dhresponse->errstat != SNMP_ERR_NOERROR || dhresponse->variables->type != ASN_OCTET_STR) { snmp_sess_perror("snmpusm", ss); if (dhresponse && dhresponse->variables && dhresponse->variables->type != ASN_OCTET_STR) { fprintf(stderr, "Can't get diffie-helman exchange from the agent\n"); fprintf(stderr, " (maybe it doesn't support the SNMP-USM-DH-OBJECTS-MIB MIB)\n"); } exitval = 1; goto begone; } dhvar = dhresponse->variables; vars = dhvar->next_variable; /* complete the DH equation & print resulting keys */ if (doauthkey) { if (get_USM_DH_key(vars, dhvar, sc_get_properlength(ss->securityAuthProto, ss->securityAuthProtoLen), pdu, "auth", dhauthKeyChange, name_length) != SNMPERR_SUCCESS) goto begone; vars = vars->next_variable; } if (doprivkey) { size_t dhprivKeyLen = 0; int privtype = sc_get_privtype(ss->securityPrivProto, ss->securityPrivProtoLen); dhprivKeyLen = sc_get_proper_priv_length_bytype(privtype); if (USM_CREATE_USER_PRIV_DES == privtype) dhprivKeyLen *= 2; /* ?? we store salt with key */ if (get_USM_DH_key(vars, dhvar, dhprivKeyLen, pdu, "priv", dhprivKeyChange, name_length2) != SNMPERR_SUCCESS) goto begone; vars = vars->next_variable; } /* snmp_free_pdu(dhresponse); */ /* parts still in use somewhere */ #endif /* HAVE_OPENSSL_DH_H && HAVE_LIBCRYPTO */ } else { fprintf(stderr, "Unknown command\n"); usage(); goto close_session; } /* * add usmUserPublic if specified (via -Cp) */ if (usmUserPublic_val) { name_length = USM_OID_LEN; setup_oid(usmUserPublic, &name_length, usmUserEngineID, usmUserEngineIDLen, session.securityName); snmp_pdu_add_variable(pdu, usmUserPublic, name_length, ASN_OCTET_STR, usmUserPublic_val, strlen(usmUserPublic_val)); } /* * do the request */ status = snmp_synch_response(ss, pdu, &response); if (status == STAT_SUCCESS) { if (response) { if (response->errstat == SNMP_ERR_NOERROR) { fprintf(stdout, "%s\n", successNotes[command - 1]); } else { fprintf(stderr, "Error in packet.\nReason: %s\n", snmp_errstring(response->errstat)); if (response->errindex != 0) { int count; netsnmp_variable_list *vars; fprintf(stderr, "Failed object: "); for (count = 1, vars = response->variables; vars && count != response->errindex; vars = vars->next_variable, count++) /*EMPTY*/; if (vars) fprint_objid(stderr, vars->name, vars->name_length); fprintf(stderr, "\n"); } exitval = 2; } } } else if (status == STAT_TIMEOUT) { fprintf(stderr, "Timeout: No Response from %s\n", session.peername); exitval = 1; } else { /* status == STAT_ERROR */ snmp_sess_perror("snmpset", ss); exitval = 1; } exitval = 0; #if defined(HAVE_OPENSSL_DH_H) && defined(HAVE_LIBCRYPTO) begone: #endif /* HAVE_OPENSSL_DH_H && HAVE_LIBCRYPTO */ if (response) snmp_free_pdu(response); close_session: snmp_close(ss); out: SOCK_CLEANUP; return exitval; }
/*! \fn void *snmp_host_init(int host_id, char *hostname, int snmp_version, * char *snmp_community, char *snmp_username, char *snmp_password, * char *snmp_auth_protocol, char *snmp_priv_passphrase, char *snmp_priv_protocol, * char *snmp_context, int snmp_port, int snmp_timeout) * \brief initializes an snmp_session object for a Spine host * * This function will initialize NET-SNMP or UCD-SNMP for the Spine host * in question. * */ void *snmp_host_init(int host_id, char *hostname, int snmp_version, char *snmp_community, char *snmp_username, char *snmp_password, char *snmp_auth_protocol, char *snmp_priv_passphrase, char *snmp_priv_protocol, char *snmp_context, int snmp_port, int snmp_timeout) { void *sessp = NULL; struct snmp_session session; char hostnameport[BUFSIZE]; /* initialize SNMP */ snmp_sess_init(&session); #ifdef USE_NET_SNMP /* Prevent update of the snmpapp.conf file */ #ifdef NETSNMP_DS_LIB_DONT_PERSIST_STATE netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PERSIST_STATE, 1); #endif /* Prevent update of the snmpapp.conf file */ #ifdef NETSNMP_DS_LIB_DISABLE_PERSISTENT_LOAD netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DISABLE_PERSISTENT_LOAD, 1); #endif #ifdef NETSNMP_DS_LIB_DONT_PRINT_UNITS netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PRINT_UNITS, 1); #endif netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT, 1); netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT, 1); netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_BARE_VALUE, 1); netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NUMERIC_TIMETICKS, 1); #else ds_set_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT, 1); ds_set_boolean(DS_LIBRARY_ID, DS_LIB_PRINT_BARE_VALUE, 1); ds_set_boolean(DS_LIBRARY_ID, DS_LIB_NUMERIC_TIMETICKS, 1); #endif /* verify snmp version is accurate */ if (snmp_version == 2) { session.version = SNMP_VERSION_2c; session.securityModel = SNMP_SEC_MODEL_SNMPv2c; }else if (snmp_version == 1) { session.version = SNMP_VERSION_1; session.securityModel = SNMP_SEC_MODEL_SNMPv1; }else if (snmp_version == 3) { session.version = SNMP_VERSION_3; session.securityModel = USM_SEC_MODEL_NUMBER; }else { SPINE_LOG(("Host[%i] ERROR: SNMP Version Error for Host '%s'\n", host_id, hostname)); return 0; } snprintf(hostnameport, BUFSIZE, "%s:%i", hostname, snmp_port); session.peername = hostnameport; session.retries = 3; session.remote_port = snmp_port; session.timeout = (snmp_timeout * 1000); /* net-snmp likes microseconds */ if ((snmp_version == 2) || (snmp_version == 1)) { session.community = snmp_community; session.community_len = strlen(snmp_community); }else { /* set the SNMPv3 user name */ session.securityName = snmp_username; session.securityNameLen = strlen(session.securityName); session.contextName = snmp_context; session.contextNameLen = strlen(session.contextName); session.securityAuthKeyLen = USM_AUTH_KU_LEN; /* set the authentication protocol */ if (strcmp(snmp_auth_protocol, "MD5") == 0) { /* set the authentication method to MD5 */ session.securityAuthProto = snmp_duplicate_objid(usmHMACMD5AuthProtocol, OIDSIZE(usmHMACMD5AuthProtocol)); session.securityAuthProtoLen = OIDSIZE(usmHMACMD5AuthProtocol); }else{ /* set the authentication method to SHA1 */ session.securityAuthProto = snmp_duplicate_objid(usmHMACSHA1AuthProtocol, OIDSIZE(usmHMACSHA1AuthProtocol)); session.securityAuthProtoLen = OIDSIZE(usmHMACSHA1AuthProtocol); } /* set the authentication key to the hashed version. The password must me at least 8 char */ if (generate_Ku(session.securityAuthProto, session.securityAuthProtoLen, (u_char *) snmp_password, strlen(snmp_password), session.securityAuthKey, &(session.securityAuthKeyLen)) != SNMPERR_SUCCESS) { SPINE_LOG(("SNMP: Error generating SNMPv3 Ku from authentication pass phrase.")); } /* set the privacy protocol to none */ if (strcmp(snmp_priv_protocol, "[None]") == 0) { session.securityPrivProto = snmp_duplicate_objid(usmNoPrivProtocol, OIDSIZE(usmNoPrivProtocol)); session.securityPrivProtoLen = OIDSIZE(usmNoPrivProtocol); session.securityPrivKeyLen = USM_PRIV_KU_LEN; /* set the security level to authenticate, but not encrypted */ session.securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV; }else{ if (strcmp(snmp_priv_protocol, "DES") == 0) { session.securityPrivProto = snmp_duplicate_objid(usmDESPrivProtocol, OIDSIZE(usmDESPrivProtocol)); session.securityPrivProtoLen = OIDSIZE(usmDESPrivProtocol); session.securityPrivKeyLen = USM_PRIV_KU_LEN; /* set the security level to authenticate, and encrypted */ session.securityLevel = SNMP_SEC_LEVEL_AUTHPRIV; }else{ session.securityPrivProto = snmp_duplicate_objid(usmAES128PrivProtocol, OIDSIZE(usmAES128PrivProtocol)); session.securityPrivProtoLen = OIDSIZE(usmAES128PrivProtocol); session.securityPrivKeyLen = USM_PRIV_KU_LEN; /* set the security level to authenticate, and encrypted */ session.securityLevel = SNMP_SEC_LEVEL_AUTHPRIV; } /* set the privacy key to the hashed version. */ if (generate_Ku(session.securityAuthProto, session.securityAuthProtoLen, (u_char *) snmp_priv_passphrase, strlen(snmp_priv_passphrase), session.securityPrivKey, &(session.securityPrivKeyLen)) != SNMPERR_SUCCESS) { SPINE_LOG(("SNMP: Error generating SNMPv3 Ku from privacy pass phrase.")); } } } /* open SNMP Session */ thread_mutex_lock(LOCK_SNMP); sessp = snmp_sess_open(&session); thread_mutex_unlock(LOCK_SNMP); if (!sessp) { SPINE_LOG(("ERROR: Problem initializing SNMP session '%s'\n", hostname)); } return sessp; }
netsnmp_pdu* convert_v2pdu_to_v1( netsnmp_pdu* template_v2pdu ) { netsnmp_pdu *template_v1pdu; netsnmp_variable_list *first_vb, *vblist; netsnmp_variable_list *var; /* * Make a copy of the v2 Trap PDU * before starting to convert this * into a v1 Trap PDU. */ template_v1pdu = snmp_clone_pdu( template_v2pdu); if (!template_v1pdu) { snmp_log(LOG_WARNING, "send_trap: failed to copy v1 template PDU\n"); return NULL; } template_v1pdu->command = SNMP_MSG_TRAP; first_vb = template_v1pdu->variables; vblist = template_v1pdu->variables; /* * The first varbind should be the system uptime. */ if (!vblist || snmp_oid_compare(vblist->name, vblist->name_length, sysuptime_oid, sysuptime_oid_len)) { snmp_log(LOG_WARNING, "send_trap: no v2 sysUptime varbind to set from\n"); snmp_free_pdu(template_v1pdu); return NULL; } template_v1pdu->time = *vblist->val.integer; vblist = vblist->next_variable; /* * The second varbind should be the snmpTrapOID. */ if (!vblist || snmp_oid_compare(vblist->name, vblist->name_length, snmptrap_oid, snmptrap_oid_len)) { snmp_log(LOG_WARNING, "send_trap: no v2 trapOID varbind to set from\n"); snmp_free_pdu(template_v1pdu); return NULL; } /* * Check the v2 varbind list for any varbinds * that are not valid in an SNMPv1 trap. * This basically means Counter64 values. * * RFC 2089 said to omit such varbinds from the list. * RFC 2576/3584 say to drop the trap completely. */ for (var = vblist->next_variable; var; var = var->next_variable) { if ( var->type == ASN_COUNTER64 ) { snmp_log(LOG_WARNING, "send_trap: v1 traps can't carry Counter64 varbinds\n"); snmp_free_pdu(template_v1pdu); return NULL; } } /* * Set the generic & specific trap types, * and the enterprise field from the v2 varbind list. * If there's an agentIPAddress varbind, set the agent_addr too */ if (!snmp_oid_compare(vblist->val.objid, OID_LENGTH(trap_prefix), trap_prefix, OID_LENGTH(trap_prefix))) { /* * For 'standard' traps, extract the generic trap type * from the snmpTrapOID value, and take the enterprise * value from the 'snmpEnterprise' varbind. */ template_v1pdu->trap_type = vblist->val.objid[OID_LENGTH(trap_prefix)] - 1; template_v1pdu->specific_type = 0; var = find_varbind_in_list( vblist, snmptrapenterprise_oid, snmptrapenterprise_oid_len); if (var) { template_v1pdu->enterprise_length = var->val_len/sizeof(oid); template_v1pdu->enterprise = snmp_duplicate_objid(var->val.objid, template_v1pdu->enterprise_length); } else { template_v1pdu->enterprise = NULL; template_v1pdu->enterprise_length = 0; /* XXX ??? */ } } else { /* * For enterprise-specific traps, split the snmpTrapOID value * into enterprise and specific trap */ size_t len = vblist->val_len / sizeof(oid); if ( len <= 2 ) { snmp_log(LOG_WARNING, "send_trap: v2 trapOID too short (%d)\n", (int)len); snmp_free_pdu(template_v1pdu); return NULL; } template_v1pdu->trap_type = SNMP_TRAP_ENTERPRISESPECIFIC; template_v1pdu->specific_type = vblist->val.objid[len - 1]; len--; if (vblist->val.objid[len-1] == 0) len--; SNMP_FREE(template_v1pdu->enterprise); template_v1pdu->enterprise = snmp_duplicate_objid(vblist->val.objid, len); template_v1pdu->enterprise_length = len; } var = find_varbind_in_list( vblist, agentaddr_oid, agentaddr_oid_len); if (var) { memcpy(template_v1pdu->agent_addr, var->val.string, 4); } /* * The remainder of the v2 varbind list is kept * as the v2 varbind list. Update the PDU and * free the two redundant varbinds. */ template_v1pdu->variables = vblist->next_variable; vblist->next_variable = NULL; snmp_free_varbind( first_vb ); return template_v1pdu; }
int netsnmp_table_row_register(netsnmp_handler_registration *reginfo, netsnmp_table_registration_info *tabreg, void *row, netsnmp_variable_list *index) { netsnmp_handler_registration *reg2; netsnmp_mib_handler *handler; oid row_oid[MAX_OID_LEN]; size_t row_oid_len, len; char tmp[SNMP_MAXBUF_MEDIUM]; if ((NULL == reginfo) || (NULL == reginfo->handler) || (NULL == tabreg)) { snmp_log(LOG_ERR, "bad param in netsnmp_table_row_register\n"); netsnmp_handler_registration_free(reginfo); return SNMPERR_GENERR; } /* * The first table_row invoked for a particular table should * register the full table as well, with a default handler to * process requests for non-existent (or incomplete) rows. * * Subsequent table_row registrations attempting to set up * this default handler would fail - preferably silently! */ snprintf(tmp, sizeof(tmp), "%s_table", reginfo->handlerName); reg2 = netsnmp_create_handler_registration( tmp, _table_row_default_handler, reginfo->rootoid, reginfo->rootoid_len, reginfo->modes); netsnmp_register_table(reg2, tabreg); /* Ignore return value */ /* * Adjust the OID being registered, to take account * of the indexes and column range provided.... */ row_oid_len = reginfo->rootoid_len; memcpy( row_oid, (u_char *) reginfo->rootoid, row_oid_len * sizeof(oid)); row_oid[row_oid_len++] = 1; /* tableEntry */ row_oid[row_oid_len++] = tabreg->min_column; reginfo->range_ubound = tabreg->max_column; reginfo->range_subid = row_oid_len-1; build_oid_noalloc(&row_oid[row_oid_len], MAX_OID_LEN-row_oid_len, &len, NULL, 0, index); row_oid_len += len; free(reginfo->rootoid); reginfo->rootoid = snmp_duplicate_objid(row_oid, row_oid_len); reginfo->rootoid_len = row_oid_len; /* * ... insert a minimal handler ... */ handler = netsnmp_table_row_handler_get(row); if (!handler || (netsnmp_inject_handler(reginfo, handler) != SNMPERR_SUCCESS)) { snmp_log(LOG_ERR, "could not create table row handler\n"); netsnmp_handler_free(handler); netsnmp_handler_registration_free(reginfo); return SNMP_ERR_GENERR; } /* * ... and register the row */ return netsnmp_register_handler(reginfo); }
int main(int argc, char *argv[]) { netsnmp_session session, *ss; netsnmp_pdu *pdu = NULL, *response = NULL; #ifdef notused netsnmp_variable_list *vars; #endif int arg; #ifdef notused int count; int current_name = 0; int current_type = 0; int current_value = 0; char *names[128]; char types[128]; char *values[128]; oid name[MAX_OID_LEN]; #endif size_t name_length = USM_OID_LEN; size_t name_length2 = USM_OID_LEN; int status; int exitval = 0; int rval; int command = 0; long longvar; size_t oldKu_len = SNMP_MAXBUF_SMALL, newKu_len = SNMP_MAXBUF_SMALL, oldkul_len = SNMP_MAXBUF_SMALL, newkul_len = SNMP_MAXBUF_SMALL, keychange_len = SNMP_MAXBUF_SMALL; char *newpass = NULL, *oldpass = NULL; u_char oldKu[SNMP_MAXBUF_SMALL], newKu[SNMP_MAXBUF_SMALL], oldkul[SNMP_MAXBUF_SMALL], newkul[SNMP_MAXBUF_SMALL], keychange[SNMP_MAXBUF_SMALL]; authKeyChange = authKeyOid; privKeyChange = privKeyOid; /* * get the common command line arguments */ switch (arg = snmp_parse_args(argc, argv, &session, "C:", optProc)) { case -2: exit(0); case -1: usage(); exit(1); default: break; } SOCK_STARTUP; /* * open an SNMP session */ /* * Note: this wil obtain the engineID needed below */ ss = snmp_open(&session); if (ss == NULL) { /* * diagnose snmp_open errors with the input netsnmp_session pointer */ snmp_sess_perror("snmpusm", &session); exit(1); } /* * create PDU for SET request and add object names and values to request */ pdu = snmp_pdu_create(SNMP_MSG_SET); if (arg >= argc) { fprintf(stderr, "Please specify a operation to perform.\n"); usage(); exit(1); } if (strcmp(argv[arg], CMD_PASSWD_NAME) == 0) { /* * passwd: change a users password. * * XXX: Uses the auth type of the calling user, a MD5 user can't * change a SHA user's key. */ command = CMD_PASSWD; oldpass = argv[++arg]; newpass = argv[++arg]; if (doprivkey == 0 && doauthkey == 0) doprivkey = doauthkey = 1; if (newpass == NULL || strlen(newpass) < USM_LENGTH_P_MIN) { fprintf(stderr, "New passphrase must be greater than %d characters in length.\n", USM_LENGTH_P_MIN); exit(1); } if (oldpass == NULL || strlen(oldpass) < USM_LENGTH_P_MIN) { fprintf(stderr, "Old passphrase must be greater than %d characters in length.\n", USM_LENGTH_P_MIN); exit(1); } /* * do we have a securityName? If not, copy the default */ if (session.securityName == NULL) { session.securityName = strdup(netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_SECNAME)); } /* * the old Ku is in the session, but we need the new one */ if (session.securityAuthProto == NULL) { /* * get .conf set default */ const oid *def = get_default_authtype(&session.securityAuthProtoLen); session.securityAuthProto = snmp_duplicate_objid(def, session.securityAuthProtoLen); } if (session.securityAuthProto == NULL) { /* * assume MD5 */ session.securityAuthProtoLen = sizeof(usmHMACMD5AuthProtocol) / sizeof(oid); session.securityAuthProto = snmp_duplicate_objid(usmHMACMD5AuthProtocol, session.securityAuthProtoLen); } rval = generate_Ku(session.securityAuthProto, session.securityAuthProtoLen, (u_char *) newpass, strlen(newpass), newKu, &newKu_len); if (rval != SNMPERR_SUCCESS) { snmp_perror(argv[0]); fprintf(stderr, "generating the old Ku failed\n"); exit(1); } /* * the old Ku is in the session, but we need the new one */ rval = generate_Ku(session.securityAuthProto, session.securityAuthProtoLen, (u_char *) oldpass, strlen(oldpass), oldKu, &oldKu_len); if (rval != SNMPERR_SUCCESS) { snmp_perror(argv[0]); fprintf(stderr, "generating the new Ku failed\n"); exit(1); } /* * generate the two Kul's */ rval = generate_kul(session.securityAuthProto, session.securityAuthProtoLen, ss->contextEngineID, ss->contextEngineIDLen, oldKu, oldKu_len, oldkul, &oldkul_len); if (rval != SNMPERR_SUCCESS) { snmp_perror(argv[0]); fprintf(stderr, "generating the old Kul failed\n"); exit(1); } rval = generate_kul(session.securityAuthProto, session.securityAuthProtoLen, ss->contextEngineID, ss->contextEngineIDLen, newKu, newKu_len, newkul, &newkul_len); if (rval != SNMPERR_SUCCESS) { snmp_perror(argv[0]); fprintf(stderr, "generating the new Kul failed\n"); exit(1); } /* * create the keychange string */ rval = encode_keychange(session.securityAuthProto, session.securityAuthProtoLen, oldkul, oldkul_len, newkul, newkul_len, keychange, &keychange_len); if (rval != SNMPERR_SUCCESS) { snmp_perror(argv[0]); fprintf(stderr, "encoding the keychange failed\n"); usage(); exit(1); } /* * add the keychange string to the outgoing packet */ if (doauthkey) { setup_oid(authKeyChange, &name_length, ss->contextEngineID, ss->contextEngineIDLen, session.securityName); snmp_pdu_add_variable(pdu, authKeyChange, name_length, ASN_OCTET_STR, keychange, keychange_len); } if (doprivkey) { setup_oid(privKeyChange, &name_length, ss->contextEngineID, ss->contextEngineIDLen, session.securityName); snmp_pdu_add_variable(pdu, privKeyChange, name_length, ASN_OCTET_STR, keychange, keychange_len); } } else if (strcmp(argv[arg], CMD_CREATE_NAME) == 0) { /* * create: create a user * * create USER [CLONEFROM] */ if (++arg >= argc) { fprintf(stderr, "You must specify the user name to create\n"); usage(); exit(1); } command = CMD_CREATE; if (++arg < argc) { /* * clone the new user from an existing user * (and make them active immediately) */ setup_oid(usmUserStatus, &name_length, ss->contextEngineID, ss->contextEngineIDLen, argv[arg-1]); longvar = RS_CREATEANDGO; snmp_pdu_add_variable(pdu, usmUserStatus, name_length, ASN_INTEGER, (u_char *) & longvar, sizeof(longvar)); setup_oid(usmUserCloneFrom, &name_length, ss->contextEngineID, ss->contextEngineIDLen, argv[arg - 1]); setup_oid(usmUserSecurityName, &name_length2, ss->contextEngineID, ss->contextEngineIDLen, argv[arg]); snmp_pdu_add_variable(pdu, usmUserCloneFrom, name_length, ASN_OBJECT_ID, (u_char *) usmUserSecurityName, sizeof(oid) * name_length2); } else { /* * create a new (unauthenticated) user from scratch * The Net-SNMP agent won't allow such a user to be made active. */ setup_oid(usmUserStatus, &name_length, ss->contextEngineID, ss->contextEngineIDLen, argv[arg-1]); longvar = RS_CREATEANDWAIT; snmp_pdu_add_variable(pdu, usmUserStatus, name_length, ASN_INTEGER, (u_char *) & longvar, sizeof(longvar)); } } else if (strcmp(argv[arg], CMD_CLONEFROM_NAME) == 0) { /* * create: clone a user from another * * cloneFrom USER FROM */ if (++arg >= argc) { fprintf(stderr, "You must specify the user name to operate on\n"); usage(); exit(1); } command = CMD_CLONEFROM; setup_oid(usmUserStatus, &name_length, ss->contextEngineID, ss->contextEngineIDLen, argv[arg]); longvar = RS_ACTIVE; snmp_pdu_add_variable(pdu, usmUserStatus, name_length, ASN_INTEGER, (u_char *) & longvar, sizeof(longvar)); setup_oid(usmUserCloneFrom, &name_length, ss->contextEngineID, ss->contextEngineIDLen, argv[arg]); if (++arg >= argc) { fprintf(stderr, "You must specify the user name to clone from\n"); usage(); exit(1); } setup_oid(usmUserSecurityName, &name_length2, ss->contextEngineID, ss->contextEngineIDLen, argv[arg]); snmp_pdu_add_variable(pdu, usmUserCloneFrom, name_length, ASN_OBJECT_ID, (u_char *) usmUserSecurityName, sizeof(oid) * name_length2); } else if (strcmp(argv[arg], CMD_DELETE_NAME) == 0) { /* * delete: delete a user * * delete USER */ if (++arg >= argc) { fprintf(stderr, "You must specify the user name to delete\n"); exit(1); } command = CMD_DELETE; setup_oid(usmUserStatus, &name_length, ss->contextEngineID, ss->contextEngineIDLen, argv[arg]); longvar = RS_DESTROY; snmp_pdu_add_variable(pdu, usmUserStatus, name_length, ASN_INTEGER, (u_char *) & longvar, sizeof(longvar)); } else { fprintf(stderr, "Unknown command\n"); usage(); exit(1); } /* * do the request */ status = snmp_synch_response(ss, pdu, &response); if (status == STAT_SUCCESS) { if (response) { if (response->errstat == SNMP_ERR_NOERROR) { fprintf(stderr, "%s\n", successNotes[command - 1]); } else { fprintf(stderr, "Error in packet.\nReason: %s\n", snmp_errstring(response->errstat)); if (response->errindex != 0) { int count; netsnmp_variable_list *vars; fprintf(stderr, "Failed object: "); for (count = 1, vars = response->variables; vars && count != response->errindex; vars = vars->next_variable, count++) /*EMPTY*/; if (vars) fprint_objid(stderr, vars->name, vars->name_length); fprintf(stderr, "\n"); } exitval = 2; } } } else if (status == STAT_TIMEOUT) { fprintf(stderr, "Timeout: No Response from %s\n", session.peername); exitval = 1; } else { /* status == STAT_ERROR */ snmp_sess_perror("snmpset", ss); exitval = 1; } if (response) snmp_free_pdu(response); snmp_close(ss); SOCK_CLEANUP; return exitval; }
/* * Register a new trap-specific traphandler */ netsnmp_trapd_handler * netsnmp_add_traphandler(Netsnmp_Trap_Handler* handler, oid *trapOid, int trapOidLen ) { netsnmp_trapd_handler *traph, *traph2; if ( !handler ) return NULL; traph = SNMP_MALLOC_TYPEDEF(netsnmp_trapd_handler); if ( !traph ) return NULL; /* * Populate this new handler with the trap information * (NB: the OID fields were not used in the default/global lists) */ traph->authtypes = TRAP_AUTH_ALL; /* callers will likely change this */ traph->handler = handler; traph->trapoid_len = trapOidLen; traph->trapoid = snmp_duplicate_objid(trapOid, trapOidLen); /* * Now try to find the appropriate place in the trap-specific * list for this particular trap OID. If there's a matching OID * already, then find it. Otherwise find the one that follows. * If we run out of entried, the new one should be tacked onto the end. */ for (traph2 = netsnmp_specific_traphandlers; traph2; traph2 = traph2->nextt) { /* XXX - check this! */ if (snmp_oid_compare(traph2->trapoid, traph2->trapoid_len, trapOid, trapOidLen) <= 0) break; } if (traph2) { /* * OK - We've either got an exact match, or we've found the * entry *after* where the new one should go. */ if (!snmp_oid_compare(traph->trapoid, traph->trapoid_len, traph2->trapoid, traph2->trapoid_len)) { /* * Exact match, so find the end of the *handler* list * and tack on this new entry... */ while (traph2->nexth) traph2 = traph2->nexth; traph2->nexth = traph; traph->nextt = traph2->nextt; /* Might as well... */ traph->prevt = traph2->prevt; } else { /* * .. or the following entry, so insert the new one before it. */ traph->prevt = traph2->prevt; if (traph2->prevt) traph2->prevt->nextt = traph; else netsnmp_specific_traphandlers = traph; traph2->prevt = traph; traph->nextt = traph2; } } else { /* * If we've run out of entries without finding a suitable spot, * the new one should be tacked onto the end..... */ if (netsnmp_specific_traphandlers) { traph2 = netsnmp_specific_traphandlers; while (traph2->nextt) traph2 = traph2->nextt; traph2->nextt = traph; traph->prevt = traph2; } else { /* * .... unless this is the very first entry, of course! */ netsnmp_specific_traphandlers = traph; } } return traph; }
int mte_add_object_to_table(const char *owner, const char *objname, oid * oidname, size_t oidname_len, int iswild) { struct header_complex_index *hcptr = mteObjectsTableStorage, *lastnode; static struct mteObjectsTable_data *StorageNew; /* * malloc initial struct */ StorageNew = SNMP_MALLOC_STRUCT(mteObjectsTable_data); if (StorageNew == NULL) return SNMP_ERR_GENERR; StorageNew->mteOwner = netsnmp_strdup_and_null(owner, strlen(owner)); StorageNew->mteOwnerLen = strlen(owner); StorageNew->mteObjectsName = netsnmp_strdup_and_null(objname, strlen(objname)); StorageNew->mteObjectsNameLen = strlen(objname); /* * find the next number */ /* * get to start of objects list */ while (hcptr && (strcmp(((struct mteObjectsTable_data *) hcptr->data)->mteOwner, owner) != 0 || strcmp(((struct mteObjectsTable_data *) hcptr->data)-> mteObjectsName, objname) != 0)) hcptr = hcptr->next; if (hcptr) { /* * an object existed. Find the first one past and increment * the previous number */ lastnode = hcptr; while (hcptr && strcmp(((struct mteObjectsTable_data *) hcptr->data)-> mteOwner, owner) == 0 && strcmp(((struct mteObjectsTable_data *) hcptr->data)-> mteObjectsName, objname) == 0) { lastnode = hcptr; hcptr = hcptr->next; } StorageNew->mteObjectsIndex = ((struct mteObjectsTable_data *) lastnode->data)-> mteObjectsIndex + 1; } else { StorageNew->mteObjectsIndex = 1; } /* * XXX: fill in default row values here into StorageNew */ StorageNew->mteObjectsID = snmp_duplicate_objid(oidname, oidname_len); StorageNew->mteObjectsIDLen = oidname_len; if (iswild) StorageNew->mteObjectsIDWildcard = MTEOBJECTSIDWILDCARD_TRUE; else StorageNew->mteObjectsIDWildcard = MTEOBJECTSIDWILDCARD_FALSE; StorageNew->mteObjectsEntryStatus = RS_ACTIVE; StorageNew->storagetype = ST_READONLY; return mteObjectsTable_add(StorageNew); }
#ifndef DISABLE_DES if (!strcmp(priv_proto, "DES")) { session.securityPrivProto = snmp_duplicate_objid(usmDESPrivProtocol, USM_PRIV_PROTO_DES_LEN); session.securityPrivProtoLen = USM_PRIV_PROTO_DES_LEN; } else #endif if (!strncmp(priv_proto, "AES", 3)) { session.securityPrivProto = snmp_duplicate_objid(usmAESPrivProtocol, USM_PRIV_PROTO_AES_LEN); session.securityPrivProtoLen = USM_PRIV_PROTO_AES_LEN; } else if (!strcmp(priv_proto, "DEFAULT")) { const oid *p = get_default_privtype(&session.securityPrivProtoLen); session.securityPrivProto = snmp_duplicate_objid(p, session.securityPrivProtoLen); } else { if (verbose) printf("error:snmp_new_v3_session:Unsupported privacy protocol(%s)\n", priv_proto); goto end; }
#ifndef DISABLE_MD5 if (!strcmp(auth_proto, "MD5")) { session.securityAuthProto = snmp_duplicate_objid(usmHMACMD5AuthProtocol, USM_AUTH_PROTO_MD5_LEN); session.securityAuthProtoLen = USM_AUTH_PROTO_MD5_LEN; } else #endif if (!strcmp(auth_proto, "SHA")) { session.securityAuthProto = snmp_duplicate_objid(usmHMACSHA1AuthProtocol, USM_AUTH_PROTO_SHA_LEN); session.securityAuthProtoLen = USM_AUTH_PROTO_SHA_LEN; } else if (!strcmp(auth_proto, "DEFAULT")) { const oid* a = get_default_authtype(&session.securityAuthProtoLen); session.securityAuthProto = snmp_duplicate_objid(a, session.securityAuthProtoLen); } else { if (verbose) printf("error:snmp_new_v3_session:Unsupported authentication protocol(%s)\n", auth_proto); goto end; }