c++ - net-snmp 没有正确更改 auth 和 priv 协议(protocol)

标签 c++ c net-snmp

我在 Linux 下的 c++ 程序中使用 net-snmp 库(版本 5.7.1)。我有一个 Web 前端,用户可以在其中选择 SNMP 版本并进行配置。 SNMPv1 和 SNMPv2 工作正常,但我在使用 SNMPv3 时遇到了一些问题。

这是前端的图片:Screenshot of Webinterface (抱歉没有在这里直接上传,但我至少需要 10 个声望才能做到这一点)

当我启动 c++ 后端并正确输入所有需要的 SNMPv3 凭据时,一切正常并且可以访问设备。例如,如果我将 Auth Protocol 从 MD5 更改为 SHA,但将其余凭据保持不变,我预计该设备将无法再访问。实际上,它仍然可以访问。重新启动后端后,设备(如预期)无法再使用相同的设置访问。

发现这个问题后,我进行了一些测试。对于测试,我使用了不同的用户和不同的设置。它们使用不同供应商的三种不同设备运行,我每次都得到相同的结果。所以它不可能是设备相关的问题。结果可以在这里看到:Test results

测试后我的结论是,net-snmp 似乎为一个用户名缓存了选定的 auth 和 priv 协议(protocol)。这在测试 2 中可以看出非常好。我第一次使用具有特定协议(protocol)的用户名时,我得到了预期的结果。更改协议(protocol)后 预期会有不同的结果,但我仍然得到与以前相同的结果。

