| /* |
| * Note: this file originally auto-generated by mib2c using |
| * $ |
| */ |
| |
| #include <net-snmp/net-snmp-config.h> |
| #include <net-snmp/net-snmp-features.h> |
| #include <net-snmp/net-snmp-includes.h> |
| #include <net-snmp/agent/net-snmp-agent-includes.h> |
| #include <openssl/ssl.h> |
| #include <openssl/x509.h> |
| #include <net-snmp/library/cert_util.h> |
| #include "tlstm-mib.h" |
| #include "snmpTlstmCertToTSNTable.h" |
| |
| netsnmp_feature_require(table_tdata) |
| netsnmp_feature_require(cert_fingerprints) |
| netsnmp_feature_require(table_tdata_delete_table) |
| netsnmp_feature_require(table_tdata_extract_table) |
| netsnmp_feature_require(table_tdata_remove_row) |
| netsnmp_feature_require(tls_fingerprint_build) |
| #ifndef NETSNMP_NO_WRITE_SUPPORT |
| netsnmp_feature_require(check_vb_storagetype) |
| netsnmp_feature_require(check_vb_type_and_max_size) |
| netsnmp_feature_require(check_vb_rowstatus_with_storagetype) |
| netsnmp_feature_require(table_tdata_insert_row) |
| #endif /* NETSNMP_NO_WRITE_SUPPORT */ |
| |
| /** XXX - move these to table_data header? */ |
| #define FATE_NEWLY_CREATED 1 |
| #define FATE_NO_CHANGE 0 |
| #define FATE_DELETE_ME -1 |
| |
| #define MAP_MIB_CONFIG_TOKEN "snmpTlstmCertToTSNEntry" |
| |
| extern netsnmp_cert_map *netsnmp_certToTSN_parse_common(char **line); |
| |
| |
| /* |
| * structure for undo storage and other vars for set processing |
| */ |
| typedef struct certToTSN_undo_s { |
| char fate; |
| char copied; |
| char is_consistent; |
| netsnmp_request_info *req[SNMPTLSTMCERTTOTSN_TABLE_MAX_COL+1]; |
| |
| /* |
| * undo Column space |
| */ |
| char fingerprint[SNMPTLSTMCERTTOTSN_FINGERPRINT_MAX_SIZE]; |
| size_t fingerprint_len; |
| int mapType; |
| char data[SNMPTLSTMCERTTOTSN_DATA_MAX_SIZE]; |
| size_t data_len; |
| u_char hashType; |
| char storageType; |
| char rowStatus; |
| } certToTSN_undo; |
| |
| /* |
| * Typical data structure for a row entry |
| */ |
| typedef struct certToTSN_entry_s { |
| /* |
| * Index values |
| */ |
| u_long tlstmCertToTSNID; |
| |
| /* |
| * Column values |
| */ |
| char fingerprint[SNMPTLSTMCERTTOTSN_FINGERPRINT_MAX_SIZE]; |
| size_t fingerprint_len; |
| int mapType; |
| char data[SNMPTLSTMCERTTOTSN_DATA_MAX_SIZE]; |
| size_t data_len; |
| char storageType; |
| char rowStatus; |
| u_char hashType; |
| char map_flags; |
| |
| /* |
| * used during set processing |
| */ |
| certToTSN_undo *undo; |
| } certToTSN_entry; |
| |
| static Netsnmp_Node_Handler tlstmCertToTSNTable_handler; |
| static oid _oid2type(oid *val, int val_len); |
| /** static int _type2oid(int type, oid *val, int *val_len); */ |
| static int _cache_load(netsnmp_cache *cache, netsnmp_tdata *table); |
| static void _cache_free(netsnmp_cache *cache, netsnmp_tdata *table); |
| static void _cert_map_add(certToTSN_entry *entry); |
| static void _cert_map_remove(certToTSN_entry *entry); |
| static int _count_handler(netsnmp_mib_handler *handler, |
| netsnmp_handler_registration *reginfo, |
| netsnmp_agent_request_info *reqinfo, |
| netsnmp_request_info *requests); |
| static void _parse_mib_maps(const char *token, char *line); |
| static int _save_maps(int majorID, int minorID, void *server, void *client); |
| static int _save_map(netsnmp_cert_map *map, int row_status, void *type); |
| static void _cert_map_tweak_storage(certToTSN_entry *entry); |
| |
| static netsnmp_tdata *_table = NULL; |
| static uint32_t _last_changed = 0; |
| |
| |
| /** Initializes the tlstmCertToTSNTable module */ |
| void |
| init_snmpTlstmCertToTSNTable(void) |
| { |
| init_snmpTlstmCertToTSNTable_context(NULL); |
| } |
| |
| void |
| init_snmpTlstmCertToTSNTable_context(const char *contextName) |
| { |
| oid reg_oid[] = { SNMP_TLS_TM_CERT_TABLE }; |
| const size_t reg_oid_len = OID_LENGTH(reg_oid); |
| netsnmp_handler_registration *reg; |
| netsnmp_table_registration_info *info; |
| netsnmp_cache *cache; |
| netsnmp_watcher_info *watcher; |
| const char *mib_map_help = |
| MAP_MIB_CONFIG_TOKEN " table persistence (internal use)"; |
| |
| DEBUGMSGTL(("tlstmCertToSN:init", |
| "initializing table tlstmCertToTSNTable\n")); |
| |
| reg = netsnmp_create_handler_registration |
| ("tlstmCertToTSNTable", tlstmCertToTSNTable_handler, |
| reg_oid, reg_oid_len, |
| HANDLER_CAN_RWRITE); |
| if (NULL == reg) { |
| snmp_log(LOG_ERR, |
| "error creating handler registration for tlstmCertToSN\n"); |
| return; |
| } |
| |
| if (NULL != contextName) |
| reg->contextName = strdup(contextName); |
| |
| _table = netsnmp_tdata_create_table("tlstmCertToTSNTable", 0); |
| if (NULL == _table) { |
| snmp_log(LOG_ERR, |
| "error creating tdata table for tlstmCertToTSNTable\n"); |
| return; |
| } |
| info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info); |
| if (NULL == info) { |
| snmp_log(LOG_ERR, |
| "error creating table info for tlstmCertToTSNTable\n"); |
| netsnmp_tdata_delete_table(_table); |
| _table = NULL; |
| return; |
| } |
| netsnmp_table_helper_add_indexes(info, |
| /* index: tlstmCertToTSNID */ |
| ASN_UNSIGNED, 0); |
| |
| info->min_column = SNMPTLSTMCERTTOTSN_TABLE_MIN_COL; |
| info->max_column = SNMPTLSTMCERTTOTSN_TABLE_MAX_COL; |
| |
| /* |
| * cache init |
| */ |
| cache = netsnmp_cache_create(30, (NetsnmpCacheLoad*)_cache_load, |
| (NetsnmpCacheFree*)_cache_free, |
| reg_oid, |
| reg_oid_len); |
| if (NULL == cache) { |
| snmp_log(LOG_ERR,"error creating cache for tlstmCertToTSNTable\n"); |
| netsnmp_tdata_delete_table(_table); |
| _table = NULL; |
| return; |
| } |
| cache->magic = (void *)_table; |
| cache->flags = NETSNMP_CACHE_DONT_INVALIDATE_ON_SET; |
| |
| netsnmp_tdata_register(reg, _table, info); |
| |
| if (cache) |
| netsnmp_inject_handler_before( reg, netsnmp_cache_handler_get(cache), |
| "table_container"); |
| |
| /* |
| * register scalars |
| */ |
| reg_oid[10] = 1; |
| reg = netsnmp_create_handler_registration("snmpTlstmCertToTSNCount", |
| _count_handler, reg_oid, |
| OID_LENGTH(reg_oid), |
| HANDLER_CAN_RONLY); |
| if (NULL == reg) |
| snmp_log(LOG_ERR, |
| "could not create handler for snmpTlstmCertToTSNCount\n"); |
| else { |
| if (NULL != contextName) |
| reg->contextName = strdup(contextName); |
| |
| netsnmp_register_scalar(reg); |
| if (cache) |
| netsnmp_inject_handler_before(reg, netsnmp_cache_handler_get(cache), |
| "table_container"); |
| } |
| |
| reg_oid[10] = 2; |
| reg = netsnmp_create_handler_registration( |
| "snmpTlstmCertToTSNTableLastChanged", NULL, reg_oid, |
| OID_LENGTH(reg_oid), HANDLER_CAN_RONLY); |
| watcher = netsnmp_create_watcher_info((void*)&_last_changed, |
| sizeof(_last_changed), |
| ASN_TIMETICKS, |
| WATCHER_FIXED_SIZE); |
| if ((NULL == reg) || (NULL == watcher)) |
| snmp_log(LOG_ERR, |
| "could not create handler for snmpTlstmCertToTSNCount\n"); |
| else { |
| if (NULL != contextName) |
| reg->contextName = strdup(contextName); |
| netsnmp_register_watched_scalar2(reg, watcher); |
| } |
| |
| /* |
| * persistence |
| */ |
| register_config_handler(NULL, MAP_MIB_CONFIG_TOKEN, _parse_mib_maps, NULL, |
| mib_map_help); |
| if (snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA, |
| _save_maps, NULL) != SNMP_ERR_NOERROR) |
| snmp_log(LOG_ERR, "error registering for STORE_DATA callback " |
| "for certToTSN\n"); |
| |
| } |
| |
| /* |
| * create a new row in the table |
| */ |
| netsnmp_tdata_row * |
| tlstmCertToTSNTable_createEntry(netsnmp_tdata * table, u_long tlstmCertToTSNID) |
| { |
| certToTSN_entry *entry; |
| netsnmp_tdata_row *row; |
| |
| entry = SNMP_MALLOC_TYPEDEF(certToTSN_entry); |
| if (!entry) |
| return NULL; |
| |
| row = netsnmp_tdata_create_row(); |
| if (!row) { |
| SNMP_FREE(entry); |
| return NULL; |
| } |
| row->data = entry; |
| |
| DEBUGMSGT(("tlstmCertToSN:entry:create", "entry %p / row %p\n", |
| entry, row)); |
| /* |
| * populate index |
| */ |
| entry->tlstmCertToTSNID = tlstmCertToTSNID; |
| netsnmp_tdata_row_add_index(row, ASN_UNSIGNED, |
| &(entry->tlstmCertToTSNID), |
| sizeof(entry->tlstmCertToTSNID)); |
| /* |
| * assign default column values |
| */ |
| entry->mapType = TSNM_tlstmCertSpecified; |
| entry->storageType = ST_NONVOLATILE; |
| entry->rowStatus = RS_NOTREADY; |
| |
| if (table) { |
| DEBUGMSGTL(("tlstmCertToTSN:row:insert", "row %p\n", row)); |
| netsnmp_tdata_add_row(table, row); |
| } |
| return row; |
| } |
| |
| /* |
| * allocate undo resources |
| */ |
| static certToTSN_undo * |
| _allocUndo(certToTSN_entry * entry) |
| { |
| if (!entry) |
| return NULL; |
| |
| netsnmp_assert(!entry->undo); |
| |
| entry->undo = SNMP_MALLOC_TYPEDEF(certToTSN_undo); |
| if (!entry->undo) |
| return NULL; |
| |
| entry->undo->is_consistent = -1; /* don't know */ |
| |
| return entry->undo; |
| } |
| |
| /* |
| * free undo resources |
| */ |
| static void |
| _freeUndo(certToTSN_entry * entry) |
| { |
| if (!entry || !entry->undo) |
| return; |
| |
| /* |
| * TODO: release any allocated resources |
| */ |
| SNMP_FREE(entry->undo); |
| } |
| |
| /* |
| * remove a row from the table |
| */ |
| void |
| tlstmCertToTSNTable_removeEntry(netsnmp_tdata * table, |
| netsnmp_tdata_row * row) |
| { |
| certToTSN_entry *entry; |
| |
| if (!row) |
| return; /* Nothing to remove */ |
| |
| entry = (certToTSN_entry *) row->data; |
| |
| DEBUGMSGT(("tlstmCertToSN:entry:delete", "entry %p / row %p\n", |
| entry, row)); |
| |
| if (entry && entry->undo) |
| _freeUndo(entry); |
| SNMP_FREE(entry); |
| |
| if (table) { |
| DEBUGMSGTL(("tlstmCertToSN:row:remove", "row %p\n", row)); |
| netsnmp_tdata_remove_and_delete_row(table, row); |
| } |
| else |
| netsnmp_tdata_delete_row(row); |
| } |
| |
| |
| /** handles requests for the tlstmCertToTSNTable table */ |
| static int |
| tlstmCertToTSNTable_handler(netsnmp_mib_handler *handler, |
| netsnmp_handler_registration *reginfo, |
| netsnmp_agent_request_info *reqinfo, |
| netsnmp_request_info *requests) |
| { |
| oid tsnm[] = { SNMP_TLS_TM_BASE, 1, 1, 0 }; |
| static const int tsnm_pos = OID_LENGTH(tsnm) - 1; |
| netsnmp_request_info *request = NULL; |
| netsnmp_table_request_info *info; |
| netsnmp_tdata *table; |
| netsnmp_tdata_row *row; |
| certToTSN_entry *entry; |
| int ret = SNMP_ERR_NOERROR; |
| |
| DEBUGMSGTL(("tlstmCertToSN:handler", "Processing request (mode %s (%d))\n", |
| se_find_label_in_slist("agent_mode", reqinfo->mode), |
| reqinfo->mode)); |
| |
| switch (reqinfo->mode) { |
| /** ######################################################### GET ##### |
| * |
| * Read-support (also covers GetNext requests) |
| */ |
| case MODE_GET: |
| for (request = requests; request; request = request->next) { |
| if (request->processed) |
| continue; |
| |
| entry = (certToTSN_entry *) netsnmp_tdata_extract_entry(request); |
| info = netsnmp_extract_table_info(request); |
| netsnmp_assert(entry && info); |
| |
| switch (info->colnum) { |
| case COL_SNMPTLSTMCERTTOTSN_FINGERPRINT: |
| { |
| /* |
| * build SnmpTLSFingerprint |
| */ |
| u_char bin[42], *ptr = bin; |
| size_t len = sizeof(bin); |
| int rc; |
| rc = netsnmp_tls_fingerprint_build(entry->hashType, |
| entry->fingerprint, |
| &ptr, &len, 0); |
| if (SNMPERR_SUCCESS != rc) |
| netsnmp_set_request_error(reqinfo, request, |
| SNMP_ERR_GENERR); |
| else |
| snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR, |
| bin, len); |
| } |
| break; /* case COL_SNMPTLSTMCERTTOTSN_FINGERPRINT */ |
| case COL_SNMPTLSTMCERTTOTSN_MAPTYPE: |
| tsnm[tsnm_pos] = entry->mapType; |
| snmp_set_var_typed_value(request->requestvb, ASN_OBJECT_ID, |
| tsnm, sizeof(tsnm)); |
| break; /* case COL_SNMPTLSTMCERTTOTSN_MAPTYPE */ |
| case COL_SNMPTLSTMCERTTOTSN_DATA: |
| snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR, |
| entry->data, entry->data_len); |
| break; /* case COL_SNMPTLSTMCERTTOTSN_DATA */ |
| case COL_SNMPTLSTMCERTTOTSN_STORAGETYPE: |
| snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, |
| entry->storageType); |
| break; /* case COL_SNMPTLSTMCERTTOTSN_STORAGETYPE */ |
| case COL_SNMPTLSTMCERTTOTSN_ROWSTATUS: |
| snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, |
| entry->rowStatus); |
| break; /* case COL_SNMPTLSTMCERTTOTSN_ROWSTATUS */ |
| default: |
| netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT); |
| break; |
| } /* switch colnum */ |
| } /* for requests */ |
| break; /* case MODE_GET */ |
| |
| /* |
| * Write-support |
| */ |
| /** #################################################### RESERVE1 ##### |
| * |
| * In RESERVE1 we are just checking basic ASN.1 size/type restrictions. |
| * You probably don't need to change any of this code. Don't change any |
| * of the column values here. Save that for the ACTION phase. |
| * |
| * The next phase is RESERVE2 or FREE. |
| */ |
| case MODE_SET_RESERVE1: |
| for (request = requests; request; request = request->next) { |
| netsnmp_assert(request->processed == 0); |
| |
| entry = (certToTSN_entry *) netsnmp_tdata_extract_entry(request); |
| info = netsnmp_extract_table_info(request); |
| |
| if ((NULL != entry) && (ST_READONLY == entry->storageType)) { |
| ret = SNMP_ERR_NOTWRITABLE; |
| break; |
| } |
| |
| switch (info->colnum) { |
| case COL_SNMPTLSTMCERTTOTSN_FINGERPRINT: |
| ret = netsnmp_check_vb_type_and_max_size |
| (request->requestvb, ASN_OCTET_STR, |
| sizeof(entry->fingerprint)); |
| /** check len/algorithm MIB requirements */ |
| if (ret == SNMP_ERR_NOERROR) |
| ret = netsnmp_cert_check_vb_fingerprint(request->requestvb); |
| break; /* case COL_SNMPTLSTMCERTTOTSN_FINGERPRINT */ |
| case COL_SNMPTLSTMCERTTOTSN_MAPTYPE: |
| ret = netsnmp_check_vb_type_and_max_size |
| (request->requestvb, ASN_OBJECT_ID, |
| SNMPTLSTMCERTTOTSN_MAPTYPE_MAX_SIZE); |
| if (ret == SNMP_ERR_NOERROR) { |
| if (_oid2type(request->requestvb->val.objid, |
| request->requestvb->val_len) > |
| TSNM_tlstmCert_MAX) |
| ret = SNMP_ERR_WRONGVALUE; |
| } |
| break; /* case COL_SNMPTLSTMCERTTOTSN_MAPTYPE */ |
| case COL_SNMPTLSTMCERTTOTSN_DATA: |
| ret = netsnmp_check_vb_type_and_max_size |
| (request->requestvb, ASN_OCTET_STR, sizeof(entry->data)); |
| break; /* case COL_SNMPTLSTMCERTTOTSN_DATA */ |
| case COL_SNMPTLSTMCERTTOTSN_STORAGETYPE: |
| ret = netsnmp_check_vb_storagetype |
| (request->requestvb,(entry ? entry->storageType : ST_NONE)); |
| break; /* case COL_SNMPTLSTMCERTTOTSN_STORAGETYPE */ |
| case COL_SNMPTLSTMCERTTOTSN_ROWSTATUS: |
| ret = netsnmp_check_vb_rowstatus_with_storagetype |
| (request->requestvb, |
| (entry ? entry->rowStatus :RS_NONEXISTENT), |
| (entry ? entry->storageType :ST_NONE)); |
| break; /* case COL_SNMPTLSTMCERTTOTSN_ROWSTATUS */ |
| default: |
| ret = SNMP_ERR_NOTWRITABLE; |
| } /* switch colnum */ |
| |
| if (ret != SNMP_ERR_NOERROR) |
| break; |
| } /* for requests */ |
| break; /* case MODE_SET_RESERVE1 */ |
| |
| /** #################################################### RESERVE2 ##### |
| * |
| * RESERVE2 is for checking additional restrictions from the MIB. |
| * Since these restrictions are often in the description of the object, |
| * mib2c can't generate code. It's possible that you need to add |
| * additional checks here. However, don't change any of the column |
| * values here. Save that for the ACTION phase. |
| * |
| * The next phase is ACTION or FREE. |
| */ |
| case MODE_SET_RESERVE2: |
| for (request = requests; request; request = request->next) { |
| netsnmp_assert(request->processed == 0); |
| |
| entry = (certToTSN_entry *) netsnmp_tdata_extract_entry(request); |
| table = netsnmp_tdata_extract_table(request); |
| info = netsnmp_extract_table_info(request); |
| /* |
| * if no row, create one |
| */ |
| if (!entry) { |
| row = tlstmCertToTSNTable_createEntry |
| (table,*info->indexes->val.integer); |
| if (!row) { |
| ret = SNMP_ERR_RESOURCEUNAVAILABLE; |
| break; |
| } |
| entry = row->data; |
| _allocUndo(entry); |
| if (!entry->undo) { |
| tlstmCertToTSNTable_removeEntry(table, row); |
| row = NULL; |
| ret = SNMP_ERR_RESOURCEUNAVAILABLE; |
| break; |
| } |
| entry->undo->fate = FATE_NEWLY_CREATED; |
| /** associate row with requests */ |
| netsnmp_insert_tdata_row(request, row); |
| } |
| |
| /** allocate undo structure, if needed */ |
| if (!entry->undo) { |
| _allocUndo(entry); |
| if (!entry->undo) { |
| ret = SNMP_ERR_RESOURCEUNAVAILABLE; |
| break; |
| } |
| } |
| |
| /* |
| * save request ptr for column. if we already |
| * have a value, bail. |
| */ |
| if (entry->undo->req[info->colnum]) { |
| DEBUGMSGT(("tlstmCertToSN:reserve2", |
| "multiple sets to col %d in request\n", |
| info->colnum)); |
| if (FATE_NEWLY_CREATED == entry->undo->fate) |
| ret = SNMP_ERR_INCONSISTENTNAME; |
| else |
| ret = SNMP_ERR_INCONSISTENTVALUE; |
| break; |
| } |
| entry->undo->req[info->colnum] = request; |
| if (ret != SNMP_ERR_NOERROR) |
| break; |
| } /* for requests */ |
| |
| if (ret == SNMP_ERR_NOERROR) { |
| /** make sure rowstatus is used to create rows */ |
| for (request = requests; request; request = request->next) { |
| if (request->processed) |
| continue; |
| |
| entry = (certToTSN_entry *) |
| netsnmp_tdata_extract_entry(request); |
| if ((entry->undo->fate != FATE_NEWLY_CREATED) || |
| (entry->undo->req[COL_SNMPTLSTMCERTTOTSN_ROWSTATUS])) |
| continue; |
| ret = SNMP_ERR_INCONSISTENTNAME; |
| break; |
| } /* creation for requests */ |
| } /* no error */ |
| break; /* case MODE_SET_RESERVE2 */ |
| |
| /** ######################################################## FREE ##### |
| * |
| * FREE is for cleaning up after a failed request (during either |
| * RESERVE1 or RESERVE2). So any allocated resources need to be |
| * released. |
| * |
| * This the final phase for this path in the state machine. |
| */ |
| case MODE_SET_FREE: |
| /* |
| * release undo resources |
| * remove any newly created rows |
| */ |
| for (request = requests; request; request = request->next) { |
| table = netsnmp_tdata_extract_table(request); |
| row = netsnmp_tdata_extract_row(request); |
| entry = (certToTSN_entry *) netsnmp_tdata_extract_entry(request); |
| |
| if (!entry || !entry->undo) |
| continue; |
| |
| /** disassociate row with requests */ |
| netsnmp_remove_tdata_row(request, row); |
| |
| if (FATE_NEWLY_CREATED == entry->undo->fate) |
| tlstmCertToTSNTable_removeEntry(table, row); |
| else |
| _freeUndo(entry); |
| } |
| break; /* case MODE_SET_FREE */ |
| |
| /** ###################################################### ACTION ##### |
| * |
| * In the ACTION phase, we perform any sets that can be undone. |
| * (Save anything that can't be undone for the COMMIT phase.) |
| * |
| * After individual columns have been done, you should check that the |
| * row as a whole is consistent. |
| * |
| * The next phase is UNDO or COMMIT. |
| */ |
| case MODE_SET_ACTION: |
| for (request = requests; request; request = request->next) { |
| entry = (certToTSN_entry *) netsnmp_tdata_extract_entry(request); |
| info = netsnmp_extract_table_info(request); |
| |
| /** reserve2 should enforce this */ |
| netsnmp_assert(request == entry->undo->req[info->colnum]); |
| |
| /* |
| * for each col, save old value and the set new value |
| */ |
| switch (info->colnum) { |
| case COL_SNMPTLSTMCERTTOTSN_FINGERPRINT: |
| { |
| u_char *tmp = (u_char*)entry->fingerprint; |
| u_int size = sizeof(entry->fingerprint); |
| netsnmp_variable_list *vb = request->requestvb; |
| |
| memcpy(entry->undo->fingerprint, |
| entry->fingerprint, sizeof(entry->fingerprint)); |
| entry->undo->fingerprint_len = entry->fingerprint_len; |
| entry->undo->hashType = entry->hashType; |
| memset(entry->fingerprint, 0, sizeof(entry->fingerprint)); |
| |
| (void)netsnmp_tls_fingerprint_parse(vb->val.string, vb->val_len, |
| (char**)&tmp, &size, 0, |
| &entry->hashType); |
| entry->fingerprint_len = size; |
| if (0 == entry->fingerprint_len) |
| ret = SNMP_ERR_GENERR; |
| } |
| break; /* case COL_SNMPTLSTMCERTTOTSN_FINGERPRINT */ |
| case COL_SNMPTLSTMCERTTOTSN_MAPTYPE: |
| entry->undo->mapType = entry->mapType; |
| entry->mapType = _oid2type(request->requestvb->val.objid, |
| request->requestvb->val_len); |
| break; /* case COL_SNMPTLSTMCERTTOTSN_MAPTYPE */ |
| case COL_SNMPTLSTMCERTTOTSN_DATA: |
| memcpy(entry->undo->data, entry->data, sizeof(entry->data)); |
| entry->undo->data_len = entry->data_len; |
| memset(entry->data, 0, sizeof(entry->data)); |
| memcpy(entry->data, request->requestvb->val.string, |
| request->requestvb->val_len); |
| entry->data_len = request->requestvb->val_len; |
| break; /* case COL_SNMPTLSTMCERTTOTSN_DATA */ |
| case COL_SNMPTLSTMCERTTOTSN_STORAGETYPE: |
| entry->undo->storageType = entry->storageType; |
| entry->storageType = *request->requestvb->val.integer; |
| break; /* case COL_SNMPTLSTMCERTTOTSN_STORAGETYPE */ |
| case COL_SNMPTLSTMCERTTOTSN_ROWSTATUS: |
| entry->undo->rowStatus = entry->rowStatus; |
| entry->rowStatus = *request->requestvb->val.integer; |
| break; /* case COL_SNMPTLSTMCERTTOTSN_ROWSTATUS */ |
| } /* switch colnum */ |
| } /* set values for requests */ |
| |
| if (ret != SNMP_ERR_NOERROR) |
| break; /* skip consistency if we've already got error */ |
| |
| /* |
| * All columns now have their final values set. check the |
| * internal consistency of each row. |
| */ |
| for (request = requests; request; request = request->next) { |
| entry = (certToTSN_entry *) netsnmp_tdata_extract_entry(request); |
| info = netsnmp_extract_table_info(request); |
| |
| if (entry->undo->is_consistent != -1) |
| continue; /* already checked */ |
| |
| /** assume consistency */ |
| entry->undo->is_consistent = 1; |
| |
| /* |
| * per mib, can't have empty fingerprint and must |
| * have data if indicated by map type. |
| */ |
| if (0 == entry->fingerprint_len) { |
| DEBUGMSGTL(("tlstmCertToTSNTable:inconsistent", |
| "fingerprint must not be empty\n")); |
| entry->undo->is_consistent = 0; |
| } |
| else if ((TSNM_tlstmCertSpecified == entry->mapType) && |
| (0 == entry->data_len)) { |
| DEBUGMSGTL(("tlstmCertToTSNTable:inconsistent", |
| "must specify Data for CertSpecified identity\n")); |
| entry->undo->is_consistent = 0; |
| } |
| |
| if ((RS_IS_ACTIVE(entry->rowStatus)) && |
| ((!entry->undo->req[COL_SNMPTLSTMCERTTOTSN_ROWSTATUS]) || |
| (RS_IS_ACTIVE(entry->undo->rowStatus)))) { |
| /* |
| * per mib, can't modify these while row active |
| */ |
| char _cols[3] = { COL_SNMPTLSTMCERTTOTSN_FINGERPRINT, |
| COL_SNMPTLSTMCERTTOTSN_MAPTYPE, COL_SNMPTLSTMCERTTOTSN_DATA }; |
| int i; |
| for (i=0; i < 3; ++i ) { |
| if (!entry->undo->req[i]) |
| continue; |
| DEBUGMSGTL(("tlstmCertToTSNTable:inconsistent", |
| "can't modify row %d while active\n", |
| _cols[i])); |
| entry->undo->is_consistent = 0; |
| ret = SNMP_ERR_NOTWRITABLE; |
| request= entry->undo->req[i]; |
| break; |
| } |
| } else if (RS_IS_GOING_ACTIVE(entry->rowStatus)) { |
| /* |
| * if going active, inconsistency is fatal |
| */ |
| if (!entry->undo->is_consistent) { |
| netsnmp_assert(entry->undo->req[COL_SNMPTLSTMCERTTOTSN_ROWSTATUS]); |
| if (FATE_NEWLY_CREATED == entry->undo->fate) |
| ret = SNMP_ERR_INCONSISTENTNAME; |
| else |
| ret = SNMP_ERR_INCONSISTENTVALUE; |
| request = entry->undo->req[COL_SNMPTLSTMCERTTOTSN_ROWSTATUS]; |
| } |
| } else if (RS_DESTROY == entry->rowStatus) { |
| /* |
| * can't destroy active row |
| */ |
| if (RS_IS_ACTIVE(entry->undo->rowStatus)) { |
| DEBUGMSGTL(("tlstmCertToTSNTable:inconsistent", |
| "can't destroy active row\n")); |
| netsnmp_assert(entry->undo->req[COL_SNMPTLSTMCERTTOTSN_ROWSTATUS]); |
| ret = SNMP_ERR_INCONSISTENTVALUE; |
| request = entry->undo->req[COL_SNMPTLSTMCERTTOTSN_ROWSTATUS]; |
| } |
| } |
| if (ret != SNMP_ERR_NOERROR) |
| break; |
| } /* consistency for requests */ |
| break; /* case MODE_SET_ACTION */ |
| |
| /** ######################################################## UNDO ##### |
| * |
| * UNDO is for cleaning up any failed requests that went through the |
| * ACTION phase. |
| * |
| * This the final phase for this path in the state machine. |
| */ |
| case MODE_SET_UNDO: |
| for (request = requests; request; request = request->next) { |
| row = netsnmp_tdata_extract_row(request); |
| entry = (certToTSN_entry *) netsnmp_tdata_extract_entry(request); |
| info = netsnmp_extract_table_info(request); |
| |
| /* |
| * skip newly created rows, as we're going to delete |
| * them below anyways |
| */ |
| if (FATE_NEWLY_CREATED == entry->undo->fate) |
| continue; |
| |
| /* |
| * restore values |
| */ |
| switch (info->colnum) { |
| case COL_SNMPTLSTMCERTTOTSN_FINGERPRINT: |
| memcpy(entry->fingerprint, entry->undo->fingerprint, |
| sizeof(entry->fingerprint)); |
| entry->fingerprint_len = entry->undo->fingerprint_len; |
| entry->hashType = entry->undo->hashType; |
| break; /* case COL_SNMPTLSTMCERTTOTSN_FINGERPRINT */ |
| case COL_SNMPTLSTMCERTTOTSN_MAPTYPE: |
| entry->mapType = entry->undo->mapType; |
| break; /* case COL_SNMPTLSTMCERTTOTSN_MAPTYPE */ |
| case COL_SNMPTLSTMCERTTOTSN_DATA: |
| memcpy(entry->data, entry->undo->data, sizeof(entry->data)); |
| entry->data_len = entry->undo->data_len; |
| break; /* case COL_SNMPTLSTMCERTTOTSN_DATA */ |
| case COL_SNMPTLSTMCERTTOTSN_STORAGETYPE: |
| entry->storageType = entry->undo->storageType; |
| break; /* case COL_SNMPTLSTMCERTTOTSN_STORAGETYPE */ |
| case COL_SNMPTLSTMCERTTOTSN_ROWSTATUS: |
| entry->rowStatus = entry->undo->rowStatus; |
| break; /* case COL_SNMPTLSTMCERTTOTSN_ROWSTATUS */ |
| } /* switch colnum */ |
| } /* for requests */ |
| |
| /* |
| * release undo data |
| * or remove any newly created rows |
| */ |
| for (request = requests; request; request = request->next) { |
| table = netsnmp_tdata_extract_table(request); |
| row = netsnmp_tdata_extract_row(request); |
| entry = (certToTSN_entry *) netsnmp_tdata_extract_entry(request); |
| |
| if (!entry || !entry->undo) |
| continue; |
| |
| /** disassociate row with requests */ |
| netsnmp_remove_tdata_row(request, row); |
| |
| if (FATE_NEWLY_CREATED == entry->undo->fate) |
| tlstmCertToTSNTable_removeEntry(table, row); |
| else |
| _freeUndo(entry); |
| } /* for requests */ |
| break; /* case MODE_SET_UNDO */ |
| |
| /** ###################################################### COMMIT ##### |
| * |
| * COMMIT is the final success state, when all changes are finalized. |
| * There is not recovery state should something faile here. |
| * |
| * This the final phase for this path in the state machine. |
| */ |
| case MODE_SET_COMMIT: |
| for (request = requests; request; request = request->next) { |
| row = netsnmp_tdata_extract_row(request); |
| table = netsnmp_tdata_extract_table(request); |
| info = netsnmp_extract_table_info(request); |
| entry = (certToTSN_entry *) netsnmp_tdata_extract_entry(request); |
| |
| if ((RS_NOTREADY == entry->rowStatus) && entry->undo->is_consistent) |
| entry->rowStatus = RS_NOTINSERVICE; |
| else if ((RS_NOTINSERVICE == entry->rowStatus) && |
| (0 == entry->undo->is_consistent)) |
| entry->rowStatus = RS_NOTREADY; |
| |
| /** release undo data for requests with no rowstatus */ |
| if (entry->undo && !entry->undo->req[COL_SNMPTLSTMCERTTOTSN_ROWSTATUS]) { |
| _freeUndo(entry); |
| if ((0 == entry->map_flags) && (entry->rowStatus == RS_ACTIVE)) |
| _cert_map_add(entry); |
| else if ((0 != entry->map_flags) && |
| (entry->rowStatus == RS_DESTROY)) |
| _cert_map_remove(entry); |
| } |
| |
| switch (info->colnum) { |
| case COL_SNMPTLSTMCERTTOTSN_ROWSTATUS: |
| switch (entry->rowStatus) { |
| case RS_CREATEANDGO: |
| /** Fall-through */ |
| case RS_ACTIVE: |
| netsnmp_assert(entry->undo->is_consistent); |
| entry->rowStatus = RS_ACTIVE; |
| if (0 == entry->map_flags) |
| _cert_map_add(entry); |
| break; |
| |
| case RS_CREATEANDWAIT: |
| /** Fall-through */ |
| case RS_NOTINSERVICE: |
| /** simply set status based on consistency */ |
| if (entry->undo->is_consistent) |
| entry->rowStatus = RS_NOTINSERVICE; |
| else |
| entry->rowStatus = RS_NOTREADY; |
| if (0 != entry->map_flags) |
| _cert_map_remove(entry); |
| break; |
| |
| case RS_DESTROY: |
| /** remove from cert map */ |
| if (0 != entry->map_flags) |
| _cert_map_remove(entry); |
| /** disassociate row with requests */ |
| netsnmp_remove_tdata_row(request, row); |
| tlstmCertToTSNTable_removeEntry(table, row); |
| row = NULL; |
| entry = NULL; |
| } |
| /** release undo data */ |
| _freeUndo(entry); |
| break; /* case COL_SNMPTLSTMCERTTOTSN_ROWSTATUS */ |
| |
| case COL_SNMPTLSTMCERTTOTSN_STORAGETYPE: |
| if (RS_ACTIVE == entry->rowStatus) |
| _cert_map_tweak_storage(entry); |
| break; /* case COL_SNMPTLSTMCERTTOTSN_STORAGETYPE */ |
| |
| case COL_SNMPTLSTMCERTTOTSN_FINGERPRINT: |
| case COL_SNMPTLSTMCERTTOTSN_MAPTYPE: |
| case COL_SNMPTLSTMCERTTOTSN_DATA: |
| break; |
| } /* switch colnum */ |
| |
| } /* for requests */ |
| |
| /** update last changed */ |
| _last_changed = netsnmp_get_agent_uptime(); |
| |
| /** set up to save persistent store */ |
| snmp_store_needed(NULL); |
| |
| break; /* case MODE_SET_COMMIT */ |
| } /* switch (reqinfo->mode) */ |
| |
| if (ret != SNMP_ERR_NOERROR) |
| netsnmp_set_request_error(reqinfo, request, ret); |
| |
| return SNMP_ERR_NOERROR; |
| } |
| |
| static int |
| _count_handler(netsnmp_mib_handler *handler, |
| netsnmp_handler_registration *reginfo, |
| netsnmp_agent_request_info *reqinfo, |
| netsnmp_request_info *requests) |
| { |
| int val; |
| |
| if (MODE_GET != reqinfo->mode) { |
| snmp_log(LOG_ERR, "bad mode in RO handler"); |
| return SNMP_ERR_GENERR; |
| } |
| |
| if (NULL == _table->container) |
| val = 0; |
| else |
| val = CONTAINER_SIZE(_table->container); |
| |
| snmp_set_var_typed_value(requests->requestvb, ASN_GAUGE, |
| (u_char *) &val, sizeof(val)); |
| |
| if (handler->next && handler->next->access_method) |
| return netsnmp_call_next_handler(handler, reginfo, reqinfo, |
| requests); |
| |
| return SNMP_ERR_NOERROR; |
| } |
| |
| static void |
| _cert_map_add(certToTSN_entry *entry) |
| { |
| netsnmp_cert_map *map; |
| |
| if (NULL == entry) |
| return; |
| |
| DEBUGMSGTL(("tlstmCertToTSNTable:map:add", "pri %ld, fp %s\n", |
| entry->tlstmCertToTSNID, entry->fingerprint)); |
| |
| map = netsnmp_cert_map_alloc(entry->fingerprint, NULL); |
| if (NULL == map) |
| return; |
| |
| map->priority = entry->tlstmCertToTSNID; |
| map->mapType = entry->mapType; |
| if (entry->data) |
| map->data = strdup(entry->data); |
| map->hashType = entry->hashType; |
| |
| map->flags = NSCM_FROM_MIB; |
| if (entry->storageType == ST_NONVOLATILE) |
| map->flags |= NSCM_NONVOLATILE; |
| |
| if (netsnmp_cert_map_add(map) != 0) |
| netsnmp_cert_map_free(map); |
| } |
| |
| static void |
| _cert_map_tweak_storage(certToTSN_entry *entry) |
| { |
| netsnmp_container *maps; |
| netsnmp_cert_map *map, index; |
| |
| if (NULL == entry) |
| return; |
| |
| DEBUGMSGTL(("tlstmCertToTSNTable:map:tweak", "pri %ld, st %d\n", |
| entry->tlstmCertToTSNID, entry->storageType)); |
| |
| /** get current active maps */ |
| maps = netsnmp_cert_map_container(); |
| if (NULL == maps) |
| return; |
| |
| index.priority = entry->tlstmCertToTSNID; |
| map = CONTAINER_FIND(maps, &index); |
| if (NULL == map) { |
| DEBUGMSGTL(("tlstmCertToTSNTable:map:tweak", "couldn't find map!\n")); |
| return; |
| } |
| |
| if (entry->storageType == ST_NONVOLATILE) |
| map->flags |= NSCM_NONVOLATILE; |
| else |
| map->flags &= ~NSCM_NONVOLATILE; |
| } |
| |
| static void |
| _cert_map_remove(certToTSN_entry *entry) |
| { |
| netsnmp_container *maps; |
| netsnmp_cert_map map; |
| |
| if (NULL == entry) |
| return; |
| |
| DEBUGMSGTL(("tlstmCertToTSNTable:map:remove", "pri %ld, fp %s\n", |
| entry->tlstmCertToTSNID, entry->fingerprint)); |
| |
| /** get current active maps */ |
| maps = netsnmp_cert_map_container(); |
| if (NULL == maps) |
| return; |
| |
| map.priority = entry->tlstmCertToTSNID; |
| map.fingerprint = entry->fingerprint; |
| |
| if (CONTAINER_REMOVE(maps, &map) != 0) { |
| snmp_log(LOG_ERR, "could not remove certificate map"); |
| } |
| entry->map_flags = 0; |
| } |
| |
| static netsnmp_tdata_row * |
| _entry_from_map(netsnmp_cert_map *map) |
| { |
| netsnmp_tdata_row *row; |
| certToTSN_entry *entry; |
| |
| row = tlstmCertToTSNTable_createEntry(NULL, map->priority); |
| if (NULL == row) { |
| snmp_log(LOG_ERR, "can create tlstmCertToTSN row entry\n"); |
| return NULL; |
| } |
| entry = row->data; |
| |
| if (map->flags & NSCM_FROM_CONFIG) |
| entry->storageType = ST_PERMANENT; |
| else if (! (map->flags & NSCM_NONVOLATILE)) |
| entry->storageType = ST_VOLATILE; |
| entry->map_flags = map->flags; |
| |
| entry->fingerprint_len = strlen(map->fingerprint); |
| if (entry->fingerprint_len > sizeof(entry->fingerprint)) |
| entry->fingerprint_len = sizeof(entry->fingerprint) - 1; |
| memcpy(entry->fingerprint, map->fingerprint, entry->fingerprint_len); |
| entry->fingerprint[sizeof(entry->fingerprint) - 1] = 0; |
| entry->hashType = map->hashType; |
| |
| if (map->data) { |
| entry->data_len = strlen(map->data); |
| if (entry->data_len) { |
| if (entry->data_len > sizeof(entry->data)) |
| entry->data_len = sizeof(entry->data) - 1; |
| memcpy(entry->data, map->data, entry->data_len); |
| entry->data[sizeof(entry->data) - 1] = 0; |
| } |
| } |
| entry->mapType = map->mapType; |
| |
| return row; |
| } |
| |
| static int |
| _cache_load(netsnmp_cache *cache, netsnmp_tdata *table) |
| { |
| netsnmp_container *maps; |
| netsnmp_iterator *map_itr; |
| netsnmp_cert_map *map; |
| netsnmp_tdata_row *row; |
| certToTSN_entry *entry; |
| int rc = 0; |
| |
| DEBUGMSGTL(("tlstmCertToTSNTable:cache:load", "called, %" NETSNMP_PRIz "d rows\n", |
| CONTAINER_SIZE(table->container))); |
| |
| /** get current active maps */ |
| maps = netsnmp_cert_map_container(); |
| if (NULL == maps) |
| return 0; |
| DEBUGMSGTL(("tlstmCertToTSNTable:cache:load", "maps %" NETSNMP_PRIz "d rows\n", |
| CONTAINER_SIZE(maps))); |
| |
| map_itr = CONTAINER_ITERATOR(maps); |
| if (NULL == map_itr) { |
| DEBUGMSGTL(("tlstmCertToTSNTable:cache:load", |
| "cant get map iterator\n")); |
| return -1; |
| } |
| |
| /* |
| * insert rows for active maps into tbl container |
| */ |
| map = ITERATOR_FIRST(map_itr); |
| for( ; map; map = ITERATOR_NEXT(map_itr)) { |
| |
| row = _entry_from_map(map); |
| if (NULL == row) { |
| rc =-1; |
| break; |
| } |
| entry = (certToTSN_entry*)row->data; |
| entry->rowStatus = RS_ACTIVE; |
| |
| if (netsnmp_tdata_add_row(table, row) != SNMPERR_SUCCESS) { |
| tlstmCertToTSNTable_removeEntry(NULL, row); |
| rc = -1; |
| break; |
| } |
| } |
| ITERATOR_RELEASE(map_itr); |
| |
| DEBUGMSGTL(("tlstmCertToTSNTable:cache:load", "done, %" NETSNMP_PRIz "d rows\n", |
| CONTAINER_SIZE(table->container))); |
| |
| return rc; |
| } |
| |
| static void |
| _cache_free(netsnmp_cache *cache, netsnmp_tdata *table) |
| { |
| netsnmp_tdata_row *row; |
| netsnmp_iterator *tbl_itr; |
| certToTSN_entry *entry; |
| |
| DEBUGMSGTL(("tlstmCertToTSNTable:cache:free", "called, %" NETSNMP_PRIz "d rows\n", |
| CONTAINER_SIZE(table->container))); |
| |
| /** insert rows for active maps into tbl container */ |
| tbl_itr = CONTAINER_ITERATOR(table->container); |
| if (NULL == tbl_itr) { |
| DEBUGMSGTL(("tlstmCertToTSNTable:cache:free", |
| "cant get map iterator\n")); |
| return; |
| } |
| |
| row = ITERATOR_FIRST(tbl_itr); |
| for( ; row; row = ITERATOR_NEXT(tbl_itr)) { |
| entry = row->data; |
| |
| /* |
| * remove all active rows (they are in the maps container kept |
| * by the library). Keep inactive ones for next time. |
| */ |
| if (entry->rowStatus == RS_ACTIVE) { |
| tlstmCertToTSNTable_removeEntry(NULL, row); |
| ITERATOR_REMOVE(tbl_itr); |
| continue; |
| } |
| } |
| ITERATOR_RELEASE(tbl_itr); |
| |
| DEBUGMSGTL(("tlstmCertToTSNTable:cache:free", "done, %" NETSNMP_PRIz "d rows\n", |
| CONTAINER_SIZE(table->container))); |
| } |
| |
| static void |
| _parse_mib_maps(const char *token, char *line) |
| { |
| netsnmp_tdata_row *row; |
| certToTSN_entry *entry; |
| netsnmp_cert_map *map = netsnmp_certToTSN_parse_common(&line); |
| |
| if (NULL == line) { |
| netsnmp_config_error("incomplete line"); |
| netsnmp_cert_map_free(map); |
| return; |
| } |
| |
| map->flags = NSCM_FROM_MIB | NSCM_NONVOLATILE; |
| row = _entry_from_map(map); |
| if (NULL == row) { |
| netsnmp_cert_map_free(map); |
| return; |
| } |
| |
| entry = (certToTSN_entry*)row->data; |
| entry->rowStatus = atoi(line); |
| entry->storageType = ST_NONVOLATILE; |
| |
| /* |
| * if row is active, add it to the maps container so it is available |
| * for use. Do not add it to the table, since it will be added |
| * during cache_load. |
| */ |
| if (RS_ACTIVE == entry->rowStatus) { |
| if (netsnmp_cert_map_add(map) != 0) |
| netsnmp_cert_map_free(map); |
| } |
| else { |
| netsnmp_cert_map_free(map); |
| if (netsnmp_tdata_add_row(_table, row) != SNMPERR_SUCCESS) |
| tlstmCertToTSNTable_removeEntry(NULL, row); |
| } |
| } |
| |
| static int |
| _save_entry(certToTSN_entry *entry, void *app_type) |
| { |
| char buf[SNMP_MAXBUF_SMALL], *hashType, *mapType, *data = NULL; |
| |
| if (NULL == entry) |
| return SNMP_ERR_GENERR; |
| |
| hashType = se_find_label_in_slist("cert_hash_alg", entry->hashType); |
| if (NULL == hashType) { |
| snmp_log(LOG_ERR, "skipping entry unknown hash type %d\n", |
| entry->hashType); |
| return SNMP_ERR_GENERR; |
| } |
| mapType = se_find_label_in_slist("cert_map_type", entry->mapType); |
| if (TSNM_tlstmCertSpecified == entry->mapType) |
| data = entry->data; |
| snprintf(buf, sizeof(buf), "%s %ld --%s %s --%s %s %d", |
| MAP_MIB_CONFIG_TOKEN, entry->tlstmCertToTSNID, hashType, |
| entry->fingerprint, mapType, data ? data : "", entry->rowStatus); |
| |
| DEBUGMSGTL(("tlstmCertToTSNTable:save", "saving '%s'\n", buf)); |
| read_config_store(app_type, buf); |
| |
| return SNMP_ERR_NOERROR; |
| } |
| |
| static int |
| _save_map(netsnmp_cert_map *map, int row_status, void *app_type) |
| { |
| char buf[SNMP_MAXBUF_SMALL], *hashType, *mapType, *data = NULL; |
| |
| if (NULL == map) |
| return SNMP_ERR_GENERR; |
| |
| /** don't store values from conf files */ |
| if (! (map->flags & NSCM_NONVOLATILE)) { |
| DEBUGMSGT(("tlstmCertToTSNTable:save", |
| "skipping RO/permanent/volatile row\n")); |
| return SNMP_ERR_NOERROR; |
| } |
| |
| hashType = se_find_label_in_slist("cert_hash_alg", map->hashType); |
| if (NULL == hashType) { |
| snmp_log(LOG_ERR, "skipping entry unknown hash type %d\n", |
| map->hashType); |
| return SNMP_ERR_GENERR; |
| } |
| mapType = se_find_label_in_slist("cert_map_type", map->mapType); |
| if (TSNM_tlstmCertSpecified == map->mapType) |
| data = (char*)map->data; |
| snprintf(buf, sizeof(buf), "%s %d --%s %s --%s %s %d", |
| MAP_MIB_CONFIG_TOKEN, map->priority, hashType, map->fingerprint, |
| mapType, data ? data : "", row_status); |
| |
| DEBUGMSGTL(("tlstmCertToTSNTable:save", "saving '%s'\n", buf)); |
| read_config_store(app_type, buf); |
| |
| return SNMP_ERR_NOERROR; |
| } |
| |
| static int |
| _save_maps(int majorID, int minorID, void *serverarg, void *clientarg) |
| { |
| char sep[] = |
| "\n##############################################################"; |
| char buf[] = |
| "#\n" "# certificate secName mapping persistent data\n" "#"; |
| char *type = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, |
| NETSNMP_DS_LIB_APPTYPE); |
| netsnmp_container *maps = netsnmp_cert_map_container(); |
| netsnmp_tdata_row *row; |
| netsnmp_iterator *tbl_itr, *map_itr; |
| netsnmp_cert_map *map; |
| certToTSN_entry *entry; |
| |
| if ((NULL == maps) || ((CONTAINER_SIZE(maps) == 0) && |
| (CONTAINER_SIZE(_table->container) == 0))) |
| return SNMPERR_SUCCESS; |
| |
| read_config_store((char *) type, sep); |
| read_config_store((char *) type, buf); |
| |
| /* |
| * save active rows from maps |
| */ |
| if (NULL != maps) { |
| map_itr = CONTAINER_ITERATOR(maps); |
| if (NULL == map_itr) { |
| DEBUGMSGTL(("tlstmCertToTSNTable:save", |
| "cant get map iterator\n")); |
| map = NULL; |
| } |
| else |
| map = ITERATOR_FIRST(map_itr); |
| |
| for( ; map; map = ITERATOR_NEXT(map_itr)) { |
| /** don't store config rows */ |
| if (map->flags & NSCM_FROM_CONFIG) |
| continue; |
| _save_map(map, RS_ACTIVE, type); |
| } |
| } |
| ITERATOR_RELEASE(map_itr); |
| |
| /* |
| * save inactive rows from mib |
| */ |
| tbl_itr = CONTAINER_ITERATOR(_table->container); |
| if (NULL == tbl_itr) |
| DEBUGMSGTL(("tlstmCertToTSNTable:save", "cant get table iterator\n")); |
| else { |
| row = ITERATOR_FIRST(tbl_itr); |
| for( ; row; row = ITERATOR_NEXT(tbl_itr)) { |
| entry = row->data; |
| |
| /* |
| * skip all active rows (should be in maps and thus saved |
| * above) and volatile rows. |
| */ |
| if ((entry->rowStatus == RS_ACTIVE) || |
| (entry->storageType != ST_NONVOLATILE)) |
| continue; |
| |
| _save_entry(entry, type); |
| } |
| ITERATOR_RELEASE(tbl_itr); |
| } |
| |
| read_config_store((char *) type, sep); |
| read_config_store((char *) type, "\n"); |
| |
| /* |
| * never fails |
| */ |
| return SNMPERR_SUCCESS; |
| } |
| |
| |
| static const oid _tsnm_base[] = { SNMP_TLS_TM_BASE, 1, 1 }; |
| static const int _tsnm_base_len = sizeof(_tsnm_base); |
| |
| static oid |
| _oid2type(oid *val, int val_len) |
| { |
| netsnmp_assert(val); |
| |
| if (val_len != (_tsnm_base_len + sizeof(oid))) |
| return -1; |
| |
| if (memcmp(_tsnm_base,val,_tsnm_base_len) != 0) |
| return -2; |
| |
| if ((val[OID_LENGTH(_tsnm_base)] > TSNM_tlstmCert_MAX) || |
| (0 == val[OID_LENGTH(_tsnm_base)])) |
| return -3; |
| |
| return val[OID_LENGTH(_tsnm_base)]; |
| } |
| |
| #if 0 |
| static int |
| _type2oid(int type, oid *val, int *val_len) |
| { |
| netsnmp_assert( val && val_len ); |
| |
| if (*val_len < _tsnm_base_len + sizeof(oid)) |
| return -1; |
| |
| memcpy(val, _tsnm_base, _tsnm_base_len + sizeof(oid)); |
| val[_tsnm_base_len + sizeof(oid)] = type; |
| |
| return 0; |
| } |
| #endif |