/* * snmpvacm.c - send snmp SET requests to a network entity to change the * vacm database * */ #include #if HAVE_STDLIB_H #include #endif #if HAVE_UNISTD_H #include #endif #if HAVE_STRING_H #include #else #include #endif #include #if HAVE_NETINET_IN_H #include #endif #include #include #if TIME_WITH_SYS_TIME # include # include #else # if HAVE_SYS_TIME_H # include # else # include # endif #endif #if HAVE_SYS_SELECT_H #include #endif #if HAVE_NETDB_H #include #endif #if HAVE_ARPA_INET_H #include #endif #include #define CMD_CREATESEC2GROUP_NAME "createSec2Group" #define CMD_CREATESEC2GROUP 1 #define CMD_DELETESEC2GROUP_NAME "deleteSec2Group" #define CMD_DELETESEC2GROUP 2 #define CMD_CREATEACCESS_NAME "createAccess" #define CMD_CREATEACCESS 3 #define CMD_DELETEACCESS_NAME "deleteAccess" #define CMD_DELETEACCESS 4 #define CMD_CREATEVIEW_NAME "createView" #define CMD_CREATEVIEW 5 #define CMD_DELETEVIEW_NAME "deleteView" #define CMD_DELETEVIEW 6 #define CMD_CREATEAUTH_NAME "createAuth" #define CMD_CREATEAUTH 7 #define CMD_DELETEAUTH_NAME "deleteAuth" #define CMD_DELETEAUTH 8 #define CMD_NUM 8 static const char *successNotes[CMD_NUM] = { "Sec2group successfully created.", "Sec2group successfully deleted.", "Access successfully created.", "Access successfully deleted.", "View successfully created.", "View successfully deleted.", "AuthAccess successfully created.", "AuthAccess successfully deleted." }; #define SEC2GROUP_OID_LEN 11 #define ACCESS_OID_LEN 11 #define VIEW_OID_LEN 12 #define AUTH_OID_LEN 12 static oid vacmGroupName[MAX_OID_LEN] = { 1, 3, 6, 1, 6, 3, 16, 1, 2, 1, 3 }, vacmSec2GroupStatus[MAX_OID_LEN] = { 1, 3, 6, 1, 6, 3, 16, 1, 2, 1, 5}, vacmAccessContextMatch[MAX_OID_LEN] = { 1, 3, 6, 1, 6, 3, 16, 1, 4, 1, 4}, vacmAccessReadViewName[MAX_OID_LEN] = { 1, 3, 6, 1, 6, 3, 16, 1, 4, 1, 5}, vacmAccessWriteViewName[MAX_OID_LEN] = { 1, 3, 6, 1, 6, 3, 16, 1, 4, 1, 6}, vacmAccessNotifyViewName[MAX_OID_LEN] = { 1, 3, 6, 1, 6, 3, 16, 1, 4, 1, 7}, vacmAccessStatus[MAX_OID_LEN] = { 1, 3, 6, 1, 6, 3, 16, 1, 4, 1, 9}, vacmViewTreeFamilyMask[MAX_OID_LEN] = { 1, 3, 6, 1, 6, 3, 16, 1, 5, 2, 1, 3}, vacmViewTreeFamilyType[MAX_OID_LEN] = { 1, 3, 6, 1, 6, 3, 16, 1, 5, 2, 1, 4}, vacmViewTreeFamilyStatus[MAX_OID_LEN] = { 1, 3, 6, 1, 6, 3, 16, 1, 5, 2, 1, 6} ; #define NSVACMACCESSTABLE 1, 3, 6, 1, 4, 1, 8072, 1, 9, 1 static oid nsVacmContextPfx[MAX_OID_LEN] = { NSVACMACCESSTABLE, 1, 2 }; static oid nsVacmViewName[MAX_OID_LEN] = { NSVACMACCESSTABLE, 1, 3 }; static oid nsVacmRowStatus[MAX_OID_LEN] = { NSVACMACCESSTABLE, 1, 5 }; int viewTreeFamilyType = 1; void usage(void) { fprintf(stderr, "Usage: snmpvacm "); snmp_parse_args_usage(stderr); fprintf(stderr, " COMMAND\n\n"); snmp_parse_args_descriptions(stderr); fprintf(stderr, "\nsnmpvacm commands:\n"); fprintf(stderr, " createAccess GROUPNAME [CONTEXTPREFIX] SECURITYMODEL SECURITYLEVEL CONTEXTMATCH READVIEWNAME WRITEVIEWNAME NOTIFYVIEWNAME\n"); fprintf(stderr, " deleteAccess GROUPNAME [CONTEXTPREFIX] SECURITYMODEL SECURITYLEVEL\n"); fprintf(stderr, " createSec2Group MODEL SECURITYNAME GROUPNAME\n"); fprintf(stderr, " deleteSec2Group MODEL SECURITYNAME\n"); fprintf(stderr, " [-Ce] createView NAME SUBTREE [MASK]\n"); fprintf(stderr, " deleteView NAME SUBTREE\n"); fprintf(stderr, " createAuth GROUPNAME [CONTEXTPREFIX] SECURITYMODEL SECURITYLEVEL AUTHTYPE CONTEXTMATCH VIEWNAME\n"); fprintf(stderr, " deleteAuth GROUPNAME [CONTEXTPREFIX] SECURITYMODEL SECURITYLEVEL AUTHTYPE\n"); } void auth_oid(oid * it, size_t * len, const char *groupName, const char *prefix, int model, int level, const char *authtype) { int i; int itIndex = AUTH_OID_LEN; it[itIndex++] = strlen(groupName); for (i = 0; i < (int) strlen(groupName); i++) it[itIndex++] = groupName[i]; if (prefix) { *len += strlen(prefix); it[itIndex++] = strlen(prefix); for (i = 0; i < (int) strlen(prefix); i++) it[itIndex++] = prefix[i]; } else it[itIndex++] = 0; it[itIndex++] = model; it[itIndex++] = level; it[itIndex++] = strlen(authtype); for (i = 0; i < (int) strlen(authtype); i++) it[itIndex++] = authtype[i]; *len = itIndex; } void access_oid(oid * it, size_t * len, const char *groupName, const char *prefix, int model, int level) { int i; int itIndex = ACCESS_OID_LEN; *len = itIndex + 4 + +strlen(groupName); it[itIndex++] = strlen(groupName); for (i = 0; i < (int) strlen(groupName); i++) it[itIndex++] = groupName[i]; if (prefix) { *len += strlen(prefix); it[itIndex++] = strlen(prefix); for (i = 0; i < (int) strlen(prefix); i++) it[itIndex++] = prefix[i]; } else it[itIndex++] = 0; it[itIndex++] = model; it[itIndex++] = level; } void sec2group_oid(oid * it, size_t * len, int model, const char *name) { int i; int itIndex = SEC2GROUP_OID_LEN; *len = itIndex + 2 + strlen(name); it[itIndex++] = model; it[itIndex++] = strlen(name); for (i = 0; i < (int) strlen(name); i++) it[itIndex++] = name[i]; } void view_oid(oid * it, size_t * len, const char *viewName, char *viewSubtree) { int i; oid c_oid[SPRINT_MAX_LEN]; size_t c_oid_length = SPRINT_MAX_LEN; int itIndex = VIEW_OID_LEN; if (!snmp_parse_oid(viewSubtree, c_oid, &c_oid_length)) { printf("Error parsing subtree (%s)\n", viewSubtree); exit(1); } *len = itIndex + 2 + strlen(viewName) + c_oid_length; it[itIndex++] = strlen(viewName); for (i = 0; i < (int) strlen(viewName); i++) it[itIndex++] = viewName[i]; it[itIndex++] = c_oid_length; for (i = 0; i < (int) c_oid_length; i++) it[itIndex++] = c_oid[i]; /* * sprint_objid(c_oid, it, *len); */ } static void optProc(int argc, char *const *argv, int opt) { switch (opt) { case 'C': while (*optarg) { switch (*optarg++) { case 'e': viewTreeFamilyType = 2; break; default: fprintf(stderr, "Unknown flag passed to -C: %c\n", optarg[-1]); exit(1); } } break; } } 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; int status; int exitval = 1; int command = 0; long longvar; int secModel, secLevel, contextMatch; unsigned int val, i = 0; char *mask, *groupName, *prefix, *authtype; u_char viewMask[VACMSTRINGLEN]; char *st; SOCK_STARTUP; /* * 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; } /* * 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("snmpvacm", &session); goto out; } /* * 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(); goto close_session; } if (strcmp(argv[arg], CMD_DELETEVIEW_NAME) == 0) /* * deleteView: delete a view * * deleteView NAME SUBTREE * */ { if (++arg + 2 != argc) { fprintf(stderr, "You must specify the view to delete\n"); usage(); goto close_session; } command = CMD_DELETEVIEW; name_length = VIEW_OID_LEN; view_oid(vacmViewTreeFamilyStatus, &name_length, argv[arg], argv[arg + 1]); longvar = RS_DESTROY; snmp_pdu_add_variable(pdu, vacmViewTreeFamilyStatus, name_length, ASN_INTEGER, (u_char *) & longvar, sizeof(longvar)); } else if (strcmp(argv[arg], CMD_CREATEVIEW_NAME) == 0) /* * createView: create a view * * createView NAME SUBTREE MASK * */ { if (++arg + 2 > argc) { fprintf(stderr, "You must specify name, subtree and mask\n"); usage(); goto close_session; } command = CMD_CREATEVIEW; name_length = VIEW_OID_LEN; view_oid(vacmViewTreeFamilyStatus, &name_length, argv[arg], argv[arg + 1]); longvar = RS_CREATEANDGO; snmp_pdu_add_variable(pdu, vacmViewTreeFamilyStatus, name_length, ASN_INTEGER, (u_char *) & longvar, sizeof(longvar)); /* * Mask */ if (arg + 3 == argc) { mask = argv[arg + 2]; for (mask = strtok_r(mask, ".:", &st); mask; mask = strtok_r(NULL, ".:", &st)) { if (i >= sizeof(viewMask)) { printf("MASK too long\n"); goto close_session; } if (sscanf(mask, "%x", &val) == 0) { printf("invalid MASK\n"); goto close_session; } viewMask[i] = val; i++; } } else { for (i=0 ; i < (name_length+7)/8; i++) viewMask[i] = (u_char)0xff; } view_oid(vacmViewTreeFamilyMask, &name_length, argv[arg], argv[arg + 1]); snmp_pdu_add_variable(pdu, vacmViewTreeFamilyMask, name_length, ASN_OCTET_STR, viewMask, i); view_oid(vacmViewTreeFamilyType, &name_length, argv[arg], argv[arg + 1]); snmp_pdu_add_variable(pdu, vacmViewTreeFamilyType, name_length, ASN_INTEGER, (u_char *) & viewTreeFamilyType, sizeof(viewTreeFamilyType)); } else if (strcmp(argv[arg], CMD_DELETESEC2GROUP_NAME) == 0) /* * deleteSec2Group: delete security2group * * deleteSec2Group MODEL SECURITYNAME * */ { if (++arg + 2 != argc) { fprintf(stderr, "You must specify the sec2group to delete\n"); usage(); goto close_session; } command = CMD_DELETESEC2GROUP; name_length = SEC2GROUP_OID_LEN; if (sscanf(argv[arg], "%d", &secModel) == 0) { printf("invalid security model\n"); usage(); goto close_session; } sec2group_oid(vacmSec2GroupStatus, &name_length, secModel, argv[arg + 1]); longvar = RS_DESTROY; snmp_pdu_add_variable(pdu, vacmSec2GroupStatus, name_length, ASN_INTEGER, (u_char *) & longvar, sizeof(longvar)); } else if (strcmp(argv[arg], CMD_CREATESEC2GROUP_NAME) == 0) /* * createSec2Group: create a security2group * * createSec2Group MODEL SECURITYNAME GROUPNAME * */ { if (++arg + 3 != argc) { fprintf(stderr, "You must specify model, security name and group name\n"); usage(); goto close_session; } command = CMD_CREATESEC2GROUP; name_length = SEC2GROUP_OID_LEN; if (sscanf(argv[arg], "%d", &secModel) == 0) { printf("invalid security model\n"); usage(); goto close_session; } sec2group_oid(vacmSec2GroupStatus, &name_length, secModel, argv[arg + 1]); longvar = RS_CREATEANDGO; snmp_pdu_add_variable(pdu, vacmSec2GroupStatus, name_length, ASN_INTEGER, (u_char *) & longvar, sizeof(longvar)); sec2group_oid(vacmGroupName, &name_length, secModel, argv[arg + 1]); snmp_pdu_add_variable(pdu, vacmGroupName, name_length, ASN_OCTET_STR, (u_char *) argv[arg + 2], strlen(argv[arg + 2])); } else if (strcmp(argv[arg], CMD_DELETEACCESS_NAME) == 0) /* * deleteAccess: delete access entry * * deleteAccess GROUPNAME [CONTEXTPREFIX] SECURITYMODEL SECURITYLEVEL * */ { if (++arg + 3 > argc) { fprintf(stderr, "You must specify the access entry to delete\n"); usage(); goto close_session; } command = CMD_DELETEACCESS; name_length = ACCESS_OID_LEN; groupName = argv[arg]; if (arg + 4 == argc) prefix = argv[++arg]; else prefix = NULL; if (sscanf(argv[arg + 1], "%d", &secModel) == 0) { printf("invalid security model\n"); usage(); goto close_session; } if (sscanf(argv[arg + 2], "%d", &secLevel) == 0) { printf("invalid security level\n"); usage(); goto close_session; } access_oid(vacmAccessStatus, &name_length, groupName, prefix, secModel, secLevel); longvar = RS_DESTROY; snmp_pdu_add_variable(pdu, vacmAccessStatus, name_length, ASN_INTEGER, (u_char *) & longvar, sizeof(longvar)); } else if (strcmp(argv[arg], CMD_CREATEACCESS_NAME) == 0) /* * createAccess: create access entry * * createAccess GROUPNAME [CONTEXTPREFIX] SECURITYMODEL SECURITYLEVEL CONTEXTMATCH READVIEWNAME WRITEVIEWNAME NOTIFYVIEWNAME * */ { if (++arg + 7 > argc) { fprintf(stderr, "You must specify the access entry to create\n"); usage(); goto close_session; } command = CMD_CREATEACCESS; name_length = ACCESS_OID_LEN; groupName = argv[arg]; if (arg + 8 == argc) prefix = argv[++arg]; else prefix = NULL; if (sscanf(argv[arg + 1], "%d", &secModel) == 0) { printf("invalid security model\n"); usage(); goto close_session; } if (sscanf(argv[arg + 2], "%d", &secLevel) == 0) { printf("invalid security level\n"); usage(); goto close_session; } access_oid(vacmAccessStatus, &name_length, groupName, prefix, secModel, secLevel); longvar = RS_CREATEANDGO; snmp_pdu_add_variable(pdu, vacmAccessStatus, name_length, ASN_INTEGER, (u_char *) & longvar, sizeof(longvar)); access_oid(vacmAccessContextMatch, &name_length, groupName, prefix, secModel, secLevel); if (sscanf(argv[arg + 3], "%d", &contextMatch) == 0) { printf("invalid contextMatch\n"); usage(); goto close_session; } snmp_pdu_add_variable(pdu, vacmAccessContextMatch, name_length, ASN_INTEGER, (u_char *) & contextMatch, sizeof(contextMatch)); access_oid(vacmAccessReadViewName, &name_length, groupName, prefix, secModel, secLevel); snmp_pdu_add_variable(pdu, vacmAccessReadViewName, name_length, ASN_OCTET_STR, (u_char *) argv[arg + 4], strlen(argv[arg + 4])); access_oid(vacmAccessWriteViewName, &name_length, groupName, prefix, secModel, secLevel); snmp_pdu_add_variable(pdu, vacmAccessWriteViewName, name_length, ASN_OCTET_STR, (u_char *) argv[arg + 5], strlen(argv[arg + 5])); access_oid(vacmAccessNotifyViewName, &name_length, groupName, prefix, secModel, secLevel); snmp_pdu_add_variable(pdu, vacmAccessNotifyViewName, name_length, ASN_OCTET_STR, (u_char *) argv[arg + 6], strlen(argv[arg + 6])); } else if (strcmp(argv[arg], CMD_DELETEAUTH_NAME) == 0) /* * deleteAuth: delete authAccess entry * * deleteAuth GROUPNAME [CONTEXTPREFIX] SECURITYMODEL SECURITYLEVEL AUTHTYPE * */ { if (++arg + 4 > argc) { fprintf(stderr, "You must specify the authAccess entry to delete\n"); usage(); goto close_session; } command = CMD_DELETEAUTH; name_length = AUTH_OID_LEN; groupName = argv[arg]; if (arg + 5 == argc) prefix = argv[++arg]; else prefix = NULL; if (sscanf(argv[arg + 1], "%d", &secModel) == 0) { printf("invalid security model\n"); usage(); goto close_session; } if (sscanf(argv[arg + 2], "%d", &secLevel) == 0) { printf("invalid security level\n"); usage(); goto close_session; } authtype = argv[arg+3]; auth_oid(nsVacmRowStatus, &name_length, groupName, prefix, secModel, secLevel, authtype); longvar = RS_DESTROY; snmp_pdu_add_variable(pdu, nsVacmRowStatus, name_length, ASN_INTEGER, (u_char *) & longvar, sizeof(longvar)); } else if (strcmp(argv[arg], CMD_CREATEAUTH_NAME) == 0) /* * createAuth: create authAccess entry * * createAuth GROUPNAME [CONTEXTPREFIX] SECURITYMODEL SECURITYLEVEL AUTHTYPE CONTEXTMATCH VIEWNAME * */ { if (++arg + 6 > argc) { fprintf(stderr, "You must specify the authAccess entry to create\n"); usage(); goto close_session; } command = CMD_CREATEAUTH; name_length = AUTH_OID_LEN; groupName = argv[arg]; if (arg + 7 == argc) prefix = argv[++arg]; else prefix = NULL; if (sscanf(argv[arg + 1], "%d", &secModel) == 0) { printf("invalid security model\n"); usage(); goto close_session; } if (sscanf(argv[arg + 2], "%d", &secLevel) == 0) { printf("invalid security level\n"); usage(); goto close_session; } authtype = argv[arg+3]; auth_oid(nsVacmRowStatus, &name_length, groupName, prefix, secModel, secLevel, authtype); longvar = RS_CREATEANDGO; snmp_pdu_add_variable(pdu, nsVacmRowStatus, name_length, ASN_INTEGER, (u_char *) & longvar, sizeof(longvar)); auth_oid(nsVacmContextPfx, &name_length, groupName, prefix, secModel, secLevel, authtype); if (sscanf(argv[arg + 4], "%d", &contextMatch) == 0) { printf("invalid contextMatch\n"); usage(); goto close_session; } snmp_pdu_add_variable(pdu, nsVacmContextPfx, name_length, ASN_INTEGER, (u_char *) & contextMatch, sizeof(contextMatch)); auth_oid(nsVacmViewName, &name_length, groupName, prefix, secModel, secLevel, authtype); snmp_pdu_add_variable(pdu, nsVacmViewName, name_length, ASN_OCTET_STR, (u_char *) argv[arg + 5], strlen(argv[arg + 5])); } else { printf("Unknown command\n"); usage(); goto close_session; } exitval = 0; /* * 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; struct variable_list *vars = response->variables; fprintf(stderr, "Failed object: "); for(count = 1; vars && (count != response->errindex); vars = vars->next_variable, count++) ; 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 { snmp_sess_perror("snmpset", ss); exitval = 1; } if (response) snmp_free_pdu(response); close_session: snmp_close(ss); out: SOCK_CLEANUP; return exitval; }