最后一些信息是如何进行 SNMP 调用的:

  • 有一个名为SNMPWrapper 的类,它处理整个 SNMP 通信
  • 在构造函数中,我调用 init_snmp() 来初始化 net-snmp
  • 从外部我只能调用get()set()walk()。每次调用其中一个方法时,都会创建一个新的 SNMP session (首先我使用 snmp_sess_init() 创建一个新 session ,然后设置所需的东西,最后我用 snmp_sess_open()
  • 发出请求并收到答复后,我使用 snmp_sess_close()
  • 关闭 session

问题:在更改协议(protocol)之前,我是否必须进行任何其他清理才能使其正常工作?

编辑:我添加了一些代码,显示了所描述的行为

int main(int argc, char** argv) {
struct snmp_session session, session1, *ss, *ss1;
struct snmp_pdu *pdu, *pdu1;
struct snmp_pdu *response, *response1;

oid anOID[MAX_OID_LEN];
size_t anOID_len = MAX_OID_LEN;

struct variable_list *vars;
int status, status1;

init_snmp("snmpapp");

const char* user = "md5";
string authpw = "123123123";
string privpw = "";
string ipString = "192.168.15.32";

char ip[16];
memset(&ip, 0, sizeof (ip));
ipString.copy(ip, sizeof (ip) - 1, 0);

/*
 * First request: AuthProto is MD5, no PrivProto is used. The snmp-get
 * request is successful
 */
snmp_sess_init(&session); /* set up defaults */
session.peername = ip;
session.version = SNMP_VERSION_3;

/* set the SNMPv3 user name */
session.securityName = strdup(user);
session.securityNameLen = strlen(session.securityName);

// set the authentication method to MD5     
session.securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV;

session.securityAuthProto = usmHMACMD5AuthProtocol;
session.securityAuthProtoLen = USM_AUTH_PROTO_MD5_LEN;
session.securityAuthKeyLen = USM_AUTH_KU_LEN;;

if (generate_Ku(session.securityAuthProto,
        session.securityAuthProtoLen,
        (u_char *) authpw.c_str(), strlen(authpw.c_str()),
        session.securityAuthKey,
        &session.securityAuthKeyLen) != SNMPERR_SUCCESS) {
    //if code reaches here, the creation of the security key was not successful

}

cout << "SecurityAuthProto - session: " << session.securityAuthProto[9] << " / SecurityAuthKey - session: " << session.securityAuthKey << endl;

ss = snmp_open(&session); /* establish the session */

if (!ss) {
    cout << "Couldn't open session1 correctly";
    exit(2);
}

cout << "SecurityAuthProto - ss: " << ss->securityAuthProto[9] << " / SecurityAuthKey - ss: " << ss->securityAuthKey << endl;

//send message
pdu = snmp_pdu_create(SNMP_MSG_GET);
read_objid(".1.3.6.1.2.1.1.1.0", anOID, &anOID_len);
snmp_add_null_var(pdu, anOID, anOID_len);
status = snmp_synch_response(ss, pdu, &response);

/*
 * Process the response.
 */
if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) {
    cout << "SNMP-read success" << endl;
} else {
    cout << "SNMP-read fail" << endl;
}

if (response)
    snmp_free_pdu(response);
if (!snmp_close(ss))
    cout << "Snmp closing failed" << endl;

/*
 * Second request: Only the authProto is changed from MD5 to SHA1. I expect,
 * that the snmp-get fails, but it still succeeds.
 */

snmp_sess_init(&session1);
session1.peername = ip;
session1.version = SNMP_VERSION_3;

/* set the SNMPv3 user name */
session1.securityName = strdup(user);
session1.securityNameLen = strlen(session1.securityName);

// set the authentication method to SHA1 
session1.securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV;

session1.securityAuthProto = usmHMACSHA1AuthProtocol;
session1.securityAuthProtoLen = USM_AUTH_PROTO_SHA_LEN;
session1.securityAuthKeyLen = USM_AUTH_KU_LEN;

if (generate_Ku(session1.securityAuthProto,
        session1.securityAuthProtoLen,
        (u_char *) authpw.c_str(), strlen(authpw.c_str()),
        session1.securityAuthKey,
        &session1.securityAuthKeyLen) != SNMPERR_SUCCESS) {
    //if code reaches here, the creation of the security key was not successful
}

cout << "SecurityAuthProto - session1: " << session1.securityAuthProto[9] << " / SecurityAuthKey - session1: " << session1.securityAuthKey << endl;

ss1 = snmp_open(&session1); /* establish the session */

if (!ss1) {
    cout << "Couldn't open session1 correctly";
    exit(2);
}

cout << "SecurityAuthProto - ss1: " << ss1->securityAuthProto[9] << " / SecurityAuthKey - ss1: " << ss1->securityAuthKey << endl;

//send message
pdu1 = snmp_pdu_create(SNMP_MSG_GET);
read_objid(".1.3.6.1.2.1.1.1.0", anOID, &anOID_len);
snmp_add_null_var(pdu1, anOID, anOID_len);
status1 = snmp_synch_response(ss1, pdu1, &response1);

/*
 * Process the response.
 */
if (status1 == STAT_SUCCESS && response1->errstat == SNMP_ERR_NOERROR) {
    cout << "SNMP-read success" << endl;
} else {
    cout << "SNMP-read fail" << endl;
}

if (response1)
    snmp_free_pdu(response1);
snmp_close(ss1);

return 0;

最佳答案

我自己找到了解决方案:

net-snmp 为用户的每个 EngineId(设备)缓存。如果 engineID 已经存在一个用户,而您尝试与该用户打开一个新 session ,net-snmp 将使用缓存的 session 。所以解决方案是清除缓存用户列表。

通过这段代码我可以解决我的问题:

usmUser* actUser = usm_get_userList();
while (actUser != NULL) {
    usmUser* dummy = actUser;
    usm_remove_user(actUser);
    actUser = dummy->next;
}

我希望我可以帮助其他人。

关于c++ - net-snmp 没有正确更改 auth 和 priv 协议(protocol),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18380435/

相关文章:

C++ 如何获得从 1 到 12 的随机值?

c - 不正确的输出和警告消息 '' 从 int '' 创建指针

c - 将数组转换为以一个数组作为成员的结构体是否安全?

linux - 执行 snmpd::FATAL: 内核太旧

使用 <bitset> 的 C++ 程序运行速度很慢

c++ - 相同版本的 clang 在不同操作系统上给出不同的结果

c++ - 来自垂死的多线程进程的核心转储

c++ - GCC:使用 -Werror 但将特定错误降级为警告(在命令行中)

bash - 收到 SNMP 陷阱时如何执行脚本?

Python 网络 SNMP,Linux : gather usernames by IP