00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00036
00037
00038
00039 #include <net-snmp/net-snmp-config.h>
00040
00041 #include <stdio.h>
00042 #include <ctype.h>
00043 #if HAVE_STDLIB_H
00044 #include <stdlib.h>
00045 #endif
00046 #if HAVE_STRING_H
00047 #include <string.h>
00048 #else
00049 #include <strings.h>
00050 #endif
00051 #if HAVE_UNISTD_H
00052 #include <unistd.h>
00053 #endif
00054 #include <sys/types.h>
00055 #if HAVE_SYS_PARAM_H
00056 #include <sys/param.h>
00057 #endif
00058 #if TIME_WITH_SYS_TIME
00059 # ifdef WIN32
00060 # include <sys/timeb.h>
00061 # else
00062 # include <sys/time.h>
00063 # endif
00064 # include <time.h>
00065 #else
00066 # if HAVE_SYS_TIME_H
00067 # include <sys/time.h>
00068 # else
00069 # include <time.h>
00070 # endif
00071 #endif
00072 #if HAVE_NETINET_IN_H
00073 #include <netinet/in.h>
00074 #endif
00075 #if HAVE_ARPA_INET_H
00076 #include <arpa/inet.h>
00077 #endif
00078 #if HAVE_SYS_SELECT_H
00079 #include <sys/select.h>
00080 #endif
00081 #if HAVE_IO_H
00082 #include <io.h>
00083 #endif
00084 #if HAVE_WINSOCK_H
00085 #include <winsock.h>
00086 #endif
00087 #if HAVE_SYS_SOCKET_H
00088 #include <sys/socket.h>
00089 #endif
00090 #if HAVE_SYS_UN_H
00091 #include <sys/un.h>
00092 #endif
00093 #if HAVE_NETDB_H
00094 #include <netdb.h>
00095 #endif
00096 #if HAVE_NET_IF_DL_H
00097 #ifndef dynix
00098 #include <net/if_dl.h>
00099 #else
00100 #include <sys/net/if_dl.h>
00101 #endif
00102 #endif
00103 #include <errno.h>
00104
00105 #if HAVE_LOCALE_H
00106 #include <locale.h>
00107 #endif
00108
00109 #if HAVE_DMALLOC_H
00110 #include <dmalloc.h>
00111 #endif
00112
00113 #define SNMP_NEED_REQUEST_LIST
00114 #include <net-snmp/types.h>
00115 #include <net-snmp/output_api.h>
00116 #include <net-snmp/config_api.h>
00117 #include <net-snmp/utilities.h>
00118
00119 #include <net-snmp/library/asn1.h>
00120 #include <net-snmp/library/snmp.h>
00121 #include <net-snmp/library/snmp_api.h>
00122 #include <net-snmp/library/snmp_client.h>
00123 #include <net-snmp/library/parse.h>
00124 #include <net-snmp/library/mib.h>
00125 #include <net-snmp/library/int64.h>
00126 #include <net-snmp/library/snmpv3.h>
00127 #include <net-snmp/library/callback.h>
00128 #include <net-snmp/library/container.h>
00129 #include <net-snmp/library/snmp_secmod.h>
00130 #include <net-snmp/library/large_fd_set.h>
00131 #ifdef NETSNMP_SECMOD_USM
00132 #include <net-snmp/library/snmpusm.h>
00133 #endif
00134 #ifdef NETSNMP_SECMOD_KSM
00135 #include <net-snmp/library/snmpksm.h>
00136 #endif
00137 #include <net-snmp/library/keytools.h>
00138 #include <net-snmp/library/lcd_time.h>
00139 #include <net-snmp/library/snmp_alarm.h>
00140 #include <net-snmp/library/snmp_transport.h>
00141 #include <net-snmp/library/snmp_service.h>
00142 #include <net-snmp/library/vacm.h>
00143
00144 static void _init_snmp(void);
00145
00146 #include "../agent/mibgroup/agentx/protocol.h"
00147 #include <net-snmp/library/transform_oids.h>
00148 #ifndef timercmp
00149 #define timercmp(tvp, uvp, cmp) \
00150 \
00151 ((tvp)->tv_sec cmp (uvp)->tv_sec || \
00152 ((tvp)->tv_sec == (uvp)->tv_sec && \
00153 \
00154 (tvp)->tv_usec cmp (uvp)->tv_usec))
00155 #endif
00156 #ifndef timerclear
00157 #define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0
00158 #endif
00159
00160
00161
00162
00163 #define MAX_PACKET_LENGTH (0x7fffffff)
00164 #ifndef NETSNMP_STREAM_QUEUE_LEN
00165 #define NETSNMP_STREAM_QUEUE_LEN 5
00166 #endif
00167
00168 #ifndef BSD4_3
00169 #define BSD4_2
00170 #endif
00171
00172 #ifndef FD_SET
00173
00174 typedef long fd_mask;
00175 #define NFDBITS (sizeof(fd_mask) * NBBY)
00176
00177 #define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
00178 #define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
00179 #define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
00180 #define FD_ZERO(p) memset((p), 0, sizeof(*(p)))
00181 #endif
00182
00183 static oid default_enterprise[] = { 1, 3, 6, 1, 4, 1, 3, 1, 1 };
00184
00185
00186
00187
00188 #define DEFAULT_COMMUNITY "public"
00189 #define DEFAULT_RETRIES 5
00190 #define DEFAULT_TIMEOUT 1000000L
00191 #define DEFAULT_REMPORT SNMP_PORT
00192 #define DEFAULT_ENTERPRISE default_enterprise
00193 #define DEFAULT_TIME 0
00194
00195
00196
00197
00198
00199 #define MAXIMUM_PACKET_SIZE 0x7fffffff
00200
00201
00202
00203
00204 struct snmp_internal_session {
00205 netsnmp_request_list *requests;
00206 netsnmp_request_list *requestsEnd;
00207 int (*hook_pre) (netsnmp_session *, netsnmp_transport *,
00208 void *, int);
00209 int (*hook_parse) (netsnmp_session *, netsnmp_pdu *,
00210 u_char *, size_t);
00211 int (*hook_post) (netsnmp_session *, netsnmp_pdu *, int);
00212 int (*hook_build) (netsnmp_session *, netsnmp_pdu *,
00213 u_char *, size_t *);
00214 int (*hook_realloc_build) (netsnmp_session *,
00215 netsnmp_pdu *, u_char **,
00216 size_t *, size_t *);
00217 int (*check_packet) (u_char *, size_t);
00218 netsnmp_pdu *(*hook_create_pdu) (netsnmp_transport *,
00219 void *, size_t);
00220
00221 u_char *packet;
00222 size_t packet_len, packet_size;
00223 };
00224
00225
00226
00227
00228 struct session_list {
00229 struct session_list *next;
00230 netsnmp_session *session;
00231 netsnmp_transport *transport;
00232 struct snmp_internal_session *internal;
00233 };
00234
00235
00236
00237 static const char *api_errors[-SNMPERR_MAX + 1] = {
00238 "No error",
00239 "Generic error",
00240 "Invalid local port",
00241 "Unknown host",
00242 "Unknown session",
00243 "Too long",
00244 "No socket",
00245 "Cannot send V2 PDU on V1 session",
00246 "Cannot send V1 PDU on V2 session",
00247 "Bad value for non-repeaters",
00248 "Bad value for max-repetitions",
00249 "Error building ASN.1 representation",
00250 "Failure in sendto",
00251 "Bad parse of ASN.1 type",
00252 "Bad version specified",
00253 "Bad source party specified",
00254 "Bad destination party specified",
00255 "Bad context specified",
00256 "Bad community specified",
00257 "Cannot send noAuth/Priv",
00258 "Bad ACL definition",
00259 "Bad Party definition",
00260 "Session abort failure",
00261 "Unknown PDU type",
00262 "Timeout",
00263 "Failure in recvfrom",
00264 "Unable to determine contextEngineID",
00265 "No securityName specified",
00266 "Unable to determine securityLevel",
00267 "ASN.1 parse error in message",
00268 "Unknown security model in message",
00269 "Invalid message (e.g. msgFlags)",
00270 "Unknown engine ID",
00271 "Unknown user name",
00272 "Unsupported security level",
00273 "Authentication failure (incorrect password, community or key)",
00274 "Not in time window",
00275 "Decryption error",
00276 "SCAPI general failure",
00277 "SCAPI sub-system not configured",
00278 "Key tools not available",
00279 "Unknown Report message",
00280 "USM generic error",
00281 "USM unknown security name (no such user exists)",
00282 "USM unsupported security level (this user has not been configured for that level of security)",
00283 "USM encryption error",
00284 "USM authentication failure (incorrect password or key)",
00285 "USM parse error",
00286 "USM unknown engineID",
00287 "USM not in time window",
00288 "USM decryption error",
00289 "MIB not initialized",
00290 "Value out of range",
00291 "Sub-id out of range",
00292 "Bad sub-id in object identifier",
00293 "Object identifier too long",
00294 "Bad value name",
00295 "Bad value notation",
00296 "Unknown Object Identifier",
00297 "No PDU in snmp_send",
00298 "Missing variables in PDU",
00299 "Bad variable type",
00300 "Out of memory (malloc failure)",
00301 "Kerberos related error",
00302 "Protocol error",
00303 "OID not increasing",
00304 };
00305
00306 static const char *secLevelName[] = {
00307 "BAD_SEC_LEVEL",
00308 "noAuthNoPriv",
00309 "authNoPriv",
00310 "authPriv"
00311 };
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326 struct session_list *Sessions = NULL;
00327 static long Reqid = 0;
00328 static long Msgid = 0;
00329 static long Sessid = 0;
00330 static long Transid = 0;
00331 int snmp_errno = 0;
00332
00333
00334
00335
00336
00337
00338
00339 static char snmp_detail[192];
00340 static int snmp_detail_f = 0;
00341
00342
00343
00344
00345 int snmp_build(u_char ** pkt, size_t * pkt_len,
00346 size_t * offset, netsnmp_session * pss,
00347 netsnmp_pdu *pdu);
00348 static int snmp_parse(void *, netsnmp_session *, netsnmp_pdu *,
00349 u_char *, size_t);
00350
00351 static void snmpv3_calc_msg_flags(int, int, u_char *);
00352 static int snmpv3_verify_msg(netsnmp_request_list *, netsnmp_pdu *);
00353 static int snmpv3_build_probe_pdu(netsnmp_pdu **);
00354 static int snmpv3_build(u_char ** pkt, size_t * pkt_len,
00355 size_t * offset, netsnmp_session * session,
00356 netsnmp_pdu *pdu);
00357 static int snmp_parse_version(u_char *, size_t);
00358 static int snmp_resend_request(struct session_list *slp,
00359 netsnmp_request_list *rp,
00360 int incr_retries);
00361 static void register_default_handlers(void);
00362 static struct session_list *snmp_sess_copy(netsnmp_session * pss);
00363 int snmp_get_errno(void);
00364 void snmp_synch_reset(netsnmp_session * notused);
00365 void snmp_synch_setup(netsnmp_session * notused);
00366
00367 #ifndef HAVE_STRERROR
00368 const char *
00369 strerror(int err)
00370 {
00371 extern const char *sys_errlist[];
00372 extern int sys_nerr;
00373
00374 if (err < 0 || err >= sys_nerr)
00375 return "Unknown error";
00376 return sys_errlist[err];
00377 }
00378 #endif
00379
00380 const char *
00381 snmp_pdu_type(int type)
00382 {
00383 static char unknown[20];
00384 switch(type) {
00385 case SNMP_MSG_GET:
00386 return "GET";
00387 case SNMP_MSG_GETNEXT:
00388 return "GETNEXT";
00389 case SNMP_MSG_RESPONSE:
00390 return "RESPONSE";
00391 case SNMP_MSG_SET:
00392 return "SET";
00393 case SNMP_MSG_GETBULK:
00394 return "GETBULK";
00395 case SNMP_MSG_INFORM:
00396 return "INFORM";
00397 case SNMP_MSG_TRAP2:
00398 return "TRAP2";
00399 case SNMP_MSG_REPORT:
00400 return "REPORT";
00401 default:
00402 snprintf(unknown, sizeof(unknown), "?0x%2X?", type);
00403 return unknown;
00404 }
00405 }
00406
00407 #define DEBUGPRINTPDUTYPE(token, type) \
00408 DEBUGDUMPSECTION(token, snmp_pdu_type(type))
00409
00410 long
00411 snmp_get_next_reqid(void)
00412 {
00413 long retVal;
00414 snmp_res_lock(MT_LIBRARY_ID, MT_LIB_REQUESTID);
00415 retVal = 1 + Reqid;
00416 if (!retVal)
00417 retVal = 2;
00418 Reqid = retVal;
00419 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_16BIT_IDS))
00420 retVal &= 0x7fff;
00421 else
00422 retVal &= 0x7fffffff;
00423
00424 if (!retVal) {
00425 Reqid = retVal = 2;
00426 }
00427 snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_REQUESTID);
00428 return retVal;
00429 }
00430
00431 long
00432 snmp_get_next_msgid(void)
00433 {
00434 long retVal;
00435 snmp_res_lock(MT_LIBRARY_ID, MT_LIB_MESSAGEID);
00436 retVal = 1 + Msgid;
00437 if (!retVal)
00438 retVal = 2;
00439 Msgid = retVal;
00440 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_16BIT_IDS))
00441 retVal &= 0x7fff;
00442 else
00443 retVal &= 0x7fffffff;
00444
00445 if (!retVal) {
00446 Msgid = retVal = 2;
00447 }
00448 snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_MESSAGEID);
00449 return retVal;
00450 }
00451
00452 long
00453 snmp_get_next_sessid(void)
00454 {
00455 long retVal;
00456 snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSIONID);
00457 retVal = 1 + Sessid;
00458 if (!retVal)
00459 retVal = 2;
00460 Sessid = retVal;
00461 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_16BIT_IDS))
00462 retVal &= 0x7fff;
00463 else
00464 retVal &= 0x7fffffff;
00465
00466 if (!retVal) {
00467 Sessid = retVal = 2;
00468 }
00469 snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSIONID);
00470 return retVal;
00471 }
00472
00473 long
00474 snmp_get_next_transid(void)
00475 {
00476 long retVal;
00477 snmp_res_lock(MT_LIBRARY_ID, MT_LIB_TRANSID);
00478 retVal = 1 + Transid;
00479 if (!retVal)
00480 retVal = 2;
00481 Transid = retVal;
00482 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_16BIT_IDS))
00483 retVal &= 0x7fff;
00484 else
00485 retVal &= 0x7fffffff;
00486
00487 if (!retVal) {
00488 Transid = retVal = 2;
00489 }
00490 snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_TRANSID);
00491 return retVal;
00492 }
00493
00494 void
00495 snmp_perror(const char *prog_string)
00496 {
00497 const char *str;
00498 int xerr;
00499 xerr = snmp_errno;
00500 str = snmp_api_errstring(xerr);
00501 snmp_log(LOG_ERR, "%s: %s\n", prog_string, str);
00502 }
00503
00504 void
00505 snmp_set_detail(const char *detail_string)
00506 {
00507 if (detail_string != NULL) {
00508 strncpy((char *) snmp_detail, detail_string, sizeof(snmp_detail));
00509 snmp_detail[sizeof(snmp_detail) - 1] = '\0';
00510 snmp_detail_f = 1;
00511 }
00512 }
00513
00514
00515
00516
00517
00518
00519
00520 const char *
00521 snmp_api_errstring(int snmp_errnumber)
00522 {
00523 const char *msg = "";
00524 static char msg_buf[SPRINT_MAX_LEN];
00525 if (snmp_errnumber >= SNMPERR_MAX && snmp_errnumber <= SNMPERR_GENERR) {
00526 msg = api_errors[-snmp_errnumber];
00527 } else if (snmp_errnumber != SNMPERR_SUCCESS) {
00528 msg = NULL;
00529 }
00530 if (!msg)
00531 snprintf(msg_buf, sizeof(msg_buf), "Unknown error: %d", snmp_errnumber);
00532 else if (snmp_detail_f) {
00533 snprintf(msg_buf, sizeof(msg_buf), "%s (%s)", msg, snmp_detail);
00534 snmp_detail_f = 0;
00535 } else {
00536 strncpy(msg_buf, msg, sizeof(msg_buf));
00537 }
00538 msg_buf[sizeof(msg_buf)-1] = '\0';
00539
00540 return (msg_buf);
00541 }
00542
00543
00544
00545
00546
00547
00548 void
00549 snmp_error(netsnmp_session * psess,
00550 int *p_errno, int *p_snmp_errno, char **p_str)
00551 {
00552 char buf[SPRINT_MAX_LEN];
00553 int snmp_errnumber;
00554
00555 if (p_errno)
00556 *p_errno = psess->s_errno;
00557 if (p_snmp_errno)
00558 *p_snmp_errno = psess->s_snmp_errno;
00559 if (p_str == NULL)
00560 return;
00561
00562 strcpy(buf, "");
00563 snmp_errnumber = psess->s_snmp_errno;
00564 if (snmp_errnumber >= SNMPERR_MAX && snmp_errnumber <= SNMPERR_GENERR) {
00565 if (snmp_detail_f) {
00566 snprintf(buf, sizeof(buf), "%s (%s)", api_errors[-snmp_errnumber],
00567 snmp_detail);
00568 snmp_detail_f = 0;
00569 }
00570 else
00571 strncpy(buf, api_errors[-snmp_errnumber], sizeof(buf));
00572 } else {
00573 if (snmp_errnumber)
00574 snprintf(buf, sizeof(buf), "Unknown Error %d", snmp_errnumber);
00575 }
00576 buf[sizeof(buf)-1] = '\0';
00577
00578
00579
00580
00581 if (psess->s_errno) {
00582 const char* error = strerror(psess->s_errno);
00583 if(error == NULL)
00584 error = "Unknown Error";
00585 snprintf (&buf[strlen(buf)], sizeof(buf)-strlen(buf),
00586 " (%s)", error);
00587 }
00588 buf[sizeof(buf)-1] = '\0';
00589 *p_str = strdup(buf);
00590 }
00591
00592
00593
00594
00595 void
00596 snmp_sess_error(void *sessp, int *p_errno, int *p_snmp_errno, char **p_str)
00597 {
00598 struct session_list *slp = (struct session_list *) sessp;
00599
00600 if ((slp) && (slp->session))
00601 snmp_error(slp->session, p_errno, p_snmp_errno, p_str);
00602 }
00603
00604
00605
00606
00607 void
00608 netsnmp_sess_log_error(int priority,
00609 const char *prog_string, netsnmp_session * ss)
00610 {
00611 char *err;
00612 snmp_error(ss, NULL, NULL, &err);
00613 snmp_log(priority, "%s: %s\n", prog_string, err);
00614 SNMP_FREE(err);
00615 }
00616
00617
00618
00619
00620 void
00621 snmp_sess_perror(const char *prog_string, netsnmp_session * ss)
00622 {
00623 netsnmp_sess_log_error(LOG_ERR, prog_string, ss);
00624 }
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638 static char _init_snmp_init_done = 0;
00639 static void
00640 _init_snmp(void)
00641 {
00642
00643 struct timeval tv;
00644 long tmpReqid, tmpMsgid;
00645
00646 if (_init_snmp_init_done)
00647 return;
00648 _init_snmp_init_done = 1;
00649 Reqid = 1;
00650
00651 snmp_res_init();
00652 #ifndef NETSNMP_DISABLE_MIB_LOADING
00653 netsnmp_init_mib_internals();
00654 #endif
00655 netsnmp_tdomain_init();
00656
00657 gettimeofday(&tv, (struct timezone *) 0);
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668 #ifdef SVR4
00669 srand48(tv.tv_sec ^ tv.tv_usec);
00670 tmpReqid = lrand48();
00671 tmpMsgid = lrand48();
00672 #else
00673 srandom(tv.tv_sec ^ tv.tv_usec);
00674 tmpReqid = random();
00675 tmpMsgid = random();
00676 #endif
00677
00678 if (tmpReqid == 0)
00679 tmpReqid = 1;
00680 if (tmpMsgid == 0)
00681 tmpMsgid = 1;
00682 Reqid = tmpReqid;
00683 Msgid = tmpMsgid;
00684
00685 netsnmp_register_default_domain("snmp", "udp udp6");
00686 netsnmp_register_default_domain("snmptrap", "udp udp6");
00687
00688 netsnmp_register_default_target("snmp", "udp", ":161");
00689 netsnmp_register_default_target("snmp", "tcp", ":161");
00690 netsnmp_register_default_target("snmp", "udp6", ":161");
00691 netsnmp_register_default_target("snmp", "tcp6", ":161");
00692 netsnmp_register_default_target("snmp", "ipx", "/36879");
00693 netsnmp_register_default_target("snmptrap", "udp", ":162");
00694 netsnmp_register_default_target("snmptrap", "tcp", ":162");
00695 netsnmp_register_default_target("snmptrap", "udp6", ":162");
00696 netsnmp_register_default_target("snmptrap", "tcp6", ":162");
00697 netsnmp_register_default_target("snmptrap", "ipx", "/36880");
00698
00699 netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
00700 NETSNMP_DS_LIB_HEX_OUTPUT_LENGTH, 16);
00701
00702 #ifdef NETSNMP_USE_REVERSE_ASNENCODING
00703 netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
00704 NETSNMP_DS_LIB_REVERSE_ENCODE,
00705 NETSNMP_DEFAULT_ASNENCODING_DIRECTION);
00706 #endif
00707 }
00708
00709
00710
00711
00712
00713
00714 void
00715 snmp_sess_init(netsnmp_session * session)
00716 {
00717 _init_snmp();
00718
00719
00720
00721
00722
00723 memset(session, 0, sizeof(netsnmp_session));
00724 session->remote_port = SNMP_DEFAULT_REMPORT;
00725 session->timeout = SNMP_DEFAULT_TIMEOUT;
00726 session->retries = SNMP_DEFAULT_RETRIES;
00727 session->version = SNMP_DEFAULT_VERSION;
00728 session->securityModel = SNMP_DEFAULT_SECMODEL;
00729 session->rcvMsgMaxSize = SNMP_MAX_MSG_SIZE;
00730 session->flags |= SNMP_FLAGS_DONT_PROBE;
00731 }
00732
00733
00734 static void
00735 register_default_handlers(void)
00736 {
00737 netsnmp_ds_register_config(ASN_BOOLEAN, "snmp", "dumpPacket",
00738 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DUMP_PACKET);
00739 netsnmp_ds_register_config(ASN_BOOLEAN, "snmp", "reverseEncodeBER",
00740 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_REVERSE_ENCODE);
00741 netsnmp_ds_register_config(ASN_INTEGER, "snmp", "defaultPort",
00742 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DEFAULT_PORT);
00743 #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
00744 netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "defCommunity",
00745 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_COMMUNITY);
00746 #endif
00747 netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "noTokenWarnings",
00748 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NO_TOKEN_WARNINGS);
00749 netsnmp_ds_register_config(ASN_BOOLEAN, "snmp", "noRangeCheck",
00750 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_CHECK_RANGE);
00751 netsnmp_ds_register_premib(ASN_OCTET_STR, "snmp", "persistentDir",
00752 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PERSISTENT_DIR);
00753 netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "tempFilePattern",
00754 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_TEMP_FILE_PATTERN);
00755 netsnmp_ds_register_config(ASN_BOOLEAN, "snmp", "noDisplayHint",
00756 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NO_DISPLAY_HINT);
00757 netsnmp_ds_register_config(ASN_BOOLEAN, "snmp", "16bitIDs",
00758 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_16BIT_IDS);
00759 netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "clientaddr",
00760 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_CLIENT_ADDR);
00761 netsnmp_ds_register_config(ASN_INTEGER, "snmp", "serverSendBuf",
00762 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_SERVERSENDBUF);
00763 netsnmp_ds_register_config(ASN_INTEGER, "snmp", "serverRecvBuf",
00764 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_SERVERRECVBUF);
00765 netsnmp_ds_register_config(ASN_INTEGER, "snmp", "clientSendBuf",
00766 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_CLIENTSENDBUF);
00767 netsnmp_ds_register_config(ASN_INTEGER, "snmp", "clientRecvBuf",
00768 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_CLIENTRECVBUF);
00769 netsnmp_ds_register_config(ASN_BOOLEAN, "snmp", "noPersistentLoad",
00770 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DISABLE_PERSISTENT_LOAD);
00771 netsnmp_ds_register_config(ASN_BOOLEAN, "snmp", "noPersistentSave",
00772 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DISABLE_PERSISTENT_SAVE);
00773 netsnmp_ds_register_config(ASN_BOOLEAN, "snmp",
00774 "noContextEngineIDDiscovery",
00775 NETSNMP_DS_LIBRARY_ID,
00776 NETSNMP_DS_LIB_NO_DISCOVERY);
00777
00778 netsnmp_register_service_handlers();
00779 }
00780
00781 static int init_snmp_init_done = 0;
00792 void
00793 init_snmp(const char *type)
00794 {
00795 if (init_snmp_init_done) {
00796 return;
00797 }
00798
00799 init_snmp_init_done = 1;
00800
00801
00802
00803
00804 if (type && !netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
00805 NETSNMP_DS_LIB_APPTYPE)) {
00806 netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID,
00807 NETSNMP_DS_LIB_APPTYPE, type);
00808 }
00809
00810 _init_snmp();
00811
00812
00813
00814
00815 #ifdef HAVE_SETLOCALE
00816 setlocale(LC_CTYPE, "");
00817 #endif
00818
00819 snmp_debug_init();
00820 netsnmp_container_init_list();
00821 init_callbacks();
00822 init_snmp_logging();
00823 snmp_init_statistics();
00824 register_mib_handlers();
00825 register_default_handlers();
00826 init_snmpv3(type);
00827 init_snmp_alarm();
00828 init_snmp_enum(type);
00829 init_vacm();
00830
00831 read_premib_configs();
00832 #ifndef NETSNMP_DISABLE_MIB_LOADING
00833 netsnmp_init_mib();
00834 #endif
00835
00836 read_configs();
00837
00838 }
00839
00840 void
00841 snmp_store(const char *type)
00842 {
00843 DEBUGMSGTL(("snmp_store", "storing stuff...\n"));
00844 snmp_save_persistent(type);
00845 snmp_call_callbacks(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA, NULL);
00846 snmp_clean_persistent(type);
00847 }
00848
00849
00858 void
00859 snmp_shutdown(const char *type)
00860 {
00861 snmp_store(type);
00862 snmp_call_callbacks(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_SHUTDOWN, NULL);
00863 shutdown_snmp_logging();
00864 snmp_alarm_unregister_all();
00865 snmp_close_sessions();
00866 #ifndef NETSNMP_DISABLE_MIB_LOADING
00867 shutdown_mib();
00868 #endif
00869 unregister_all_config_handlers();
00870 netsnmp_container_free_list();
00871 clear_sec_mod();
00872 clear_snmp_enum();
00873 netsnmp_clear_tdomain_list();
00874 clear_callback();
00875 netsnmp_ds_shutdown();
00876 clear_user_list();
00877 netsnmp_clear_default_target();
00878 netsnmp_clear_default_domain();
00879 free_etimelist();
00880
00881 init_snmp_init_done = 0;
00882 _init_snmp_init_done = 0;
00883 }
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893 netsnmp_session *
00894 snmp_open(netsnmp_session *session)
00895 {
00896 struct session_list *slp;
00897 slp = (struct session_list *) snmp_sess_open(session);
00898 if (!slp) {
00899 return NULL;
00900 }
00901
00902 snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION);
00903 slp->next = Sessions;
00904 Sessions = slp;
00905 snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION);
00906
00907 return (slp->session);
00908 }
00909
00910
00911
00912
00913 netsnmp_session *
00914 snmp_open_ex(netsnmp_session *session,
00915 int (*fpre_parse) (netsnmp_session *, netsnmp_transport *,
00916 void *, int),
00917 int (*fparse) (netsnmp_session *, netsnmp_pdu *, u_char *,
00918 size_t),
00919 int (*fpost_parse) (netsnmp_session *, netsnmp_pdu *, int),
00920
00921 int (*fbuild) (netsnmp_session *, netsnmp_pdu *, u_char *,
00922 size_t *),
00923 int (*frbuild) (netsnmp_session *, netsnmp_pdu *,
00924 u_char **, size_t *, size_t *),
00925 int (*fcheck) (u_char *, size_t)
00926 )
00927 {
00928 struct session_list *slp;
00929 slp = (struct session_list *) snmp_sess_open(session);
00930 if (!slp) {
00931 return NULL;
00932 }
00933 slp->internal->hook_pre = fpre_parse;
00934 slp->internal->hook_parse = fparse;
00935 slp->internal->hook_post = fpost_parse;
00936 slp->internal->hook_build = fbuild;
00937 slp->internal->hook_realloc_build = frbuild;
00938 slp->internal->check_packet = fcheck;
00939
00940 snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION);
00941 slp->next = Sessions;
00942 Sessions = slp;
00943 snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION);
00944
00945 return (slp->session);
00946 }
00947
00948 static struct session_list *
00949 _sess_copy(netsnmp_session * in_session)
00950 {
00951 struct session_list *slp;
00952 struct snmp_internal_session *isp;
00953 netsnmp_session *session;
00954 struct snmp_secmod_def *sptr;
00955 char *cp;
00956 u_char *ucp;
00957 size_t i;
00958
00959 in_session->s_snmp_errno = 0;
00960 in_session->s_errno = 0;
00961
00962
00963
00964
00965 slp = (struct session_list *) calloc(1, sizeof(struct session_list));
00966 if (slp == NULL) {
00967 in_session->s_snmp_errno = SNMPERR_MALLOC;
00968 return (NULL);
00969 }
00970
00971 slp->transport = NULL;
00972
00973 isp = (struct snmp_internal_session *)calloc(1, sizeof(struct snmp_internal_session));
00974
00975 if (isp == NULL) {
00976 snmp_sess_close(slp);
00977 in_session->s_snmp_errno = SNMPERR_MALLOC;
00978 return (NULL);
00979 }
00980
00981 slp->internal = isp;
00982 slp->session = (netsnmp_session *)malloc(sizeof(netsnmp_session));
00983 if (slp->session == NULL) {
00984 snmp_sess_close(slp);
00985 in_session->s_snmp_errno = SNMPERR_MALLOC;
00986 return (NULL);
00987 }
00988 memmove(slp->session, in_session, sizeof(netsnmp_session));
00989 session = slp->session;
00990
00991
00992
00993
00994
00995 session->peername = NULL;
00996 session->community = NULL;
00997 session->contextEngineID = NULL;
00998 session->contextName = NULL;
00999 session->securityEngineID = NULL;
01000 session->securityName = NULL;
01001 session->securityAuthProto = NULL;
01002 session->securityPrivProto = NULL;
01003
01004
01005
01006
01007
01008
01009 if (in_session->peername != NULL) {
01010 session->peername = (char *)malloc(strlen(in_session->peername) + 1);
01011 if (session->peername == NULL) {
01012 snmp_sess_close(slp);
01013 in_session->s_snmp_errno = SNMPERR_MALLOC;
01014 return (NULL);
01015 }
01016 strcpy(session->peername, in_session->peername);
01017 }
01018
01019
01020
01021
01022 #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
01023 if (in_session->community_len != SNMP_DEFAULT_COMMUNITY_LEN) {
01024 ucp = (u_char *) malloc(in_session->community_len);
01025 if (ucp != NULL)
01026 memmove(ucp, in_session->community, in_session->community_len);
01027 } else {
01028 if ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01029 NETSNMP_DS_LIB_COMMUNITY)) != NULL) {
01030 session->community_len = strlen(cp);
01031 ucp = (u_char *) malloc(session->community_len);
01032 if (ucp)
01033 memmove(ucp, cp, session->community_len);
01034 } else {
01035 #ifdef NETSNMP_NO_ZEROLENGTH_COMMUNITY
01036 session->community_len = strlen(DEFAULT_COMMUNITY);
01037 ucp = (u_char *) malloc(session->community_len);
01038 if (ucp)
01039 memmove(ucp, DEFAULT_COMMUNITY, session->community_len);
01040 #else
01041 ucp = (u_char *) strdup("");
01042 #endif
01043 }
01044 }
01045
01046 if (ucp == NULL) {
01047 snmp_sess_close(slp);
01048 in_session->s_snmp_errno = SNMPERR_MALLOC;
01049 return (NULL);
01050 }
01051 session->community = ucp;
01052 #endif
01053
01054 if (session->securityLevel <= 0) {
01055 session->securityLevel =
01056 netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_SECLEVEL);
01057 }
01058
01059 if (session->securityLevel == 0)
01060 session->securityLevel = SNMP_SEC_LEVEL_NOAUTH;
01061
01062 if (in_session->securityAuthProtoLen > 0) {
01063 session->securityAuthProto =
01064 snmp_duplicate_objid(in_session->securityAuthProto,
01065 in_session->securityAuthProtoLen);
01066 if (session->securityAuthProto == NULL) {
01067 snmp_sess_close(slp);
01068 in_session->s_snmp_errno = SNMPERR_MALLOC;
01069 return (NULL);
01070 }
01071 } else if (get_default_authtype(&i) != NULL) {
01072 session->securityAuthProto =
01073 snmp_duplicate_objid(get_default_authtype(NULL), i);
01074 session->securityAuthProtoLen = i;
01075 }
01076
01077 if (in_session->securityPrivProtoLen > 0) {
01078 session->securityPrivProto =
01079 snmp_duplicate_objid(in_session->securityPrivProto,
01080 in_session->securityPrivProtoLen);
01081 if (session->securityPrivProto == NULL) {
01082 snmp_sess_close(slp);
01083 in_session->s_snmp_errno = SNMPERR_MALLOC;
01084 return (NULL);
01085 }
01086 } else if (get_default_privtype(&i) != NULL) {
01087 session->securityPrivProto =
01088 snmp_duplicate_objid(get_default_privtype(NULL), i);
01089 session->securityPrivProtoLen = i;
01090 }
01091
01092 if (in_session->securityEngineIDLen > 0) {
01093 ucp = (u_char *) malloc(in_session->securityEngineIDLen);
01094 if (ucp == NULL) {
01095 snmp_sess_close(slp);
01096 in_session->s_snmp_errno = SNMPERR_MALLOC;
01097 return (NULL);
01098 }
01099 memmove(ucp, in_session->securityEngineID,
01100 in_session->securityEngineIDLen);
01101 session->securityEngineID = ucp;
01102
01103 }
01104
01105 if (in_session->contextEngineIDLen > 0) {
01106 ucp = (u_char *) malloc(in_session->contextEngineIDLen);
01107 if (ucp == NULL) {
01108 snmp_sess_close(slp);
01109 in_session->s_snmp_errno = SNMPERR_MALLOC;
01110 return (NULL);
01111 }
01112 memmove(ucp, in_session->contextEngineID,
01113 in_session->contextEngineIDLen);
01114 session->contextEngineID = ucp;
01115 } else if (in_session->securityEngineIDLen > 0) {
01116
01117
01118
01119 ucp = (u_char *) malloc(in_session->securityEngineIDLen);
01120 if (ucp == NULL) {
01121 snmp_sess_close(slp);
01122 in_session->s_snmp_errno = SNMPERR_MALLOC;
01123 return (NULL);
01124 }
01125 memmove(ucp, in_session->securityEngineID,
01126 in_session->securityEngineIDLen);
01127 session->contextEngineID = ucp;
01128 session->contextEngineIDLen = in_session->securityEngineIDLen;
01129 }
01130
01131 if (in_session->contextName) {
01132 session->contextName = strdup(in_session->contextName);
01133 if (session->contextName == NULL) {
01134 snmp_sess_close(slp);
01135 return (NULL);
01136 }
01137 } else {
01138 if ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01139 NETSNMP_DS_LIB_CONTEXT)) != NULL)
01140 cp = strdup(cp);
01141 else
01142 cp = strdup(SNMP_DEFAULT_CONTEXT);
01143 if (cp == NULL) {
01144 snmp_sess_close(slp);
01145 return (NULL);
01146 }
01147 session->contextName = cp;
01148 session->contextNameLen = strlen(cp);
01149 }
01150
01151 if (in_session->securityName) {
01152 session->securityName = strdup(in_session->securityName);
01153 if (session->securityName == NULL) {
01154 snmp_sess_close(slp);
01155 return (NULL);
01156 }
01157 } else if ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01158 NETSNMP_DS_LIB_SECNAME)) != NULL) {
01159 cp = strdup(cp);
01160 if (cp == NULL) {
01161 snmp_sess_close(slp);
01162 return (NULL);
01163 }
01164 session->securityName = cp;
01165 session->securityNameLen = strlen(cp);
01166 }
01167
01168 if ((in_session->securityAuthKeyLen <= 0) &&
01169 ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01170 NETSNMP_DS_LIB_AUTHMASTERKEY)))) {
01171 size_t buflen = sizeof(session->securityAuthKey);
01172 u_char *tmpp = session->securityAuthKey;
01173 session->securityAuthKeyLen = 0;
01174
01175 if (!snmp_hex_to_binary(&tmpp, &buflen,
01176 &session->securityAuthKeyLen, 0, cp)) {
01177 snmp_set_detail("error parsing authentication master key");
01178 snmp_sess_close(slp);
01179 return NULL;
01180 }
01181 } else if ((in_session->securityAuthKeyLen <= 0) &&
01182 ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01183 NETSNMP_DS_LIB_AUTHPASSPHRASE)) ||
01184 (cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01185 NETSNMP_DS_LIB_PASSPHRASE)))) {
01186 session->securityAuthKeyLen = USM_AUTH_KU_LEN;
01187 if (generate_Ku(session->securityAuthProto,
01188 session->securityAuthProtoLen,
01189 (u_char *) cp, strlen(cp),
01190 session->securityAuthKey,
01191 &session->securityAuthKeyLen) != SNMPERR_SUCCESS) {
01192 snmp_set_detail
01193 ("Error generating a key (Ku) from the supplied authentication pass phrase.");
01194 snmp_sess_close(slp);
01195 return NULL;
01196 }
01197 }
01198
01199
01200 if ((in_session->securityPrivKeyLen <= 0) &&
01201 ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01202 NETSNMP_DS_LIB_PRIVMASTERKEY)))) {
01203 size_t buflen = sizeof(session->securityPrivKey);
01204 u_char *tmpp = session->securityPrivKey;
01205 session->securityPrivKeyLen = 0;
01206
01207 if (!snmp_hex_to_binary(&tmpp, &buflen,
01208 &session->securityPrivKeyLen, 0, cp)) {
01209 snmp_set_detail("error parsing encryption master key");
01210 snmp_sess_close(slp);
01211 return NULL;
01212 }
01213 } else if ((in_session->securityPrivKeyLen <= 0) &&
01214 ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01215 NETSNMP_DS_LIB_PRIVPASSPHRASE)) ||
01216 (cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01217 NETSNMP_DS_LIB_PASSPHRASE)))) {
01218 session->securityPrivKeyLen = USM_PRIV_KU_LEN;
01219 if (generate_Ku(session->securityAuthProto,
01220 session->securityAuthProtoLen,
01221 (u_char *) cp, strlen(cp),
01222 session->securityPrivKey,
01223 &session->securityPrivKeyLen) != SNMPERR_SUCCESS) {
01224 snmp_set_detail
01225 ("Error generating a key (Ku) from the supplied privacy pass phrase.");
01226 snmp_sess_close(slp);
01227 return NULL;
01228 }
01229 }
01230
01231 if (session->retries == SNMP_DEFAULT_RETRIES)
01232 session->retries = DEFAULT_RETRIES;
01233 if (session->timeout == SNMP_DEFAULT_TIMEOUT)
01234 session->timeout = DEFAULT_TIMEOUT;
01235 session->sessid = snmp_get_next_sessid();
01236
01237 snmp_call_callbacks(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_SESSION_INIT,
01238 session);
01239
01240 if ((sptr = find_sec_mod(session->securityModel)) != NULL &&
01241 sptr->session_open != NULL) {
01242
01243
01244
01245 (*sptr->session_open) (session);
01246 }
01247
01248 return (slp);
01249 }
01250
01251 static struct session_list *
01252 snmp_sess_copy(netsnmp_session * pss)
01253 {
01254 struct session_list *psl;
01255 psl = _sess_copy(pss);
01256 if (!psl) {
01257 if (!pss->s_snmp_errno) {
01258 pss->s_snmp_errno = SNMPERR_GENERR;
01259 }
01260 SET_SNMP_ERROR(pss->s_snmp_errno);
01261 }
01262 return psl;
01263 }
01264
01273 int
01274 snmpv3_probe_contextEngineID_rfc5343(void *slp, netsnmp_session *session) {
01275 netsnmp_pdu *pdu = NULL, *response = NULL;
01276 static oid snmpEngineIDoid[] = { 1,3,6,1,6,3,10,2,1,1,0};
01277 static size_t snmpEngineIDoid_len = 11;
01278
01279 static char probeEngineID[] = { (char)0x80, 0, 0, 0, 6 };
01280 static size_t probeEngineID_len = sizeof(probeEngineID);
01281
01282 int status;
01283
01284 pdu = snmp_pdu_create(SNMP_MSG_GET);
01285 if (!pdu)
01286 return SNMP_ERR_GENERR;
01287 pdu->version = SNMP_VERSION_3;
01288
01289 if (session->securityName) {
01290 pdu->securityName = strdup(session->securityName);
01291 pdu->securityNameLen = strlen(pdu->securityName);
01292 }
01293 pdu->securityLevel = SNMP_SEC_LEVEL_NOAUTH;
01294 pdu->securityModel = session->securityModel;
01295 if (memdup(&pdu->contextEngineID, probeEngineID, probeEngineID_len) !=
01296 SNMPERR_SUCCESS) {
01297 snmp_log(LOG_ERR, "failed to clone memory for rfc5343 probe\n");
01298 return SNMP_ERR_GENERR;
01299 }
01300 pdu->contextEngineIDLen = probeEngineID_len;
01301
01302 snmp_add_null_var(pdu, snmpEngineIDoid, snmpEngineIDoid_len);
01303
01304 DEBUGMSGTL(("snmp_api", "probing for engineID using rfc5343 methods...\n"));
01305 session->flags |= SNMP_FLAGS_DONT_PROBE;
01306 status = snmp_sess_synch_response(slp, pdu, &response);
01307
01308 if ((response == NULL) || (status != STAT_SUCCESS)) {
01309 snmp_log(LOG_ERR, "failed rfc5343 contextEngineID probing\n");
01310 return SNMP_ERR_GENERR;
01311 }
01312
01313
01314 if (NULL != response->variables &&
01315 NULL != response->variables->name &&
01316 snmp_oid_compare(response->variables->name,
01317 response->variables->name_length,
01318 snmpEngineIDoid, snmpEngineIDoid_len) == 0 &&
01319 ASN_OCTET_STR == response->variables->type &&
01320 NULL != response->variables->val.string &&
01321 response->variables->val_len > 0) {
01322 if (memdup(&session->contextEngineID,
01323 response->variables->val.string,
01324 response->variables->val_len) != SNMPERR_SUCCESS) {
01325 snmp_log(LOG_ERR, "failed rfc5343 contextEngineID probing: memory allocation failed\n");
01326 return SNMP_ERR_GENERR;
01327 }
01328
01329
01330
01331 if (memdup(&session->securityEngineID,
01332 response->variables->val.string,
01333 response->variables->val_len) != SNMPERR_SUCCESS) {
01334 snmp_log(LOG_ERR, "failed rfc5343 securityEngineID probing: memory allocation failed\n");
01335 return SNMP_ERR_GENERR;
01336 }
01337
01338 session->securityEngineIDLen = session->contextEngineIDLen =
01339 response->variables->val_len;
01340
01341 if (snmp_get_do_debugging()) {
01342 int i;
01343 DEBUGMSGTL(("snmp_sess_open",
01344 " probe found engineID: "));
01345 for (i = 0; i < session->securityEngineIDLen; i++)
01346 DEBUGMSG(("snmp_sess_open", "%02x",
01347 session->securityEngineID[i]));
01348 DEBUGMSG(("snmp_sess_open", "\n"));
01349 }
01350 }
01351 return SNMPERR_SUCCESS;
01352 }
01353
01354
01370 int
01371 snmpv3_engineID_probe(struct session_list *slp,
01372 netsnmp_session * in_session)
01373 {
01374 netsnmp_pdu *pdu = NULL, *response = NULL;
01375 netsnmp_session *session;
01376 unsigned int i;
01377 int status;
01378
01379 if (slp == NULL || slp->session == NULL) {
01380 return 0;
01381 }
01382
01383 session = slp->session;
01384
01385
01386
01387
01388
01389
01390
01391 if ((session->flags & SNMP_FLAGS_DONT_PROBE) == SNMP_FLAGS_DONT_PROBE)
01392 return 1;
01393
01394 if (session->version == SNMP_VERSION_3) {
01395 struct snmp_secmod_def *sptr = find_sec_mod(session->securityModel);
01396
01397 if (NULL != sptr && NULL != sptr->probe_engineid) {
01398 DEBUGMSGTL(("snmp_api", "probing for engineID using security model callback...\n"));
01399
01400 status = (*sptr->probe_engineid) (slp, session);
01401 if (status)
01402 return 0;
01403 return 1;
01404 } else if (session->securityEngineIDLen == 0) {
01405 if (snmpv3_build_probe_pdu(&pdu) != 0) {
01406 DEBUGMSGTL(("snmp_api", "unable to create probe PDU\n"));
01407 return 0;
01408 }
01409 DEBUGMSGTL(("snmp_api", "probing for engineID...\n"));
01410 session->flags |= SNMP_FLAGS_DONT_PROBE;
01411 status = snmp_sess_synch_response(slp, pdu, &response);
01412
01413 if ((response == NULL) && (status == STAT_SUCCESS)) {
01414 status = STAT_ERROR;
01415 }
01416
01417 switch (status) {
01418 case STAT_SUCCESS:
01419 in_session->s_snmp_errno = SNMPERR_INVALID_MSG;
01420 DEBUGMSGTL(("snmp_sess_open",
01421 "error: expected Report as response to probe: %s (%ld)\n",
01422 snmp_errstring(response->errstat),
01423 response->errstat));
01424 break;
01425 case STAT_ERROR:
01426 in_session->s_snmp_errno = SNMPERR_UNKNOWN_ENG_ID;
01427 break;
01428 case STAT_TIMEOUT:
01429 in_session->s_snmp_errno = SNMPERR_TIMEOUT;
01430 default:
01431 DEBUGMSGTL(("snmp_sess_open",
01432 "unable to connect with remote engine: %s (%d)\n",
01433 snmp_api_errstring(session->s_snmp_errno),
01434 session->s_snmp_errno));
01435 break;
01436 }
01437
01438 if (slp->session->securityEngineIDLen == 0) {
01439 DEBUGMSGTL(("snmp_api",
01440 "unable to determine remote engine ID\n"));
01441 return 0;
01442 }
01443
01444 in_session->s_snmp_errno = SNMPERR_SUCCESS;
01445 if (snmp_get_do_debugging()) {
01446 DEBUGMSGTL(("snmp_sess_open",
01447 " probe found engineID: "));
01448 for (i = 0; i < slp->session->securityEngineIDLen; i++)
01449 DEBUGMSG(("snmp_sess_open", "%02x",
01450 slp->session->securityEngineID[i]));
01451 DEBUGMSG(("snmp_sess_open", "\n"));
01452 }
01453 }
01454
01455
01456
01457
01458 if (session->engineBoots || session->engineTime) {
01459 set_enginetime(session->securityEngineID,
01460 session->securityEngineIDLen,
01461 session->engineBoots, session->engineTime,
01462 TRUE);
01463 }
01464
01465 if (create_user_from_session(slp->session) != SNMPERR_SUCCESS) {
01466 in_session->s_snmp_errno = SNMPERR_UNKNOWN_USER_NAME;
01467 DEBUGMSGTL(("snmp_api",
01468 "snmpv3_engine_probe(): failed(2) to create a new user from session\n"));
01469 return 0;
01470 }
01471 }
01472
01473 return 1;
01474 }
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490 static void *
01491 _sess_open(netsnmp_session * in_session)
01492 {
01493 netsnmp_transport *transport = NULL;
01494
01495 in_session->s_snmp_errno = 0;
01496 in_session->s_errno = 0;
01497
01498 _init_snmp();
01499
01500 {
01501 char *clientaddr_save = NULL;
01502
01503 if (NULL != in_session->localname) {
01504 clientaddr_save =
01505 netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01506 NETSNMP_DS_LIB_CLIENT_ADDR);
01507 netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID,
01508 NETSNMP_DS_LIB_CLIENT_ADDR,
01509 in_session->localname);
01510 }
01511
01512 if (in_session->flags & SNMP_FLAGS_STREAM_SOCKET) {
01513 transport =
01514 netsnmp_tdomain_transport_full("snmp", in_session->peername,
01515 in_session->local_port, "tcp",
01516 NULL);
01517 } else {
01518 transport =
01519 netsnmp_tdomain_transport_full("snmp", in_session->peername,
01520 in_session->local_port, "udp",
01521 NULL);
01522 }
01523
01524 if (NULL != clientaddr_save)
01525 netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID,
01526 NETSNMP_DS_LIB_CLIENT_ADDR, clientaddr_save);
01527 }
01528
01529 #if defined(SO_BROADCAST) && defined(SOL_SOCKET)
01530 if ( transport != 0 && (in_session->flags & SNMP_FLAGS_UDP_BROADCAST) ) {
01531 int b = 1;
01532 int rc;
01533
01534 rc = setsockopt(transport->sock, SOL_SOCKET, SO_BROADCAST,
01535 (char *)&b, sizeof(b));
01536
01537 if ( rc != 0 ) {
01538 in_session->s_snmp_errno = SNMPERR_BAD_ADDRESS;
01539 in_session->s_errno = errno;
01540
01541 DEBUGMSGTL(("_sess_open", "couldn't enable UDP_BROADCAST\n"));
01542 return NULL;
01543 }
01544 }
01545 #endif
01546
01547 if (transport == NULL) {
01548 DEBUGMSGTL(("_sess_open", "couldn't interpret peername\n"));
01549 in_session->s_snmp_errno = SNMPERR_BAD_ADDRESS;
01550 in_session->s_errno = errno;
01551 snmp_set_detail(in_session->peername);
01552 return NULL;
01553 }
01554
01555 return snmp_sess_add(in_session, transport, NULL, NULL);
01556 }
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570 netsnmp_session *
01571 snmp_add(netsnmp_session * in_session,
01572 netsnmp_transport *transport,
01573 int (*fpre_parse) (netsnmp_session *, netsnmp_transport *, void *,
01574 int), int (*fpost_parse) (netsnmp_session *,
01575 netsnmp_pdu *, int))
01576 {
01577 struct session_list *slp;
01578 slp = (struct session_list *) snmp_sess_add_ex(in_session, transport,
01579 fpre_parse, NULL,
01580 fpost_parse, NULL, NULL,
01581 NULL, NULL);
01582 if (slp == NULL) {
01583 return NULL;
01584 }
01585
01586 snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION);
01587 slp->next = Sessions;
01588 Sessions = slp;
01589 snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION);
01590
01591 return (slp->session);
01592 }
01593
01594 netsnmp_session *
01595 snmp_add_full(netsnmp_session * in_session,
01596 netsnmp_transport *transport,
01597 int (*fpre_parse) (netsnmp_session *, netsnmp_transport *,
01598 void *, int),
01599 int (*fparse) (netsnmp_session *, netsnmp_pdu *, u_char *,
01600 size_t),
01601 int (*fpost_parse) (netsnmp_session *, netsnmp_pdu *, int),
01602 int (*fbuild) (netsnmp_session *, netsnmp_pdu *, u_char *,
01603 size_t *), int (*frbuild) (netsnmp_session *,
01604 netsnmp_pdu *,
01605 u_char **,
01606 size_t *,
01607 size_t *),
01608 int (*fcheck) (u_char *, size_t),
01609 netsnmp_pdu *(*fcreate_pdu) (netsnmp_transport *, void *,
01610 size_t))
01611 {
01612 struct session_list *slp;
01613 slp = (struct session_list *) snmp_sess_add_ex(in_session, transport,
01614 fpre_parse, fparse,
01615 fpost_parse, fbuild,
01616 frbuild, fcheck,
01617 fcreate_pdu);
01618 if (slp == NULL) {
01619 return NULL;
01620 }
01621
01622 snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION);
01623 slp->next = Sessions;
01624 Sessions = slp;
01625 snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION);
01626
01627 return (slp->session);
01628 }
01629
01630
01631
01632 void *
01633 snmp_sess_add_ex(netsnmp_session * in_session,
01634 netsnmp_transport *transport,
01635 int (*fpre_parse) (netsnmp_session *, netsnmp_transport *,
01636 void *, int),
01637 int (*fparse) (netsnmp_session *, netsnmp_pdu *, u_char *,
01638 size_t),
01639 int (*fpost_parse) (netsnmp_session *, netsnmp_pdu *,
01640 int),
01641 int (*fbuild) (netsnmp_session *, netsnmp_pdu *, u_char *,
01642 size_t *),
01643 int (*frbuild) (netsnmp_session *, netsnmp_pdu *,
01644 u_char **, size_t *, size_t *),
01645 int (*fcheck) (u_char *, size_t),
01646 netsnmp_pdu *(*fcreate_pdu) (netsnmp_transport *, void *,
01647 size_t))
01648 {
01649 struct session_list *slp;
01650
01651 _init_snmp();
01652
01653 if (transport == NULL)
01654 return NULL;
01655
01656 if (in_session == NULL) {
01657 transport->f_close(transport);
01658 netsnmp_transport_free(transport);
01659 return NULL;
01660 }
01661
01662 DEBUGMSGTL(("snmp_sess_add", "fd %d\n", transport->sock));
01663
01664 if ((slp = snmp_sess_copy(in_session)) == NULL) {
01665 transport->f_close(transport);
01666 netsnmp_transport_free(transport);
01667 return (NULL);
01668 }
01669
01670 slp->transport = transport;
01671 slp->internal->hook_pre = fpre_parse;
01672 slp->internal->hook_parse = fparse;
01673 slp->internal->hook_post = fpost_parse;
01674 slp->internal->hook_build = fbuild;
01675 slp->internal->hook_realloc_build = frbuild;
01676 slp->internal->check_packet = fcheck;
01677 slp->internal->hook_create_pdu = fcreate_pdu;
01678
01679 slp->session->rcvMsgMaxSize = transport->msgMaxSize;
01680
01681 if (slp->session->version == SNMP_VERSION_3) {
01682 DEBUGMSGTL(("snmp_sess_add",
01683 "adding v3 session -- maybe engineID probe now\n"));
01684 if (!snmpv3_engineID_probe(slp, in_session)) {
01685 DEBUGMSGTL(("snmp_sess_add", "engine ID probe failed\n"));
01686 snmp_sess_close(slp);
01687 return NULL;
01688 }
01689 if (create_user_from_session(slp->session) != SNMPERR_SUCCESS) {
01690 in_session->s_snmp_errno = SNMPERR_UNKNOWN_USER_NAME;
01691 DEBUGMSGTL(("snmp_api",
01692 "snmp_sess_add(): failed(2) to create a new user from session\n"));
01693 snmp_sess_close(slp);
01694 return NULL;
01695 }
01696 }
01697
01698 slp->session->flags &= ~SNMP_FLAGS_DONT_PROBE;
01699
01700 return (void *) slp;
01701 }
01702
01703
01704
01705 void *
01706 snmp_sess_add(netsnmp_session * in_session,
01707 netsnmp_transport *transport,
01708 int (*fpre_parse) (netsnmp_session *, netsnmp_transport *,
01709 void *, int),
01710 int (*fpost_parse) (netsnmp_session *, netsnmp_pdu *, int))
01711 {
01712 return snmp_sess_add_ex(in_session, transport, fpre_parse, NULL,
01713 fpost_parse, NULL, NULL, NULL, NULL);
01714 }
01715
01716
01717
01718 void *
01719 snmp_sess_open(netsnmp_session * pss)
01720 {
01721 void *pvoid;
01722 pvoid = _sess_open(pss);
01723 if (!pvoid) {
01724 SET_SNMP_ERROR(pss->s_snmp_errno);
01725 }
01726 return pvoid;
01727 }
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745 int
01746 create_user_from_session(netsnmp_session * session)
01747 {
01748 struct usmUser *user;
01749 int user_just_created = 0;
01750 char *cp;
01751
01752
01753
01754
01755
01756 if (SNMP_FLAGS_USER_CREATED == (session->flags & SNMP_FLAGS_USER_CREATED) ||
01757 session->securityModel != SNMP_SEC_MODEL_USM ||
01758 session->version != SNMP_VERSION_3 ||
01759 session->securityNameLen == 0 ||
01760 session->securityEngineIDLen == 0)
01761 return SNMPERR_SUCCESS;
01762
01763 session->flags |= SNMP_FLAGS_USER_CREATED;
01764
01765
01766
01767
01768
01769 user = usm_get_user_from_list(session->securityEngineID,
01770 session->securityEngineIDLen,
01771 session->securityName,
01772 usm_get_userList(), 0);
01773 if (user == NULL) {
01774 DEBUGMSGTL(("snmp_api", "Building user %s...\n",
01775 session->securityName));
01776
01777
01778
01779 user = (struct usmUser *) calloc(1, sizeof(struct usmUser));
01780 if (user == NULL)
01781 return SNMPERR_GENERR;
01782
01783
01784
01785
01786 if (session->securityName) {
01787 user->name = strdup(session->securityName);
01788 user->secName = strdup(session->securityName);
01789 if (user->name == NULL || user->secName == NULL) {
01790 usm_free_user(user);
01791 return SNMPERR_GENERR;
01792 }
01793 }
01794
01795
01796
01797
01798 if (memdup(&user->engineID, session->securityEngineID,
01799 session->securityEngineIDLen) != SNMPERR_SUCCESS) {
01800 usm_free_user(user);
01801 return SNMPERR_GENERR;
01802 }
01803 user->engineIDLen = session->securityEngineIDLen;
01804
01805 user_just_created = 1;
01806 }
01807
01808
01809
01810 if (session->securityAuthProto != NULL) {
01811 SNMP_FREE(user->authProtocol);
01812 user->authProtocol =
01813 snmp_duplicate_objid(session->securityAuthProto,
01814 session->securityAuthProtoLen);
01815 if (user->authProtocol == NULL) {
01816 usm_free_user(user);
01817 return SNMPERR_GENERR;
01818 }
01819 user->authProtocolLen = session->securityAuthProtoLen;
01820 }
01821
01822
01823
01824
01825 if (session->securityPrivProto != NULL) {
01826 SNMP_FREE(user->privProtocol);
01827 user->privProtocol =
01828 snmp_duplicate_objid(session->securityPrivProto,
01829 session->securityPrivProtoLen);
01830 if (user->privProtocol == NULL) {
01831 usm_free_user(user);
01832 return SNMPERR_GENERR;
01833 }
01834 user->privProtocolLen = session->securityPrivProtoLen;
01835 }
01836
01837
01838
01839
01840 if (session->securityAuthLocalKey != NULL
01841 && session->securityAuthLocalKeyLen != 0) {
01842
01843 SNMP_FREE(user->authKey);
01844 if (memdup(&user->authKey, session->securityAuthLocalKey,
01845 session->securityAuthLocalKeyLen) != SNMPERR_SUCCESS) {
01846 usm_free_user(user);
01847 return SNMPERR_GENERR;
01848 }
01849 user->authKeyLen = session->securityAuthLocalKeyLen;
01850 } else if (session->securityAuthKey != NULL
01851 && session->securityAuthKeyLen != 0) {
01852 SNMP_FREE(user->authKey);
01853 user->authKey = (u_char *) calloc(1, USM_LENGTH_KU_HASHBLOCK);
01854 if (user->authKey == NULL) {
01855 usm_free_user(user);
01856 return SNMPERR_GENERR;
01857 }
01858 user->authKeyLen = USM_LENGTH_KU_HASHBLOCK;
01859 if (generate_kul(user->authProtocol, user->authProtocolLen,
01860 session->securityEngineID,
01861 session->securityEngineIDLen,
01862 session->securityAuthKey,
01863 session->securityAuthKeyLen, user->authKey,
01864 &user->authKeyLen) != SNMPERR_SUCCESS) {
01865 usm_free_user(user);
01866 return SNMPERR_GENERR;
01867 }
01868 } else if ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01869 NETSNMP_DS_LIB_AUTHLOCALIZEDKEY))) {
01870 size_t buflen = USM_AUTH_KU_LEN;
01871 SNMP_FREE(user->authKey);
01872 user->authKey = (u_char *)malloc(buflen);
01873 user->authKeyLen = 0;
01874
01875 if (!snmp_hex_to_binary(&user->authKey, &buflen, &user->authKeyLen,
01876 0, cp)) {
01877 usm_free_user(user);
01878 return SNMPERR_GENERR;
01879 }
01880 }
01881
01882
01883
01884
01885 if (session->securityPrivLocalKey != NULL
01886 && session->securityPrivLocalKeyLen != 0) {
01887
01888 SNMP_FREE(user->privKey);
01889 if (memdup(&user->privKey, session->securityPrivLocalKey,
01890 session->securityPrivLocalKeyLen) != SNMPERR_SUCCESS) {
01891 usm_free_user(user);
01892 return SNMPERR_GENERR;
01893 }
01894 user->privKeyLen = session->securityPrivLocalKeyLen;
01895 } else if (session->securityPrivKey != NULL
01896 && session->securityPrivKeyLen != 0) {
01897 SNMP_FREE(user->privKey);
01898 user->privKey = (u_char *) calloc(1, USM_LENGTH_KU_HASHBLOCK);
01899 if (user->privKey == NULL) {
01900 usm_free_user(user);
01901 return SNMPERR_GENERR;
01902 }
01903 user->privKeyLen = USM_LENGTH_KU_HASHBLOCK;
01904 if (generate_kul(user->authProtocol, user->authProtocolLen,
01905 session->securityEngineID,
01906 session->securityEngineIDLen,
01907 session->securityPrivKey,
01908 session->securityPrivKeyLen, user->privKey,
01909 &user->privKeyLen) != SNMPERR_SUCCESS) {
01910 usm_free_user(user);
01911 return SNMPERR_GENERR;
01912 }
01913 } else if ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01914 NETSNMP_DS_LIB_PRIVLOCALIZEDKEY))) {
01915 size_t buflen = USM_PRIV_KU_LEN;
01916 SNMP_FREE(user->privKey);
01917 user->privKey = (u_char *)malloc(buflen);
01918 user->privKeyLen = 0;
01919
01920 if (!snmp_hex_to_binary(&user->privKey, &buflen, &user->privKeyLen,
01921 0, cp)) {
01922 usm_free_user(user);
01923 return SNMPERR_GENERR;
01924 }
01925 }
01926
01927 if (user_just_created) {
01928
01929
01930
01931 user->userStatus = RS_ACTIVE;
01932 user->userStorageType = ST_READONLY;
01933 usm_add_user(user);
01934 }
01935
01936 return SNMPERR_SUCCESS;
01937
01938
01939 }
01940
01941
01942
01943
01944
01945
01946
01947
01948 static void
01949 snmp_free_session(netsnmp_session * s)
01950 {
01951 if (s) {
01952 SNMP_FREE(s->peername);
01953 SNMP_FREE(s->community);
01954 SNMP_FREE(s->contextEngineID);
01955 SNMP_FREE(s->contextName);
01956 SNMP_FREE(s->securityEngineID);
01957 SNMP_FREE(s->securityName);
01958 SNMP_FREE(s->securityAuthProto);
01959 SNMP_FREE(s->securityPrivProto);
01960 SNMP_FREE(s->paramName);
01961
01962
01963
01964
01965 netsnmp_callback_clear_client_arg(s, 0, 0);
01966
01967 free((char *) s);
01968 }
01969 }
01970
01971
01972
01973
01974
01975
01976 int
01977 snmp_sess_close(void *sessp)
01978 {
01979 struct session_list *slp = (struct session_list *) sessp;
01980 netsnmp_transport *transport;
01981 struct snmp_internal_session *isp;
01982 netsnmp_session *sesp = NULL;
01983 struct snmp_secmod_def *sptr;
01984
01985 if (slp == NULL) {
01986 return 0;
01987 }
01988
01989 if (slp->session != NULL &&
01990 (sptr = find_sec_mod(slp->session->securityModel)) != NULL &&
01991 sptr->session_close != NULL) {
01992 (*sptr->session_close) (slp->session);
01993 }
01994
01995 isp = slp->internal;
01996 slp->internal = NULL;
01997
01998 if (isp) {
01999 netsnmp_request_list *rp, *orp;
02000
02001 SNMP_FREE(isp->packet);
02002
02003
02004
02005
02006 rp = isp->requests;
02007 while (rp) {
02008 orp = rp;
02009 rp = rp->next_request;
02010 snmp_free_pdu(orp->pdu);
02011 free((char *) orp);
02012 }
02013
02014 free((char *) isp);
02015 }
02016
02017 transport = slp->transport;
02018 slp->transport = NULL;
02019
02020 if (transport) {
02021 transport->f_close(transport);
02022 netsnmp_transport_free(transport);
02023 }
02024
02025 sesp = slp->session;
02026 slp->session = NULL;
02027
02028
02029
02030
02031
02032
02033
02034 if (sesp != NULL && sesp->subsession != NULL) {
02035 netsnmp_session *subsession = sesp->subsession, *tmpsub;
02036
02037 while (subsession != NULL) {
02038 DEBUGMSGTL(("snmp_sess_close",
02039 "closing session %p, subsession %p\n", sesp,
02040 subsession));
02041 tmpsub = subsession->next;
02042 snmp_free_session(subsession);
02043 subsession = tmpsub;
02044 }
02045 }
02046
02047 snmp_free_session(sesp);
02048 free((char *) slp);
02049 return 1;
02050 }
02051
02052 int
02053 snmp_close(netsnmp_session * session)
02054 {
02055 struct session_list *slp = NULL, *oslp = NULL;
02056
02057 {
02058 snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION);
02059 if (Sessions && Sessions->session == session) {
02060 slp = Sessions;
02061 Sessions = slp->next;
02062 } else {
02063 for (slp = Sessions; slp; slp = slp->next) {
02064 if (slp->session == session) {
02065 if (oslp)
02066 oslp->next = slp->next;
02067 break;
02068 }
02069 oslp = slp;
02070 }
02071 }
02072 snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION);
02073 }
02074 if (slp == NULL) {
02075 return 0;
02076 }
02077 return snmp_sess_close((void *) slp);
02078 }
02079
02080 int
02081 snmp_close_sessions(void)
02082 {
02083 struct session_list *slp;
02084
02085 snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION);
02086 while (Sessions) {
02087 slp = Sessions;
02088 Sessions = Sessions->next;
02089 snmp_sess_close((void *) slp);
02090 }
02091 snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION);
02092 return 1;
02093 }
02094
02095 static int
02096 snmpv3_build_probe_pdu(netsnmp_pdu **pdu)
02097 {
02098 struct usmUser *user;
02099
02100
02101
02102
02103 if (!pdu)
02104 return -1;
02105 *pdu = snmp_pdu_create(SNMP_MSG_GET);
02106 if (!(*pdu))
02107 return -1;
02108 (*pdu)->version = SNMP_VERSION_3;
02109 (*pdu)->securityName = strdup("");
02110 (*pdu)->securityNameLen = strlen((*pdu)->securityName);
02111 (*pdu)->securityLevel = SNMP_SEC_LEVEL_NOAUTH;
02112 (*pdu)->securityModel = SNMP_SEC_MODEL_USM;
02113
02114
02115
02116
02117 user = usm_get_user(NULL, 0, (*pdu)->securityName);
02118 if (user == NULL) {
02119 user = (struct usmUser *) calloc(1, sizeof(struct usmUser));
02120 if (user == NULL) {
02121 snmp_free_pdu(*pdu);
02122 *pdu = (netsnmp_pdu *) NULL;
02123 return -1;
02124 }
02125 user->name = strdup((*pdu)->securityName);
02126 user->secName = strdup((*pdu)->securityName);
02127 user->authProtocolLen = sizeof(usmNoAuthProtocol) / sizeof(oid);
02128 user->authProtocol =
02129 snmp_duplicate_objid(usmNoAuthProtocol, user->authProtocolLen);
02130 user->privProtocolLen = sizeof(usmNoPrivProtocol) / sizeof(oid);
02131 user->privProtocol =
02132 snmp_duplicate_objid(usmNoPrivProtocol, user->privProtocolLen);
02133 usm_add_user(user);
02134 }
02135 return 0;
02136 }
02137
02138 static void
02139 snmpv3_calc_msg_flags(int sec_level, int msg_command, u_char * flags)
02140 {
02141 *flags = 0;
02142 if (sec_level == SNMP_SEC_LEVEL_AUTHNOPRIV)
02143 *flags = SNMP_MSG_FLAG_AUTH_BIT;
02144 else if (sec_level == SNMP_SEC_LEVEL_AUTHPRIV)
02145 *flags = SNMP_MSG_FLAG_AUTH_BIT | SNMP_MSG_FLAG_PRIV_BIT;
02146
02147 if (SNMP_CMD_CONFIRMED(msg_command))
02148 *flags |= SNMP_MSG_FLAG_RPRT_BIT;
02149
02150 return;
02151 }
02152
02153 static int
02154 snmpv3_verify_msg(netsnmp_request_list *rp, netsnmp_pdu *pdu)
02155 {
02156 netsnmp_pdu *rpdu;
02157
02158 if (!rp || !rp->pdu || !pdu)
02159 return 0;
02160
02161
02162
02163 if (pdu->command == SNMP_MSG_REPORT)
02164 return 1;
02165 rpdu = rp->pdu;
02166 if (rp->request_id != pdu->reqid || rpdu->reqid != pdu->reqid)
02167 return 0;
02168 if (rpdu->version != pdu->version)
02169 return 0;
02170 if (rpdu->securityModel != pdu->securityModel)
02171 return 0;
02172 if (rpdu->securityLevel != pdu->securityLevel)
02173 return 0;
02174
02175 if (rpdu->contextEngineIDLen != pdu->contextEngineIDLen ||
02176 memcmp(rpdu->contextEngineID, pdu->contextEngineID,
02177 pdu->contextEngineIDLen))
02178 return 0;
02179 if (rpdu->contextNameLen != pdu->contextNameLen ||
02180 memcmp(rpdu->contextName, pdu->contextName, pdu->contextNameLen))
02181 return 0;
02182
02183
02184
02185 if (pdu->securityModel == SNMP_SEC_MODEL_USM &&
02186 (rpdu->securityEngineIDLen != pdu->securityEngineIDLen ||
02187 memcmp(rpdu->securityEngineID, pdu->securityEngineID,
02188 pdu->securityEngineIDLen)))
02189 return 0;
02190
02191
02192 if (rpdu->securityNameLen != pdu->securityNameLen ||
02193 memcmp(rpdu->securityName, pdu->securityName,
02194 pdu->securityNameLen))
02195 return 0;
02196 return 1;
02197 }
02198
02199
02200
02201
02202
02203
02204
02205
02206
02207 static int
02208 snmpv3_build(u_char ** pkt, size_t * pkt_len, size_t * offset,
02209 netsnmp_session * session, netsnmp_pdu *pdu)
02210 {
02211 int ret;
02212
02213 session->s_snmp_errno = 0;
02214 session->s_errno = 0;
02215
02216
02217
02218
02219 switch (pdu->command) {
02220 case SNMP_MSG_RESPONSE:
02221 case SNMP_MSG_TRAP2:
02222 case SNMP_MSG_REPORT:
02223 netsnmp_assert(0 == (pdu->flags & UCD_MSG_FLAG_EXPECT_RESPONSE));
02224
02225
02226
02227 case SNMP_MSG_GET:
02228 case SNMP_MSG_GETNEXT:
02229 case SNMP_MSG_SET:
02230 case SNMP_MSG_INFORM:
02231 if (pdu->errstat == SNMP_DEFAULT_ERRSTAT)
02232 pdu->errstat = 0;
02233 if (pdu->errindex == SNMP_DEFAULT_ERRINDEX)
02234 pdu->errindex = 0;
02235 break;
02236
02237 case SNMP_MSG_GETBULK:
02238 if (pdu->max_repetitions < 0) {
02239 session->s_snmp_errno = SNMPERR_BAD_REPETITIONS;
02240 return -1;
02241 }
02242 if (pdu->non_repeaters < 0) {
02243 session->s_snmp_errno = SNMPERR_BAD_REPEATERS;
02244 return -1;
02245 }
02246 break;
02247
02248 case SNMP_MSG_TRAP:
02249 session->s_snmp_errno = SNMPERR_V1_IN_V2;
02250 return -1;
02251
02252 default:
02253 session->s_snmp_errno = SNMPERR_UNKNOWN_PDU;
02254 return -1;
02255 }
02256
02257
02258 if (pdu->securityEngineIDLen == 0) {
02259 if (session->securityEngineIDLen) {
02260 snmpv3_clone_engineID(&pdu->securityEngineID,
02261 &pdu->securityEngineIDLen,
02262 session->securityEngineID,
02263 session->securityEngineIDLen);
02264 }
02265 }
02266
02267
02268 if (pdu->contextEngineIDLen == 0) {
02269 if (session->contextEngineIDLen) {
02270 snmpv3_clone_engineID(&pdu->contextEngineID,
02271 &pdu->contextEngineIDLen,
02272 session->contextEngineID,
02273 session->contextEngineIDLen);
02274 } else if (pdu->securityEngineIDLen) {
02275 snmpv3_clone_engineID(&pdu->contextEngineID,
02276 &pdu->contextEngineIDLen,
02277 pdu->securityEngineID,
02278 pdu->securityEngineIDLen);
02279 }
02280 }
02281
02282 if (pdu->contextName == NULL) {
02283 if (!session->contextName) {
02284 session->s_snmp_errno = SNMPERR_BAD_CONTEXT;
02285 return -1;
02286 }
02287 pdu->contextName = strdup(session->contextName);
02288 if (pdu->contextName == NULL) {
02289 session->s_snmp_errno = SNMPERR_GENERR;
02290 return -1;
02291 }
02292 pdu->contextNameLen = session->contextNameLen;
02293 }
02294 if (pdu->securityModel == SNMP_DEFAULT_SECMODEL) {
02295 pdu->securityModel = session->securityModel;
02296 if (pdu->securityModel == SNMP_DEFAULT_SECMODEL) {
02297 pdu->securityModel = se_find_value_in_slist("snmp_secmods", netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_SECMODEL));
02298
02299 if (pdu->securityModel <= 0) {
02300 pdu->securityModel = SNMP_SEC_MODEL_USM;
02301 }
02302 }
02303 }
02304 if (pdu->securityNameLen == 0 && pdu->securityName == NULL) {
02305 if (session->securityModel != NETSNMP_TSM_SECURITY_MODEL &&
02306 session->securityNameLen == 0) {
02307 session->s_snmp_errno = SNMPERR_BAD_SEC_NAME;
02308 return -1;
02309 }
02310 if (session->securityName) {
02311 pdu->securityName = strdup(session->securityName);
02312 if (pdu->securityName == NULL) {
02313 session->s_snmp_errno = SNMPERR_GENERR;
02314 return -1;
02315 }
02316 pdu->securityNameLen = session->securityNameLen;
02317 }
02318 }
02319 if (pdu->securityLevel == 0) {
02320 if (session->securityLevel == 0) {
02321 session->s_snmp_errno = SNMPERR_BAD_SEC_LEVEL;
02322 return -1;
02323 }
02324 pdu->securityLevel = session->securityLevel;
02325 }
02326 DEBUGMSGTL(("snmp_build",
02327 "Building SNMPv3 message (secName:\"%s\", secLevel:%s)...\n",
02328 ((session->securityName) ? (char *) session->securityName :
02329 ((pdu->securityName) ? (char *) pdu->securityName :
02330 "ERROR: undefined")), secLevelName[pdu->securityLevel]));
02331
02332 DEBUGDUMPSECTION("send", "SNMPv3 Message");
02333 #ifdef NETSNMP_USE_REVERSE_ASNENCODING
02334 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_REVERSE_ENCODE)) {
02335 ret = snmpv3_packet_realloc_rbuild(pkt, pkt_len, offset,
02336 session, pdu, NULL, 0);
02337 } else {
02338 #endif
02339 ret = snmpv3_packet_build(session, pdu, *pkt, pkt_len, NULL, 0);
02340 #ifdef NETSNMP_USE_REVERSE_ASNENCODING
02341 }
02342 #endif
02343 DEBUGINDENTLESS();
02344 if (-1 != ret) {
02345 session->s_snmp_errno = ret;
02346 }
02347
02348 return ret;
02349
02350 }
02351
02352
02353
02354
02355 static u_char *
02356 snmpv3_header_build(netsnmp_session * session, netsnmp_pdu *pdu,
02357 u_char * packet, size_t * out_length,
02358 size_t length, u_char ** msg_hdr_e)
02359 {
02360 u_char *global_hdr, *global_hdr_e;
02361 u_char *cp;
02362 u_char msg_flags;
02363 long max_size;
02364 long sec_model;
02365 u_char *pb, *pb0e;
02366
02367
02368
02369
02370
02371 cp = asn_build_sequence(packet, out_length,
02372 (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
02373 length);
02374 if (cp == NULL)
02375 return NULL;
02376 if (msg_hdr_e != NULL)
02377 *msg_hdr_e = cp;
02378 pb0e = cp;
02379
02380
02381
02382
02383
02384 DEBUGDUMPHEADER("send", "SNMP Version Number");
02385 cp = asn_build_int(cp, out_length,
02386 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
02387 ASN_INTEGER), (long *) &pdu->version,
02388 sizeof(pdu->version));
02389 DEBUGINDENTLESS();
02390 if (cp == NULL)
02391 return NULL;
02392
02393 global_hdr = cp;
02394
02395
02396
02397 DEBUGDUMPSECTION("send", "msgGlobalData");
02398 cp = asn_build_sequence(cp, out_length,
02399 (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), 0);
02400 if (cp == NULL)
02401 return NULL;
02402 global_hdr_e = cp;
02403
02404
02405
02406
02407
02408 DEBUGDUMPHEADER("send", "msgID");
02409 cp = asn_build_int(cp, out_length,
02410 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
02411 ASN_INTEGER), &pdu->msgid,
02412 sizeof(pdu->msgid));
02413 DEBUGINDENTLESS();
02414 if (cp == NULL)
02415 return NULL;
02416
02417
02418
02419
02420 max_size = session->rcvMsgMaxSize;
02421 DEBUGDUMPHEADER("send", "msgMaxSize");
02422 cp = asn_build_int(cp, out_length,
02423 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
02424 ASN_INTEGER), &max_size,
02425 sizeof(max_size));
02426 DEBUGINDENTLESS();
02427 if (cp == NULL)
02428 return NULL;
02429
02430
02431
02432
02433 snmpv3_calc_msg_flags(pdu->securityLevel, pdu->command, &msg_flags);
02434 DEBUGDUMPHEADER("send", "msgFlags");
02435 cp = asn_build_string(cp, out_length,
02436 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
02437 ASN_OCTET_STR), &msg_flags,
02438 sizeof(msg_flags));
02439 DEBUGINDENTLESS();
02440 if (cp == NULL)
02441 return NULL;
02442
02443
02444
02445
02446 sec_model = pdu->securityModel;
02447 DEBUGDUMPHEADER("send", "msgSecurityModel");
02448 cp = asn_build_int(cp, out_length,
02449 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
02450 ASN_INTEGER), &sec_model,
02451 sizeof(sec_model));
02452 DEBUGINDENTADD(-4);
02453 if (cp == NULL)
02454 return NULL;
02455
02456
02457
02458
02459
02460 pb = asn_build_sequence(global_hdr, out_length,
02461 (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
02462 cp - global_hdr_e);
02463 if (pb == NULL)
02464 return NULL;
02465
02466
02467
02468
02469
02470 pb = asn_build_sequence(packet, out_length,
02471 (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
02472 length + (cp - pb0e));
02473 if (pb == NULL)
02474 return NULL;
02475
02476 return cp;
02477
02478 }
02479
02480 #ifdef NETSNMP_USE_REVERSE_ASNENCODING
02481
02482 int
02483 snmpv3_header_realloc_rbuild(u_char ** pkt, size_t * pkt_len,
02484 size_t * offset, netsnmp_session * session,
02485 netsnmp_pdu *pdu)
02486 {
02487 size_t start_offset = *offset;
02488 u_char msg_flags;
02489 long max_size, sec_model;
02490 int rc = 0;
02491
02492
02493
02494
02495 sec_model = pdu->securityModel;
02496 DEBUGDUMPHEADER("send", "msgSecurityModel");
02497 rc = asn_realloc_rbuild_int(pkt, pkt_len, offset, 1,
02498 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
02499 ASN_INTEGER), &sec_model,
02500 sizeof(sec_model));
02501 DEBUGINDENTLESS();
02502 if (rc == 0) {
02503 return 0;
02504 }
02505
02506
02507
02508
02509 snmpv3_calc_msg_flags(pdu->securityLevel, pdu->command, &msg_flags);
02510 DEBUGDUMPHEADER("send", "msgFlags");
02511 rc = asn_realloc_rbuild_string(pkt, pkt_len, offset, 1,
02512 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE
02513 | ASN_OCTET_STR), &msg_flags,
02514 sizeof(msg_flags));
02515 DEBUGINDENTLESS();
02516 if (rc == 0) {
02517 return 0;
02518 }
02519
02520
02521
02522
02523 max_size = session->rcvMsgMaxSize;
02524 DEBUGDUMPHEADER("send", "msgMaxSize");
02525 rc = asn_realloc_rbuild_int(pkt, pkt_len, offset, 1,
02526 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
02527 ASN_INTEGER), &max_size,
02528 sizeof(max_size));
02529 DEBUGINDENTLESS();
02530 if (rc == 0) {
02531 return 0;
02532 }
02533
02534
02535
02536
02537 DEBUGDUMPHEADER("send", "msgID");
02538 rc = asn_realloc_rbuild_int(pkt, pkt_len, offset, 1,
02539 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
02540 ASN_INTEGER), &pdu->msgid,
02541 sizeof(pdu->msgid));
02542 DEBUGINDENTLESS();
02543 if (rc == 0) {
02544 return 0;
02545 }
02546
02547
02548
02549
02550 rc = asn_realloc_rbuild_sequence(pkt, pkt_len, offset, 1,
02551 (u_char) (ASN_SEQUENCE |
02552 ASN_CONSTRUCTOR),
02553 *offset - start_offset);
02554 if (rc == 0) {
02555 return 0;
02556 }
02557
02558
02559
02560
02561 DEBUGDUMPHEADER("send", "SNMP Version Number");
02562 rc = asn_realloc_rbuild_int(pkt, pkt_len, offset, 1,
02563 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
02564 ASN_INTEGER),
02565 (long *) &pdu->version,
02566 sizeof(pdu->version));
02567 DEBUGINDENTLESS();
02568 return rc;
02569 }
02570 #endif
02571
02572 static u_char *
02573 snmpv3_scopedPDU_header_build(netsnmp_pdu *pdu,
02574 u_char * packet, size_t * out_length,
02575 u_char ** spdu_e)
02576 {
02577 size_t init_length;
02578 u_char *scopedPdu, *pb;
02579
02580
02581 init_length = *out_length;
02582
02583 pb = scopedPdu = packet;
02584 pb = asn_build_sequence(pb, out_length,
02585 (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), 0);
02586 if (pb == NULL)
02587 return NULL;
02588 if (spdu_e)
02589 *spdu_e = pb;
02590
02591 DEBUGDUMPHEADER("send", "contextEngineID");
02592 pb = asn_build_string(pb, out_length,
02593 (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR),
02594 pdu->contextEngineID, pdu->contextEngineIDLen);
02595 DEBUGINDENTLESS();
02596 if (pb == NULL)
02597 return NULL;
02598
02599 DEBUGDUMPHEADER("send", "contextName");
02600 pb = asn_build_string(pb, out_length,
02601 (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR),
02602 (u_char *) pdu->contextName,
02603 pdu->contextNameLen);
02604 DEBUGINDENTLESS();
02605 if (pb == NULL)
02606 return NULL;
02607
02608 return pb;
02609
02610 }
02611
02612
02613 #ifdef NETSNMP_USE_REVERSE_ASNENCODING
02614 int
02615 snmpv3_scopedPDU_header_realloc_rbuild(u_char ** pkt, size_t * pkt_len,
02616 size_t * offset, netsnmp_pdu *pdu,
02617 size_t body_len)
02618 {
02619 size_t start_offset = *offset;
02620 int rc = 0;
02621
02622
02623
02624
02625 DEBUGDUMPHEADER("send", "contextName");
02626 rc = asn_realloc_rbuild_string(pkt, pkt_len, offset, 1,
02627 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE
02628 | ASN_OCTET_STR),
02629 (u_char *) pdu->contextName,
02630 pdu->contextNameLen);
02631 DEBUGINDENTLESS();
02632 if (rc == 0) {
02633 return 0;
02634 }
02635
02636
02637
02638
02639 DEBUGDUMPHEADER("send", "contextEngineID");
02640 rc = asn_realloc_rbuild_string(pkt, pkt_len, offset, 1,
02641 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE
02642 | ASN_OCTET_STR),
02643 pdu->contextEngineID,
02644 pdu->contextEngineIDLen);
02645 DEBUGINDENTLESS();
02646 if (rc == 0) {
02647 return 0;
02648 }
02649
02650 rc = asn_realloc_rbuild_sequence(pkt, pkt_len, offset, 1,
02651 (u_char) (ASN_SEQUENCE |
02652 ASN_CONSTRUCTOR),
02653 *offset - start_offset + body_len);
02654
02655 return rc;
02656 }
02657 #endif
02658
02659 #ifdef NETSNMP_USE_REVERSE_ASNENCODING
02660
02661
02662
02663 int
02664 snmpv3_packet_realloc_rbuild(u_char ** pkt, size_t * pkt_len,
02665 size_t * offset, netsnmp_session * session,
02666 netsnmp_pdu *pdu, u_char * pdu_data,
02667 size_t pdu_data_len)
02668 {
02669 u_char *scoped_pdu, *hdrbuf = NULL, *hdr = NULL;
02670 size_t hdrbuf_len = SNMP_MAX_MSG_V3_HDRS, hdr_offset =
02671 0, spdu_offset = 0;
02672 size_t body_end_offset = *offset, body_len = 0;
02673 struct snmp_secmod_def *sptr = NULL;
02674 int rc = 0;
02675
02676
02677
02678
02679 DEBUGPRINTPDUTYPE("send", pdu->command);
02680 if (pdu_data) {
02681 while ((*pkt_len - *offset) < pdu_data_len) {
02682 if (!asn_realloc(pkt, pkt_len)) {
02683 return -1;
02684 }
02685 }
02686
02687 *offset += pdu_data_len;
02688 memcpy(*pkt + *pkt_len - *offset, pdu_data, pdu_data_len);
02689 } else {
02690 rc = snmp_pdu_realloc_rbuild(pkt, pkt_len, offset, pdu);
02691 if (rc == 0) {
02692 return -1;
02693 }
02694 }
02695 body_len = *offset - body_end_offset;
02696
02697 DEBUGDUMPSECTION("send", "ScopedPdu");
02698 rc = snmpv3_scopedPDU_header_realloc_rbuild(pkt, pkt_len, offset,
02699 pdu, body_len);
02700 if (rc == 0) {
02701 return -1;
02702 }
02703 spdu_offset = *offset;
02704 DEBUGINDENTADD(-4);
02705
02706 if ((hdrbuf = (u_char *) malloc(hdrbuf_len)) == NULL) {
02707 return -1;
02708 }
02709
02710 rc = snmpv3_header_realloc_rbuild(&hdrbuf, &hdrbuf_len, &hdr_offset,
02711 session, pdu);
02712 if (rc == 0) {
02713 SNMP_FREE(hdrbuf);
02714 return -1;
02715 }
02716 hdr = hdrbuf + hdrbuf_len - hdr_offset;
02717 scoped_pdu = *pkt + *pkt_len - spdu_offset;
02718
02719
02720
02721
02722
02723
02724 sptr = find_sec_mod(pdu->securityModel);
02725 DEBUGDUMPSECTION("send", "SM msgSecurityParameters");
02726 if (sptr && sptr->encode_reverse) {
02727 struct snmp_secmod_outgoing_params parms;
02728
02729 parms.msgProcModel = pdu->msgParseModel;
02730 parms.globalData = hdr;
02731 parms.globalDataLen = hdr_offset;
02732 parms.maxMsgSize = SNMP_MAX_MSG_SIZE;
02733 parms.secModel = pdu->securityModel;
02734 parms.secEngineID = pdu->securityEngineID;
02735 parms.secEngineIDLen = pdu->securityEngineIDLen;
02736 parms.secName = pdu->securityName;
02737 parms.secNameLen = pdu->securityNameLen;
02738 parms.secLevel = pdu->securityLevel;
02739 parms.scopedPdu = scoped_pdu;
02740 parms.scopedPduLen = spdu_offset;
02741 parms.secStateRef = pdu->securityStateRef;
02742 parms.wholeMsg = pkt;
02743 parms.wholeMsgLen = pkt_len;
02744 parms.wholeMsgOffset = offset;
02745 parms.session = session;
02746 parms.pdu = pdu;
02747
02748 rc = (*sptr->encode_reverse) (&parms);
02749 } else {
02750 if (!sptr) {
02751 snmp_log(LOG_ERR,
02752 "no such security service available: %d\n",
02753 pdu->securityModel);
02754 } else if (!sptr->encode_reverse) {
02755 snmp_log(LOG_ERR,
02756 "security service %d doesn't support reverse encoding.\n",
02757 pdu->securityModel);
02758 }
02759 rc = -1;
02760 }
02761
02762 DEBUGINDENTLESS();
02763 SNMP_FREE(hdrbuf);
02764 return rc;
02765 }
02766 #endif
02767
02768
02769
02770
02771 int
02772 snmpv3_packet_build(netsnmp_session * session, netsnmp_pdu *pdu,
02773 u_char * packet, size_t * out_length,
02774 u_char * pdu_data, size_t pdu_data_len)
02775 {
02776 u_char *global_data, *sec_params, *spdu_hdr_e;
02777 size_t global_data_len, sec_params_len;
02778 u_char spdu_buf[SNMP_MAX_MSG_SIZE];
02779 size_t spdu_buf_len, spdu_len;
02780 u_char *cp;
02781 int result;
02782 struct snmp_secmod_def *sptr;
02783
02784 global_data = packet;
02785
02786
02787
02788
02789 sec_params = snmpv3_header_build(session, pdu, global_data,
02790 out_length, 0, NULL);
02791 if (sec_params == NULL)
02792 return -1;
02793 global_data_len = sec_params - global_data;
02794 sec_params_len = *out_length;
02795
02796
02797
02798
02799
02800 spdu_buf_len = SNMP_MAX_MSG_SIZE;
02801 DEBUGDUMPSECTION("send", "ScopedPdu");
02802 cp = snmpv3_scopedPDU_header_build(pdu, spdu_buf, &spdu_buf_len,
02803 &spdu_hdr_e);
02804 if (cp == NULL)
02805 return -1;
02806
02807
02808
02809
02810 DEBUGPRINTPDUTYPE("send", ((pdu_data) ? *pdu_data : 0x00));
02811 if (pdu_data) {
02812 memcpy(cp, pdu_data, pdu_data_len);
02813 cp += pdu_data_len;
02814 } else {
02815 cp = snmp_pdu_build(pdu, cp, &spdu_buf_len);
02816 if (cp == NULL)
02817 return -1;
02818 }
02819 DEBUGINDENTADD(-4);
02820
02821
02822
02823
02824 spdu_len = cp - spdu_hdr_e;
02825 spdu_buf_len = SNMP_MAX_MSG_SIZE;
02826 if (asn_build_sequence(spdu_buf, &spdu_buf_len,
02827 (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
02828 spdu_len) == NULL)
02829 return -1;
02830 spdu_len = cp - spdu_buf;
02831
02832
02833
02834
02835
02836
02837 cp = NULL;
02838 *out_length = SNMP_MAX_MSG_SIZE;
02839 DEBUGDUMPSECTION("send", "SM msgSecurityParameters");
02840 sptr = find_sec_mod(pdu->securityModel);
02841 if (sptr && sptr->encode_forward) {
02842 struct snmp_secmod_outgoing_params parms;
02843 parms.msgProcModel = pdu->msgParseModel;
02844 parms.globalData = global_data;
02845 parms.globalDataLen = global_data_len;
02846 parms.maxMsgSize = SNMP_MAX_MSG_SIZE;
02847 parms.secModel = pdu->securityModel;
02848 parms.secEngineID = pdu->securityEngineID;
02849 parms.secEngineIDLen = pdu->securityEngineIDLen;
02850 parms.secName = pdu->securityName;
02851 parms.secNameLen = pdu->securityNameLen;
02852 parms.secLevel = pdu->securityLevel;
02853 parms.scopedPdu = spdu_buf;
02854 parms.scopedPduLen = spdu_len;
02855 parms.secStateRef = pdu->securityStateRef;
02856 parms.secParams = sec_params;
02857 parms.secParamsLen = &sec_params_len;
02858 parms.wholeMsg = &cp;
02859 parms.wholeMsgLen = out_length;
02860 parms.session = session;
02861 parms.pdu = pdu;
02862 result = (*sptr->encode_forward) (&parms);
02863 } else {
02864 if (!sptr) {
02865 snmp_log(LOG_ERR, "no such security service available: %d\n",
02866 pdu->securityModel);
02867 } else if (!sptr->encode_forward) {
02868 snmp_log(LOG_ERR,
02869 "security service %d doesn't support forward out encoding.\n",
02870 pdu->securityModel);
02871 }
02872 result = -1;
02873 }
02874 DEBUGINDENTLESS();
02875 return result;
02876
02877 }
02878
02879
02880
02881
02882
02883
02884
02885
02886
02887 static int
02888 _snmp_build(u_char ** pkt, size_t * pkt_len, size_t * offset,
02889 netsnmp_session * session, netsnmp_pdu *pdu)
02890 {
02891 #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
02892 u_char *h0e = NULL;
02893 size_t start_offset = *offset;
02894 long version;
02895 int rc = 0;
02896 #endif
02897
02898 u_char *h0, *h1;
02899 u_char *cp;
02900 size_t length;
02901
02902 session->s_snmp_errno = 0;
02903 session->s_errno = 0;
02904
02905 if (pdu->version == SNMP_VERSION_3) {
02906 return snmpv3_build(pkt, pkt_len, offset, session, pdu);
02907 }
02908
02909 switch (pdu->command) {
02910 case SNMP_MSG_RESPONSE:
02911 netsnmp_assert(0 == (pdu->flags & UCD_MSG_FLAG_EXPECT_RESPONSE));
02912
02913
02914
02915 case SNMP_MSG_GET:
02916 case SNMP_MSG_GETNEXT:
02917 case SNMP_MSG_SET:
02918
02919
02920
02921
02922
02923
02924
02925 if (pdu->errstat == SNMP_DEFAULT_ERRSTAT)
02926 pdu->errstat = 0;
02927 if (pdu->errindex == SNMP_DEFAULT_ERRINDEX)
02928 pdu->errindex = 0;
02929 break;
02930
02931 case SNMP_MSG_TRAP2:
02932 netsnmp_assert(0 == (pdu->flags & UCD_MSG_FLAG_EXPECT_RESPONSE));
02933
02934
02935
02936 case SNMP_MSG_INFORM:
02937 #ifndef NETSNMP_DISABLE_SNMPV1
02938
02939
02940
02941 if (pdu->version == SNMP_VERSION_1) {
02942 session->s_snmp_errno = SNMPERR_V2_IN_V1;
02943 return -1;
02944 }
02945 #endif
02946 if (pdu->errstat == SNMP_DEFAULT_ERRSTAT)
02947 pdu->errstat = 0;
02948 if (pdu->errindex == SNMP_DEFAULT_ERRINDEX)
02949 pdu->errindex = 0;
02950 break;
02951
02952 case SNMP_MSG_GETBULK:
02953
02954
02955
02956 #ifndef NETSNMP_DISABLE_SNMPV1
02957 if (pdu->version == SNMP_VERSION_1) {
02958 session->s_snmp_errno = SNMPERR_V2_IN_V1;
02959 return -1;
02960 }
02961 #endif
02962 if (pdu->max_repetitions < 0) {
02963 session->s_snmp_errno = SNMPERR_BAD_REPETITIONS;
02964 return -1;
02965 }
02966 if (pdu->non_repeaters < 0) {
02967 session->s_snmp_errno = SNMPERR_BAD_REPEATERS;
02968 return -1;
02969 }
02970 break;
02971
02972 case SNMP_MSG_TRAP:
02973
02974
02975
02976 #ifndef NETSNMP_DISABLE_SNMPV1
02977 if (pdu->version != SNMP_VERSION_1) {
02978 session->s_snmp_errno = SNMPERR_V1_IN_V2;
02979 return -1;
02980 }
02981 #endif
02982
02983
02984
02985 pdu->reqid = 1;
02986 if (pdu->enterprise_length == SNMP_DEFAULT_ENTERPRISE_LENGTH) {
02987 pdu->enterprise = (oid *) malloc(sizeof(DEFAULT_ENTERPRISE));
02988 if (pdu->enterprise == NULL) {
02989 session->s_snmp_errno = SNMPERR_MALLOC;
02990 return -1;
02991 }
02992 memmove(pdu->enterprise, DEFAULT_ENTERPRISE,
02993 sizeof(DEFAULT_ENTERPRISE));
02994 pdu->enterprise_length =
02995 sizeof(DEFAULT_ENTERPRISE) / sizeof(oid);
02996 }
02997 if (pdu->time == SNMP_DEFAULT_TIME)
02998 pdu->time = DEFAULT_TIME;
02999
03000
03001
03002 pdu->flags &= (~UCD_MSG_FLAG_EXPECT_RESPONSE);
03003 break;
03004
03005 case SNMP_MSG_REPORT:
03006 default:
03007 session->s_snmp_errno = SNMPERR_UNKNOWN_PDU;
03008 return -1;
03009 }
03010
03011
03012
03013
03014 length = *pkt_len;
03015
03016
03017
03018
03019
03020
03021
03022
03023
03024 h0 = *pkt;
03025 switch (pdu->version) {
03026 #ifndef NETSNMP_DISABLE_SNMPV1
03027 case SNMP_VERSION_1:
03028 #endif
03029 #ifndef NETSNMP_DISABLE_SNMPV2C
03030 case SNMP_VERSION_2c:
03031 #endif
03032 #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
03033 #ifdef NETSNMP_NO_ZEROLENGTH_COMMUNITY
03034 if (pdu->community_len == 0) {
03035 if (session->community_len == 0) {
03036 session->s_snmp_errno = SNMPERR_BAD_COMMUNITY;
03037 return -1;
03038 }
03039 pdu->community = (u_char *) malloc(session->community_len);
03040 if (pdu->community == NULL) {
03041 session->s_snmp_errno = SNMPERR_MALLOC;
03042 return -1;
03043 }
03044 memmove(pdu->community,
03045 session->community, session->community_len);
03046 pdu->community_len = session->community_len;
03047 }
03048 #else
03049 if (pdu->community_len == 0 && pdu->command != SNMP_MSG_RESPONSE) {
03050
03051
03052
03053 if (0 == session->community_len) {
03054 SNMP_FREE(pdu->community);
03055 pdu->community = NULL;
03056 } else if (pdu->community_len == session->community_len) {
03057 memmove(pdu->community,
03058 session->community, session->community_len);
03059 } else {
03060 SNMP_FREE(pdu->community);
03061 pdu->community = (u_char *) malloc(session->community_len);
03062 if (pdu->community == NULL) {
03063 session->s_snmp_errno = SNMPERR_MALLOC;
03064 return -1;
03065 }
03066 memmove(pdu->community,
03067 session->community, session->community_len);
03068 }
03069 pdu->community_len = session->community_len;
03070 }
03071 #endif
03072
03073 DEBUGMSGTL(("snmp_send", "Building SNMPv%ld message...\n",
03074 (1 + pdu->version)));
03075 #ifdef NETSNMP_USE_REVERSE_ASNENCODING
03076 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_REVERSE_ENCODE)) {
03077 DEBUGPRINTPDUTYPE("send", pdu->command);
03078 rc = snmp_pdu_realloc_rbuild(pkt, pkt_len, offset, pdu);
03079 if (rc == 0) {
03080 return -1;
03081 }
03082
03083 DEBUGDUMPHEADER("send", "Community String");
03084 rc = asn_realloc_rbuild_string(pkt, pkt_len, offset, 1,
03085 (u_char) (ASN_UNIVERSAL |
03086 ASN_PRIMITIVE |
03087 ASN_OCTET_STR),
03088 pdu->community,
03089 pdu->community_len);
03090 DEBUGINDENTLESS();
03091 if (rc == 0) {
03092 return -1;
03093 }
03094
03095
03096
03097
03098
03099 DEBUGDUMPHEADER("send", "SNMP Version Number");
03100
03101 version = pdu->version;
03102 rc = asn_realloc_rbuild_int(pkt, pkt_len, offset, 1,
03103 (u_char) (ASN_UNIVERSAL |
03104 ASN_PRIMITIVE |
03105 ASN_INTEGER),
03106 (long *) &version,
03107 sizeof(version));
03108 DEBUGINDENTLESS();
03109 if (rc == 0) {
03110 return -1;
03111 }
03112
03113
03114
03115
03116 #ifndef NETSNMP_DISABLE_SNMPV1
03117 if (pdu->version == SNMP_VERSION_1) {
03118 DEBUGDUMPSECTION("send", "SNMPv1 Message");
03119 } else {
03120 #endif
03121 DEBUGDUMPSECTION("send", "SNMPv2c Message");
03122 #ifndef NETSNMP_DISABLE_SNMPV1
03123 }
03124 #endif
03125 rc = asn_realloc_rbuild_sequence(pkt, pkt_len, offset, 1,
03126 (u_char) (ASN_SEQUENCE |
03127 ASN_CONSTRUCTOR),
03128 *offset - start_offset);
03129 DEBUGINDENTLESS();
03130
03131 if (rc == 0) {
03132 return -1;
03133 }
03134 return 0;
03135 } else {
03136
03137 #endif
03138
03139
03140
03141
03142
03143 cp = asn_build_sequence(*pkt, pkt_len,
03144 (u_char) (ASN_SEQUENCE |
03145 ASN_CONSTRUCTOR), 0);
03146 if (cp == NULL) {
03147 return -1;
03148 }
03149 h0e = cp;
03150
03151 #ifndef NETSNMP_DISABLE_SNMPV1
03152 if (pdu->version == SNMP_VERSION_1) {
03153 DEBUGDUMPSECTION("send", "SNMPv1 Message");
03154 } else {
03155 #endif
03156 DEBUGDUMPSECTION("send", "SNMPv2c Message");
03157 #ifndef NETSNMP_DISABLE_SNMPV1
03158 }
03159 #endif
03160
03161
03162
03163
03164 DEBUGDUMPHEADER("send", "SNMP Version Number");
03165
03166 version = pdu->version;
03167 cp = asn_build_int(cp, pkt_len,
03168 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
03169 ASN_INTEGER), (long *) &version,
03170 sizeof(version));
03171 DEBUGINDENTLESS();
03172 if (cp == NULL)
03173 return -1;
03174
03175
03176
03177
03178 DEBUGDUMPHEADER("send", "Community String");
03179 cp = asn_build_string(cp, pkt_len,
03180 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
03181 ASN_OCTET_STR), pdu->community,
03182 pdu->community_len);
03183 DEBUGINDENTLESS();
03184 if (cp == NULL)
03185 return -1;
03186 break;
03187
03188 #ifdef NETSNMP_USE_REVERSE_ASNENCODING
03189 }
03190 #endif
03191 break;
03192 #endif
03193 case SNMP_VERSION_2p:
03194 case SNMP_VERSION_sec:
03195 case SNMP_VERSION_2u:
03196 case SNMP_VERSION_2star:
03197 default:
03198 session->s_snmp_errno = SNMPERR_BAD_VERSION;
03199 return -1;
03200 }
03201
03202 h1 = cp;
03203 DEBUGPRINTPDUTYPE("send", pdu->command);
03204 cp = snmp_pdu_build(pdu, cp, pkt_len);
03205 DEBUGINDENTADD(-4);
03206 if (cp == NULL)
03207 return -1;
03208
03209
03210
03211
03212 switch (pdu->version) {
03213 #ifndef NETSNMP_DISABLE_SNMPV1
03214 case SNMP_VERSION_1:
03215 #endif
03216 #ifndef NETSNMP_DISABLE_SNMPV2C
03217 case SNMP_VERSION_2c:
03218 #endif
03219 #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
03220 asn_build_sequence(*pkt, &length,
03221 (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
03222 cp - h0e);
03223 break;
03224 #endif
03225
03226 case SNMP_VERSION_2p:
03227 case SNMP_VERSION_sec:
03228 case SNMP_VERSION_2u:
03229 case SNMP_VERSION_2star:
03230 default:
03231 session->s_snmp_errno = SNMPERR_BAD_VERSION;
03232 return -1;
03233 }
03234 *pkt_len = cp - *pkt;
03235 return 0;
03236 }
03237
03238 int
03239 snmp_build(u_char ** pkt, size_t * pkt_len, size_t * offset,
03240 netsnmp_session * pss, netsnmp_pdu *pdu)
03241 {
03242 int rc;
03243 rc = _snmp_build(pkt, pkt_len, offset, pss, pdu);
03244 if (rc) {
03245 if (!pss->s_snmp_errno) {
03246 snmp_log(LOG_ERR, "snmp_build: unknown failure");
03247 pss->s_snmp_errno = SNMPERR_BAD_ASN1_BUILD;
03248 }
03249 SET_SNMP_ERROR(pss->s_snmp_errno);
03250 rc = -1;
03251 }
03252 return rc;
03253 }
03254
03255
03256
03257
03258 u_char *
03259 snmp_pdu_build(netsnmp_pdu *pdu, u_char * cp, size_t * out_length)
03260 {
03261 u_char *h1, *h1e, *h2, *h2e;
03262 netsnmp_variable_list *vp;
03263 size_t length;
03264
03265 length = *out_length;
03266
03267
03268
03269
03270 h1 = cp;
03271 cp = asn_build_sequence(cp, out_length, (u_char) pdu->command, 0);
03272 if (cp == NULL)
03273 return NULL;
03274 h1e = cp;
03275
03276
03277
03278
03279 if (pdu->command != SNMP_MSG_TRAP) {
03280
03281
03282
03283
03284 DEBUGDUMPHEADER("send", "request_id");
03285
03286
03287
03288 cp = asn_build_int(cp, out_length,
03289 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
03290 ASN_INTEGER), &pdu->reqid,
03291 sizeof(pdu->reqid));
03292 DEBUGINDENTLESS();
03293 if (cp == NULL)
03294 return NULL;
03295
03296
03297
03298
03299 DEBUGDUMPHEADER("send", "error status");
03300 cp = asn_build_int(cp, out_length,
03301 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
03302 ASN_INTEGER), &pdu->errstat,
03303 sizeof(pdu->errstat));
03304 DEBUGINDENTLESS();
03305 if (cp == NULL)
03306 return NULL;
03307
03308
03309
03310
03311 DEBUGDUMPHEADER("send", "error index");
03312 cp = asn_build_int(cp, out_length,
03313 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
03314 ASN_INTEGER), &pdu->errindex,
03315 sizeof(pdu->errindex));
03316 DEBUGINDENTLESS();
03317 if (cp == NULL)
03318 return NULL;
03319 } else {
03320
03321
03322
03323
03324
03325
03326
03327 DEBUGDUMPHEADER("send", "enterprise OBJID");
03328 cp = asn_build_objid(cp, out_length,
03329 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
03330 ASN_OBJECT_ID),
03331 (oid *) pdu->enterprise,
03332 pdu->enterprise_length);
03333 DEBUGINDENTLESS();
03334 if (cp == NULL)
03335 return NULL;
03336
03337
03338
03339
03340 DEBUGDUMPHEADER("send", "agent Address");
03341 cp = asn_build_string(cp, out_length,
03342 (u_char) (ASN_IPADDRESS | ASN_PRIMITIVE),
03343 (u_char *) pdu->agent_addr, 4);
03344 DEBUGINDENTLESS();
03345 if (cp == NULL)
03346 return NULL;
03347
03348
03349
03350
03351 DEBUGDUMPHEADER("send", "generic trap number");
03352 cp = asn_build_int(cp, out_length,
03353 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
03354 ASN_INTEGER),
03355 (long *) &pdu->trap_type,
03356 sizeof(pdu->trap_type));
03357 DEBUGINDENTLESS();
03358 if (cp == NULL)
03359 return NULL;
03360
03361
03362
03363
03364 DEBUGDUMPHEADER("send", "specific trap number");
03365 cp = asn_build_int(cp, out_length,
03366 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
03367 ASN_INTEGER),
03368 (long *) &pdu->specific_type,
03369 sizeof(pdu->specific_type));
03370 DEBUGINDENTLESS();
03371 if (cp == NULL)
03372 return NULL;
03373
03374
03375
03376
03377 DEBUGDUMPHEADER("send", "timestamp");
03378 cp = asn_build_unsigned_int(cp, out_length,
03379 (u_char) (ASN_TIMETICKS |
03380 ASN_PRIMITIVE), &pdu->time,
03381 sizeof(pdu->time));
03382 DEBUGINDENTLESS();
03383 if (cp == NULL)
03384 return NULL;
03385 }
03386
03387
03388
03389
03390
03391
03392 h2 = cp;
03393 cp = asn_build_sequence(cp, out_length,
03394 (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), 0);
03395 if (cp == NULL)
03396 return NULL;
03397 h2e = cp;
03398
03399
03400
03401
03402 DEBUGDUMPSECTION("send", "VarBindList");
03403 for (vp = pdu->variables; vp; vp = vp->next_variable) {
03404 DEBUGDUMPSECTION("send", "VarBind");
03405 cp = snmp_build_var_op(cp, vp->name, &vp->name_length, vp->type,
03406 vp->val_len, (u_char *) vp->val.string,
03407 out_length);
03408 DEBUGINDENTLESS();
03409 if (cp == NULL)
03410 return NULL;
03411 }
03412 DEBUGINDENTLESS();
03413
03414
03415
03416
03417 asn_build_sequence(h2, &length,
03418 (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
03419 cp - h2e);
03420
03421
03422
03423
03424 asn_build_sequence(h1, &length, (u_char) pdu->command, cp - h1e);
03425
03426 return cp;
03427 }
03428
03429 #ifdef NETSNMP_USE_REVERSE_ASNENCODING
03430
03431
03432
03433 int
03434 snmp_pdu_realloc_rbuild(u_char ** pkt, size_t * pkt_len, size_t * offset,
03435 netsnmp_pdu *pdu)
03436 {
03437 #ifndef VPCACHE_SIZE
03438 #define VPCACHE_SIZE 50
03439 #endif
03440 netsnmp_variable_list *vpcache[VPCACHE_SIZE];
03441 netsnmp_variable_list *vp, *tmpvp;
03442 size_t start_offset = *offset;
03443 int i, wrapped = 0, notdone, final, rc = 0;
03444
03445 DEBUGMSGTL(("snmp_pdu_realloc_rbuild", "starting\n"));
03446 for (vp = pdu->variables, i = VPCACHE_SIZE - 1; vp;
03447 vp = vp->next_variable, i--) {
03448 if (i < 0) {
03449 wrapped = notdone = 1;
03450 i = VPCACHE_SIZE - 1;
03451 DEBUGMSGTL(("snmp_pdu_realloc_rbuild", "wrapped\n"));
03452 }
03453 vpcache[i] = vp;
03454 }
03455 final = i + 1;
03456
03457 do {
03458 for (i = final; i < VPCACHE_SIZE; i++) {
03459 vp = vpcache[i];
03460 DEBUGDUMPSECTION("send", "VarBind");
03461 rc = snmp_realloc_rbuild_var_op(pkt, pkt_len, offset, 1,
03462 vp->name, &vp->name_length,
03463 vp->type,
03464 (u_char *) vp->val.string,
03465 vp->val_len);
03466 DEBUGINDENTLESS();
03467 if (rc == 0) {
03468 return 0;
03469 }
03470 }
03471
03472 DEBUGINDENTLESS();
03473 if (wrapped) {
03474 notdone = 1;
03475 for (i = 0; i < final; i++) {
03476 vp = vpcache[i];
03477 DEBUGDUMPSECTION("send", "VarBind");
03478 rc = snmp_realloc_rbuild_var_op(pkt, pkt_len, offset, 1,
03479 vp->name, &vp->name_length,
03480 vp->type,
03481 (u_char *) vp->val.string,
03482 vp->val_len);
03483 DEBUGINDENTLESS();
03484 if (rc == 0) {
03485 return 0;
03486 }
03487 }
03488
03489 if (final == 0) {
03490 tmpvp = vpcache[VPCACHE_SIZE - 1];
03491 } else {
03492 tmpvp = vpcache[final - 1];
03493 }
03494 wrapped = 0;
03495
03496 for (vp = pdu->variables, i = VPCACHE_SIZE - 1;
03497 vp && vp != tmpvp; vp = vp->next_variable, i--) {
03498 if (i < 0) {
03499 wrapped = 1;
03500 i = VPCACHE_SIZE - 1;
03501 DEBUGMSGTL(("snmp_pdu_realloc_rbuild", "wrapped\n"));
03502 }
03503 vpcache[i] = vp;
03504 }
03505 final = i + 1;
03506 } else {
03507 notdone = 0;
03508 }
03509 } while (notdone);
03510
03511
03512
03513
03514
03515
03516 rc = asn_realloc_rbuild_sequence(pkt, pkt_len, offset, 1,
03517 (u_char) (ASN_SEQUENCE |
03518 ASN_CONSTRUCTOR),
03519 *offset - start_offset);
03520
03521
03522
03523
03524 if (pdu->command != SNMP_MSG_TRAP) {
03525
03526
03527
03528 DEBUGDUMPHEADER("send", "error index");
03529 rc = asn_realloc_rbuild_int(pkt, pkt_len, offset, 1,
03530 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE
03531 | ASN_INTEGER),
03532 &pdu->errindex, sizeof(pdu->errindex));
03533 DEBUGINDENTLESS();
03534 if (rc == 0) {
03535 return 0;
03536 }
03537
03538
03539
03540
03541 DEBUGDUMPHEADER("send", "error status");
03542 rc = asn_realloc_rbuild_int(pkt, pkt_len, offset, 1,
03543 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE
03544 | ASN_INTEGER),
03545 &pdu->errstat, sizeof(pdu->errstat));
03546 DEBUGINDENTLESS();
03547 if (rc == 0) {
03548 return 0;
03549 }
03550
03551
03552
03553
03554 DEBUGDUMPHEADER("send", "request_id");
03555 rc = asn_realloc_rbuild_int(pkt, pkt_len, offset, 1,
03556 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE
03557 | ASN_INTEGER), &pdu->reqid,
03558 sizeof(pdu->reqid));
03559 DEBUGINDENTLESS();
03560 if (rc == 0) {
03561 return 0;
03562 }
03563 } else {
03564
03565
03566
03567
03568
03569
03570
03571 DEBUGDUMPHEADER("send", "timestamp");
03572 rc = asn_realloc_rbuild_unsigned_int(pkt, pkt_len, offset, 1,
03573 (u_char) (ASN_TIMETICKS |
03574 ASN_PRIMITIVE),
03575 &pdu->time,
03576 sizeof(pdu->time));
03577 DEBUGINDENTLESS();
03578 if (rc == 0) {
03579 return 0;
03580 }
03581
03582
03583
03584
03585 DEBUGDUMPHEADER("send", "specific trap number");
03586 rc = asn_realloc_rbuild_int(pkt, pkt_len, offset, 1,
03587 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE
03588 | ASN_INTEGER),
03589 (long *) &pdu->specific_type,
03590 sizeof(pdu->specific_type));
03591 DEBUGINDENTLESS();
03592 if (rc == 0) {
03593 return 0;
03594 }
03595
03596
03597
03598
03599 DEBUGDUMPHEADER("send", "generic trap number");
03600 rc = asn_realloc_rbuild_int(pkt, pkt_len, offset, 1,
03601 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE
03602 | ASN_INTEGER),
03603 (long *) &pdu->trap_type,
03604 sizeof(pdu->trap_type));
03605 DEBUGINDENTLESS();
03606 if (rc == 0) {
03607 return 0;
03608 }
03609
03610
03611
03612
03613 DEBUGDUMPHEADER("send", "agent Address");
03614 rc = asn_realloc_rbuild_string(pkt, pkt_len, offset, 1,
03615 (u_char) (ASN_IPADDRESS |
03616 ASN_PRIMITIVE),
03617 (u_char *) pdu->agent_addr, 4);
03618 DEBUGINDENTLESS();
03619 if (rc == 0) {
03620 return 0;
03621 }
03622
03623
03624
03625
03626 DEBUGDUMPHEADER("send", "enterprise OBJID");
03627 rc = asn_realloc_rbuild_objid(pkt, pkt_len, offset, 1,
03628 (u_char) (ASN_UNIVERSAL |
03629 ASN_PRIMITIVE |
03630 ASN_OBJECT_ID),
03631 (oid *) pdu->enterprise,
03632 pdu->enterprise_length);
03633 DEBUGINDENTLESS();
03634 if (rc == 0) {
03635 return 0;
03636 }
03637 }
03638
03639
03640
03641
03642 rc = asn_realloc_rbuild_sequence(pkt, pkt_len, offset, 1,
03643 (u_char) pdu->command,
03644 *offset - start_offset);
03645 return rc;
03646 }
03647 #endif
03648
03649
03650
03651
03652
03653 static int
03654 snmp_parse_version(u_char * data, size_t length)
03655 {
03656 u_char type;
03657 long version = SNMPERR_BAD_VERSION;
03658
03659 data = asn_parse_sequence(data, &length, &type,
03660 (ASN_SEQUENCE | ASN_CONSTRUCTOR), "version");
03661 if (data) {
03662 data =
03663 asn_parse_int(data, &length, &type, &version, sizeof(version));
03664 if (!data || type != ASN_INTEGER) {
03665 return SNMPERR_BAD_VERSION;
03666 }
03667 }
03668 return version;
03669 }
03670
03671
03672 int
03673 snmpv3_parse(netsnmp_pdu *pdu,
03674 u_char * data,
03675 size_t * length,
03676 u_char ** after_header, netsnmp_session * sess)
03677 {
03678 u_char type, msg_flags;
03679 long ver, msg_max_size, msg_sec_model;
03680 size_t max_size_response;
03681 u_char tmp_buf[SNMP_MAX_MSG_SIZE];
03682 size_t tmp_buf_len;
03683 u_char pdu_buf[SNMP_MAX_MSG_SIZE];
03684 u_char *mallocbuf = NULL;
03685 size_t pdu_buf_len = SNMP_MAX_MSG_SIZE;
03686 u_char *sec_params;
03687 u_char *msg_data;
03688 u_char *cp;
03689 size_t asn_len, msg_len;
03690 int ret, ret_val;
03691 struct snmp_secmod_def *sptr;
03692
03693
03694 msg_data = data;
03695 msg_len = *length;
03696
03697
03698
03699
03700
03701 DEBUGDUMPSECTION("recv", "SNMPv3 Message");
03702 data = asn_parse_sequence(data, length, &type,
03703 (ASN_SEQUENCE | ASN_CONSTRUCTOR), "message");
03704 if (data == NULL) {
03705
03706
03707
03708 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
03709 DEBUGINDENTLESS();
03710 return SNMPERR_ASN_PARSE_ERR;
03711 }
03712
03713
03714
03715
03716 DEBUGDUMPHEADER("recv", "SNMP Version Number");
03717 data = asn_parse_int(data, length, &type, &ver, sizeof(ver));
03718 DEBUGINDENTLESS();
03719 if (data == NULL) {
03720 ERROR_MSG("bad parse of version");
03721 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
03722 DEBUGINDENTLESS();
03723 return SNMPERR_ASN_PARSE_ERR;
03724 }
03725 pdu->version = ver;
03726
03727
03728
03729
03730 cp = data;
03731 asn_len = *length;
03732 DEBUGDUMPSECTION("recv", "msgGlobalData");
03733 data = asn_parse_sequence(data, &asn_len, &type,
03734 (ASN_SEQUENCE | ASN_CONSTRUCTOR),
03735 "msgGlobalData");
03736 if (data == NULL) {
03737
03738
03739
03740 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
03741 DEBUGINDENTADD(-4);
03742 return SNMPERR_ASN_PARSE_ERR;
03743 }
03744 *length -= data - cp;
03745
03746
03747
03748
03749 DEBUGDUMPHEADER("recv", "msgID");
03750 data =
03751 asn_parse_int(data, length, &type, &pdu->msgid,
03752 sizeof(pdu->msgid));
03753 DEBUGINDENTLESS();
03754 if (data == NULL || type != ASN_INTEGER) {
03755 ERROR_MSG("error parsing msgID");
03756 DEBUGINDENTADD(-4);
03757 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
03758 return SNMPERR_ASN_PARSE_ERR;
03759 }
03760
03761
03762
03763
03764
03765
03766
03767
03768
03769 if (pdu->msgid < 0 || pdu->msgid > 0x7fffffff) {
03770 snmp_log(LOG_ERR, "Received bad msgID (%ld %s %s).\n", pdu->msgid,
03771 (pdu->msgid < 0) ? "<" : ">",
03772 (pdu->msgid < 0) ? "0" : "2^31 - 1");
03773 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
03774 DEBUGINDENTADD(-4);
03775 return SNMPERR_ASN_PARSE_ERR;
03776 }
03777
03778
03779
03780
03781 DEBUGDUMPHEADER("recv", "msgMaxSize");
03782 data = asn_parse_int(data, length, &type, &msg_max_size,
03783 sizeof(msg_max_size));
03784 DEBUGINDENTLESS();
03785 if (data == NULL || type != ASN_INTEGER) {
03786 ERROR_MSG("error parsing msgMaxSize");
03787 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
03788 DEBUGINDENTADD(-4);
03789 return SNMPERR_ASN_PARSE_ERR;
03790 }
03791
03792
03793
03794
03795
03796
03797
03798
03799
03800
03801
03802
03803
03804
03805 if (msg_max_size < 484) {
03806 snmp_log(LOG_ERR, "Received bad msgMaxSize (%lu < 484).\n",
03807 msg_max_size);
03808 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
03809 DEBUGINDENTADD(-4);
03810 return SNMPERR_ASN_PARSE_ERR;
03811 } else if (msg_max_size > 0x7fffffff) {
03812 snmp_log(LOG_ERR, "Received bad msgMaxSize (%lu > 2^31 - 1).\n",
03813 msg_max_size);
03814 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
03815 DEBUGINDENTADD(-4);
03816 return SNMPERR_ASN_PARSE_ERR;
03817 } else {
03818 DEBUGMSGTL(("snmpv3_parse", "msgMaxSize %lu received\n",
03819 msg_max_size));
03820 sess->sndMsgMaxSize = msg_max_size;
03821 }
03822
03823
03824
03825
03826 tmp_buf_len = SNMP_MAX_MSG_SIZE;
03827 DEBUGDUMPHEADER("recv", "msgFlags");
03828 data = asn_parse_string(data, length, &type, tmp_buf, &tmp_buf_len);
03829 DEBUGINDENTLESS();
03830 if (data == NULL || type != ASN_OCTET_STR || tmp_buf_len != 1) {
03831 ERROR_MSG("error parsing msgFlags");
03832 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
03833 DEBUGINDENTADD(-4);
03834 return SNMPERR_ASN_PARSE_ERR;
03835 }
03836 msg_flags = *tmp_buf;
03837 if (msg_flags & SNMP_MSG_FLAG_RPRT_BIT)
03838 pdu->flags |= SNMP_MSG_FLAG_RPRT_BIT;
03839 else
03840 pdu->flags &= (~SNMP_MSG_FLAG_RPRT_BIT);
03841
03842
03843
03844
03845 DEBUGDUMPHEADER("recv", "msgSecurityModel");
03846 data = asn_parse_int(data, length, &type, &msg_sec_model,
03847 sizeof(msg_sec_model));
03848 DEBUGINDENTADD(-4);
03849 if (data == NULL || type != ASN_INTEGER ||
03850 msg_sec_model < 1 || msg_sec_model > 0x7fffffff) {
03851 ERROR_MSG("error parsing msgSecurityModel");
03852 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
03853 DEBUGINDENTLESS();
03854 return SNMPERR_ASN_PARSE_ERR;
03855 }
03856 sptr = find_sec_mod(msg_sec_model);
03857 if (!sptr) {
03858 snmp_log(LOG_WARNING, "unknown security model: %ld\n",
03859 msg_sec_model);
03860 snmp_increment_statistic(STAT_SNMPUNKNOWNSECURITYMODELS);
03861 DEBUGINDENTLESS();
03862 return SNMPERR_UNKNOWN_SEC_MODEL;
03863 }
03864 pdu->securityModel = msg_sec_model;
03865
03866 if (msg_flags & SNMP_MSG_FLAG_PRIV_BIT &&
03867 !(msg_flags & SNMP_MSG_FLAG_AUTH_BIT)) {
03868 ERROR_MSG("invalid message, illegal msgFlags");
03869 snmp_increment_statistic(STAT_SNMPINVALIDMSGS);
03870 DEBUGINDENTLESS();
03871 return SNMPERR_INVALID_MSG;
03872 }
03873 pdu->securityLevel = ((msg_flags & SNMP_MSG_FLAG_AUTH_BIT)
03874 ? ((msg_flags & SNMP_MSG_FLAG_PRIV_BIT)
03875 ? SNMP_SEC_LEVEL_AUTHPRIV
03876 : SNMP_SEC_LEVEL_AUTHNOPRIV)
03877 : SNMP_SEC_LEVEL_NOAUTH);
03878
03879
03880
03881
03882
03883
03884
03885 sec_params = data;
03886 pdu->contextEngineID = (u_char *) calloc(1, SNMP_MAX_ENG_SIZE);
03887 pdu->contextEngineIDLen = SNMP_MAX_ENG_SIZE;
03888
03889
03890
03891
03892
03893
03894
03895 pdu->securityEngineID = (u_char *) calloc(1, SNMP_MAX_ENG_SIZE * 2);
03896 pdu->securityEngineIDLen = SNMP_MAX_ENG_SIZE * 2;
03897 pdu->securityName = (char *) calloc(1, SNMP_MAX_SEC_NAME_SIZE);
03898 pdu->securityNameLen = SNMP_MAX_SEC_NAME_SIZE;
03899
03900 if ((pdu->securityName == NULL) ||
03901 (pdu->securityEngineID == NULL) ||
03902 (pdu->contextEngineID == NULL)) {
03903 return SNMPERR_MALLOC;
03904 }
03905
03906 if (pdu_buf_len < msg_len
03907 && pdu->securityLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
03908
03909
03910
03911 mallocbuf = (u_char *) calloc(1, msg_len);
03912 pdu_buf_len = msg_len;
03913 cp = mallocbuf;
03914 } else {
03915 memset(pdu_buf, 0, pdu_buf_len);
03916 cp = pdu_buf;
03917 }
03918
03919 DEBUGDUMPSECTION("recv", "SM msgSecurityParameters");
03920 if (sptr->decode) {
03921 struct snmp_secmod_incoming_params parms;
03922 parms.msgProcModel = pdu->msgParseModel;
03923 parms.maxMsgSize = msg_max_size;
03924 parms.secParams = sec_params;
03925 parms.secModel = msg_sec_model;
03926 parms.secLevel = pdu->securityLevel;
03927 parms.wholeMsg = msg_data;
03928 parms.wholeMsgLen = msg_len;
03929 parms.secEngineID = pdu->securityEngineID;
03930 parms.secEngineIDLen = &pdu->securityEngineIDLen;
03931 parms.secName = pdu->securityName;
03932 parms.secNameLen = &pdu->securityNameLen;
03933 parms.scopedPdu = &cp;
03934 parms.scopedPduLen = &pdu_buf_len;
03935 parms.maxSizeResponse = &max_size_response;
03936 parms.secStateRef = &pdu->securityStateRef;
03937 parms.sess = sess;
03938 parms.pdu = pdu;
03939 parms.msg_flags = msg_flags;
03940 ret_val = (*sptr->decode) (&parms);
03941 } else {
03942 SNMP_FREE(mallocbuf);
03943 DEBUGINDENTLESS();
03944 snmp_log(LOG_WARNING, "security service %ld can't decode packets\n",
03945 msg_sec_model);
03946 return (-1);
03947 }
03948
03949 if (ret_val != SNMPERR_SUCCESS) {
03950 DEBUGDUMPSECTION("recv", "ScopedPDU");
03951
03952
03953
03954 if (cp) {
03955 cp = snmpv3_scopedPDU_parse(pdu, cp, &pdu_buf_len);
03956 }
03957 if (cp) {
03958 DEBUGPRINTPDUTYPE("recv", *cp);
03959 snmp_pdu_parse(pdu, cp, &pdu_buf_len);
03960 DEBUGINDENTADD(-8);
03961 } else {
03962 DEBUGINDENTADD(-4);
03963 }
03964
03965 if (mallocbuf) {
03966 SNMP_FREE(mallocbuf);
03967 }
03968 return ret_val;
03969 }
03970
03971
03972
03973
03974 *length = pdu_buf_len;
03975 DEBUGDUMPSECTION("recv", "ScopedPDU");
03976 data = snmpv3_scopedPDU_parse(pdu, cp, length);
03977 if (data == NULL) {
03978 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
03979 DEBUGINDENTADD(-4);
03980 if (mallocbuf) {
03981 SNMP_FREE(mallocbuf);
03982 }
03983 return SNMPERR_ASN_PARSE_ERR;
03984 }
03985
03986
03987
03988
03989 if (after_header != NULL) {
03990 *after_header = data;
03991 tmp_buf_len = *length;
03992 }
03993
03994 DEBUGPRINTPDUTYPE("recv", *data);
03995 ret = snmp_pdu_parse(pdu, data, length);
03996 DEBUGINDENTADD(-8);
03997
03998 if (after_header != NULL) {
03999 *length = tmp_buf_len;
04000 }
04001
04002 if (ret != SNMPERR_SUCCESS) {
04003 ERROR_MSG("error parsing PDU");
04004 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
04005 if (mallocbuf) {
04006 SNMP_FREE(mallocbuf);
04007 }
04008 return SNMPERR_ASN_PARSE_ERR;
04009 }
04010
04011 if (mallocbuf) {
04012 SNMP_FREE(mallocbuf);
04013 }
04014 return SNMPERR_SUCCESS;
04015 }
04016
04017 #define ERROR_STAT_LENGTH 11
04018
04019 int
04020 snmpv3_make_report(netsnmp_pdu *pdu, int error)
04021 {
04022
04023 long ltmp;
04024 static oid unknownSecurityLevel[] =
04025 { 1, 3, 6, 1, 6, 3, 15, 1, 1, 1, 0 };
04026 static oid notInTimeWindow[] =
04027 { 1, 3, 6, 1, 6, 3, 15, 1, 1, 2, 0 };
04028 static oid unknownUserName[] =
04029 { 1, 3, 6, 1, 6, 3, 15, 1, 1, 3, 0 };
04030 static oid unknownEngineID[] =
04031 { 1, 3, 6, 1, 6, 3, 15, 1, 1, 4, 0 };
04032 static oid wrongDigest[] = { 1, 3, 6, 1, 6, 3, 15, 1, 1, 5, 0 };
04033 static oid decryptionError[] =
04034 { 1, 3, 6, 1, 6, 3, 15, 1, 1, 6, 0 };
04035 oid *err_var;
04036 int err_var_len;
04037 int stat_ind;
04038 struct snmp_secmod_def *sptr;
04039
04040 switch (error) {
04041 case SNMPERR_USM_UNKNOWNENGINEID:
04042 stat_ind = STAT_USMSTATSUNKNOWNENGINEIDS;
04043 err_var = unknownEngineID;
04044 err_var_len = ERROR_STAT_LENGTH;
04045 break;
04046 case SNMPERR_USM_UNKNOWNSECURITYNAME:
04047 stat_ind = STAT_USMSTATSUNKNOWNUSERNAMES;
04048 err_var = unknownUserName;
04049 err_var_len = ERROR_STAT_LENGTH;
04050 break;
04051 case SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL:
04052 stat_ind = STAT_USMSTATSUNSUPPORTEDSECLEVELS;
04053 err_var = unknownSecurityLevel;
04054 err_var_len = ERROR_STAT_LENGTH;
04055 break;
04056 case SNMPERR_USM_AUTHENTICATIONFAILURE:
04057 stat_ind = STAT_USMSTATSWRONGDIGESTS;
04058 err_var = wrongDigest;
04059 err_var_len = ERROR_STAT_LENGTH;
04060 break;
04061 case SNMPERR_USM_NOTINTIMEWINDOW:
04062 stat_ind = STAT_USMSTATSNOTINTIMEWINDOWS;
04063 err_var = notInTimeWindow;
04064 err_var_len = ERROR_STAT_LENGTH;
04065 break;
04066 case SNMPERR_USM_DECRYPTIONERROR:
04067 stat_ind = STAT_USMSTATSDECRYPTIONERRORS;
04068 err_var = decryptionError;
04069 err_var_len = ERROR_STAT_LENGTH;
04070 break;
04071 default:
04072 return SNMPERR_GENERR;
04073 }
04074
04075 snmp_free_varbind(pdu->variables);
04076
04077 pdu->variables = NULL;
04078 SNMP_FREE(pdu->securityEngineID);
04079 pdu->securityEngineID =
04080 snmpv3_generate_engineID(&pdu->securityEngineIDLen);
04081 SNMP_FREE(pdu->contextEngineID);
04082 pdu->contextEngineID =
04083 snmpv3_generate_engineID(&pdu->contextEngineIDLen);
04084 pdu->command = SNMP_MSG_REPORT;
04085 pdu->errstat = 0;
04086 pdu->errindex = 0;
04087 SNMP_FREE(pdu->contextName);
04088 pdu->contextName = strdup("");
04089 pdu->contextNameLen = strlen(pdu->contextName);
04090
04091
04092
04093
04094
04095
04096
04097
04098 if (pdu->securityStateRef) {
04099 sptr = find_sec_mod(pdu->securityModel);
04100 if (sptr) {
04101 if (sptr->pdu_free_state_ref) {
04102 (*sptr->pdu_free_state_ref) (pdu->securityStateRef);
04103 } else {
04104 snmp_log(LOG_ERR,
04105 "Security Model %d can't free state references\n",
04106 pdu->securityModel);
04107 }
04108 } else {
04109 snmp_log(LOG_ERR,
04110 "Can't find security model to free ptr: %d\n",
04111 pdu->securityModel);
04112 }
04113 pdu->securityStateRef = NULL;
04114 }
04115
04116 if (error == SNMPERR_USM_NOTINTIMEWINDOW) {
04117 pdu->securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV;
04118 } else {
04119 pdu->securityLevel = SNMP_SEC_LEVEL_NOAUTH;
04120 }
04121
04122
04123
04124
04125 ltmp = snmp_get_statistic(stat_ind);
04126
04127
04128
04129
04130 snmp_pdu_add_variable(pdu, err_var, err_var_len,
04131 ASN_COUNTER, & ltmp, sizeof(ltmp));
04132
04133 return SNMPERR_SUCCESS;
04134 }
04135
04136
04137 int
04138 snmpv3_get_report_type(netsnmp_pdu *pdu)
04139 {
04140 static oid snmpMPDStats[] = { 1, 3, 6, 1, 6, 3, 11, 2, 1 };
04141 static oid usmStats[] = { 1, 3, 6, 1, 6, 3, 15, 1, 1 };
04142 netsnmp_variable_list *vp;
04143 int rpt_type = SNMPERR_UNKNOWN_REPORT;
04144
04145 if (pdu == NULL || pdu->variables == NULL)
04146 return rpt_type;
04147 vp = pdu->variables;
04148 if (vp->name_length == REPORT_STATS_LEN + 2) {
04149 if (memcmp(snmpMPDStats, vp->name, REPORT_STATS_LEN * sizeof(oid))
04150 == 0) {
04151 switch (vp->name[REPORT_STATS_LEN]) {
04152 case REPORT_snmpUnknownSecurityModels_NUM:
04153 rpt_type = SNMPERR_UNKNOWN_SEC_MODEL;
04154 break;
04155 case REPORT_snmpInvalidMsgs_NUM:
04156 rpt_type = SNMPERR_INVALID_MSG;
04157 break;
04158 }
04159 } else
04160 if (memcmp(usmStats, vp->name, REPORT_STATS_LEN * sizeof(oid))
04161 == 0) {
04162 switch (vp->name[REPORT_STATS_LEN]) {
04163 case REPORT_usmStatsUnsupportedSecLevels_NUM:
04164 rpt_type = SNMPERR_UNSUPPORTED_SEC_LEVEL;
04165 break;
04166 case REPORT_usmStatsNotInTimeWindows_NUM:
04167 rpt_type = SNMPERR_NOT_IN_TIME_WINDOW;
04168 break;
04169 case REPORT_usmStatsUnknownUserNames_NUM:
04170 rpt_type = SNMPERR_UNKNOWN_USER_NAME;
04171 break;
04172 case REPORT_usmStatsUnknownEngineIDs_NUM:
04173 rpt_type = SNMPERR_UNKNOWN_ENG_ID;
04174 break;
04175 case REPORT_usmStatsWrongDigests_NUM:
04176 rpt_type = SNMPERR_AUTHENTICATION_FAILURE;
04177 break;
04178 case REPORT_usmStatsDecryptionErrors_NUM:
04179 rpt_type = SNMPERR_DECRYPTION_ERR;
04180 break;
04181 }
04182 }
04183 }
04184 DEBUGMSGTL(("report", "Report type: %d\n", rpt_type));
04185 return rpt_type;
04186 }
04187
04188
04189
04190
04191
04192
04193
04194 static int
04195 _snmp_parse(void *sessp,
04196 netsnmp_session * session,
04197 netsnmp_pdu *pdu, u_char * data, size_t length)
04198 {
04199 #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
04200 u_char community[COMMUNITY_MAX_LEN];
04201 size_t community_length = COMMUNITY_MAX_LEN;
04202 #endif
04203 int result = -1;
04204
04205 static oid snmpEngineIDoid[] = { 1,3,6,1,6,3,10,2,1,1,0};
04206 static size_t snmpEngineIDoid_len = 11;
04207
04208 static char ourEngineID[SNMP_SEC_PARAM_BUF_SIZE];
04209 static size_t ourEngineID_len = sizeof(ourEngineID);
04210
04211 netsnmp_pdu *pdu2 = NULL;
04212
04213 session->s_snmp_errno = 0;
04214 session->s_errno = 0;
04215
04216
04217
04218
04219
04220
04221 pdu->transid = snmp_get_next_transid();
04222
04223 if (session->version != SNMP_DEFAULT_VERSION) {
04224 pdu->version = session->version;
04225 } else {
04226 pdu->version = snmp_parse_version(data, length);
04227 }
04228
04229 switch (pdu->version) {
04230 #ifndef NETSNMP_DISABLE_SNMPV1
04231 case SNMP_VERSION_1:
04232 #endif
04233 #ifndef NETSNMP_DISABLE_SNMPV2C
04234 case SNMP_VERSION_2c:
04235 #endif
04236 #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
04237 DEBUGMSGTL(("snmp_api", "Parsing SNMPv%ld message...\n",
04238 (1 + pdu->version)));
04239
04240
04241
04242
04243 #ifndef NETSNMP_DISABLE_SNMPV1
04244 if (pdu->version == SNMP_VERSION_1) {
04245 DEBUGDUMPSECTION("recv", "SNMPv1 message\n");
04246 } else {
04247 #endif
04248 DEBUGDUMPSECTION("recv", "SNMPv2c message\n");
04249 #ifndef NETSNMP_DISABLE_SNMPV1
04250 }
04251 #endif
04252 data = snmp_comstr_parse(data, &length,
04253 community, &community_length,
04254 &pdu->version);
04255 if (data == NULL)
04256 return -1;
04257
04258 if (pdu->version != session->version &&
04259 session->version != SNMP_DEFAULT_VERSION) {
04260 session->s_snmp_errno = SNMPERR_BAD_VERSION;
04261 return -1;
04262 }
04263
04264
04265
04266
04267 pdu->securityLevel = SNMP_SEC_LEVEL_NOAUTH;
04268 pdu->securityModel =
04269 #ifndef NETSNMP_DISABLE_SNMPV1
04270 (pdu->version == SNMP_VERSION_1) ? SNMP_SEC_MODEL_SNMPv1 :
04271 #endif
04272 SNMP_SEC_MODEL_SNMPv2c;
04273 SNMP_FREE(pdu->community);
04274 pdu->community_len = 0;
04275 pdu->community = (u_char *) 0;
04276 if (community_length) {
04277 pdu->community_len = community_length;
04278 pdu->community = (u_char *) malloc(community_length);
04279 if (pdu->community == NULL) {
04280 session->s_snmp_errno = SNMPERR_MALLOC;
04281 return -1;
04282 }
04283 memmove(pdu->community, community, community_length);
04284 }
04285 if (session->authenticator) {
04286 data = session->authenticator(data, &length,
04287 community, community_length);
04288 if (data == NULL) {
04289 session->s_snmp_errno = SNMPERR_AUTHENTICATION_FAILURE;
04290 return -1;
04291 }
04292 }
04293
04294 DEBUGDUMPSECTION("recv", "PDU");
04295 result = snmp_pdu_parse(pdu, data, &length);
04296 if (result < 0) {
04297
04298
04299
04300 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
04301 }
04302 DEBUGINDENTADD(-6);
04303 break;
04304 #endif
04305
04306 case SNMP_VERSION_3:
04307 result = snmpv3_parse(pdu, data, &length, NULL, session);
04308 DEBUGMSGTL(("snmp_parse",
04309 "Parsed SNMPv3 message (secName:%s, secLevel:%s): %s\n",
04310 pdu->securityName, secLevelName[pdu->securityLevel],
04311 snmp_api_errstring(result)));
04312
04313 if (result) {
04314 struct snmp_secmod_def *secmod =
04315 find_sec_mod(pdu->securityModel);
04316 if (!sessp) {
04317 session->s_snmp_errno = result;
04318 } else {
04319
04320
04321
04322
04323 if (secmod && secmod->handle_report) {
04324 struct session_list *slp = (struct session_list *) sessp;
04325 (*secmod->handle_report)(sessp, slp->transport, session,
04326 result, pdu);
04327 }
04328 }
04329 if (pdu->securityStateRef != NULL) {
04330 if (secmod && secmod->pdu_free_state_ref) {
04331 secmod->pdu_free_state_ref(pdu->securityStateRef);
04332 pdu->securityStateRef = NULL;
04333 }
04334 }
04335 }
04336
04337
04338
04339
04340
04341
04342
04343
04344
04345
04346
04347
04348
04349
04350
04351
04352
04353
04354
04355
04356
04357
04358
04359
04360
04361
04362
04363
04364
04365
04366
04367 if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
04368 NETSNMP_DS_LIB_NO_DISCOVERY) &&
04369 SNMP_MSG_RESPONSE != pdu->command &&
04370 NULL != pdu->contextEngineID &&
04371 pdu->contextEngineIDLen == 5 &&
04372 pdu->contextEngineID[0] == 0x80 &&
04373 pdu->contextEngineID[1] == 0x00 &&
04374 pdu->contextEngineID[2] == 0x00 &&
04375 pdu->contextEngineID[3] == 0x00 &&
04376 pdu->contextEngineID[4] == 0x06) {
04377
04378
04379
04380 result = SNMPERR_JUST_A_CONTEXT_PROBE;
04381
04382 DEBUGMSGTL(("snmpv3_contextid", "starting context ID discovery\n"));
04383
04384 if (NULL != pdu->variables &&
04385 NULL == pdu->variables->next_variable &&
04386
04387
04388 ((SNMP_MSG_GET == pdu->command &&
04389 snmp_oid_compare(snmpEngineIDoid,
04390 snmpEngineIDoid_len,
04391 pdu->variables->name,
04392 pdu->variables->name_length) == 0)
04393
04394 ||
04395 (SNMP_MSG_GETNEXT == pdu->command &&
04396 snmp_oid_compare(snmpEngineIDoid,
04397 snmpEngineIDoid_len,
04398 pdu->variables->name,
04399 pdu->variables->name_length) > 0)
04400 )) {
04401
04402 DEBUGMSGTL(("snmpv3_contextid",
04403 " One correct variable found\n"));
04404
04405
04406
04407
04408 pdu2 = snmp_clone_pdu(pdu);
04409
04410
04411 snmp_free_varbind(pdu2->variables);
04412
04413
04414 pdu2->variables = NULL;
04415 pdu2->command = SNMP_MSG_RESPONSE;
04416 pdu2->errstat = 0;
04417 pdu2->errindex = 0;
04418
04419 ourEngineID_len =
04420 snmpv3_get_engineID((u_char*)ourEngineID, ourEngineID_len);
04421 if (0 != ourEngineID_len) {
04422
04423 DEBUGMSGTL(("snmpv3_contextid",
04424 " responding with our engineID\n"));
04425
04426 snmp_pdu_add_variable(pdu2,
04427 snmpEngineIDoid, snmpEngineIDoid_len,
04428 ASN_OCTET_STR,
04429 ourEngineID, ourEngineID_len);
04430
04431
04432 if (0 == snmp_sess_send(sessp, pdu2)) {
04433
04434 DEBUGMSGTL(("snmpv3_contextid",
04435 " sent it off!\n"));
04436
04437 snmp_free_pdu(pdu2);
04438
04439 snmp_log(LOG_ERR, "sending a response to the context engineID probe failed\n");
04440 }
04441 } else {
04442 snmp_log(LOG_ERR, "failed to get our own engineID!\n");
04443 }
04444 } else {
04445 snmp_log(LOG_WARNING,
04446 "received an odd context engineID probe\n");
04447 }
04448 }
04449
04450 break;
04451 case SNMPERR_BAD_VERSION:
04452 ERROR_MSG("error parsing snmp message version");
04453 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
04454 session->s_snmp_errno = SNMPERR_BAD_VERSION;
04455 break;
04456 case SNMP_VERSION_sec:
04457 case SNMP_VERSION_2u:
04458 case SNMP_VERSION_2star:
04459 case SNMP_VERSION_2p:
04460 default:
04461 ERROR_MSG("unsupported snmp message version");
04462 snmp_increment_statistic(STAT_SNMPINBADVERSIONS);
04463
04464
04465
04466
04467
04468 if (pdu->version < 0 || pdu->version > 2147483647) {
04469 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
04470 }
04471 session->s_snmp_errno = SNMPERR_BAD_VERSION;
04472 break;
04473 }
04474
04475 return result;
04476 }
04477
04478 static int
04479 snmp_parse(void *sessp,
04480 netsnmp_session * pss,
04481 netsnmp_pdu *pdu, u_char * data, size_t length)
04482 {
04483 int rc;
04484
04485 rc = _snmp_parse(sessp, pss, pdu, data, length);
04486 if (rc) {
04487 if (!pss->s_snmp_errno) {
04488 pss->s_snmp_errno = SNMPERR_BAD_PARSE;
04489 }
04490 SET_SNMP_ERROR(pss->s_snmp_errno);
04491 }
04492
04493 return rc;
04494 }
04495
04496 int
04497 snmp_pdu_parse(netsnmp_pdu *pdu, u_char * data, size_t * length)
04498 {
04499 u_char type;
04500 u_char msg_type;
04501 u_char *var_val;
04502 int badtype = 0;
04503 size_t len;
04504 size_t four;
04505 netsnmp_variable_list *vp = NULL;
04506 oid objid[MAX_OID_LEN];
04507
04508
04509
04510
04511 data = asn_parse_header(data, length, &msg_type);
04512 if (data == NULL)
04513 return -1;
04514 DEBUGMSGTL((