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 #ifdef SNMP_SECMOD_USM
00131 #include <net-snmp/library/snmpusm.h>
00132 #endif
00133 #ifdef SNMP_SECMOD_KSM
00134 #include <net-snmp/library/snmpksm.h>
00135 #endif
00136 #include <net-snmp/library/keytools.h>
00137 #include <net-snmp/library/lcd_time.h>
00138 #include <net-snmp/library/snmp_alarm.h>
00139 #include <net-snmp/library/snmp_transport.h>
00140 #include <net-snmp/library/vacm.h>
00141
00142 static void _init_snmp(void);
00143
00144 #include "../agent/mibgroup/agentx/protocol.h"
00145 #include <net-snmp/library/transform_oids.h>
00146 #ifndef timercmp
00147 #define timercmp(tvp, uvp, cmp) \
00148 \
00149 ((tvp)->tv_sec cmp (uvp)->tv_sec || \
00150 ((tvp)->tv_sec == (uvp)->tv_sec && \
00151 \
00152 (tvp)->tv_usec cmp (uvp)->tv_usec))
00153 #endif
00154 #ifndef timerclear
00155 #define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0
00156 #endif
00157
00158
00159
00160
00161 #define MAX_PACKET_LENGTH (0x7fffffff)
00162 #ifndef NETSNMP_STREAM_QUEUE_LEN
00163 #define NETSNMP_STREAM_QUEUE_LEN 5
00164 #endif
00165
00166 #ifndef BSD4_3
00167 #define BSD4_2
00168 #endif
00169
00170 #ifndef FD_SET
00171
00172 typedef long fd_mask;
00173 #define NFDBITS (sizeof(fd_mask) * NBBY)
00174
00175 #define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
00176 #define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
00177 #define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
00178 #define FD_ZERO(p) memset((p), 0, sizeof(*(p)))
00179 #endif
00180
00181 static oid default_enterprise[] = { 1, 3, 6, 1, 4, 1, 3, 1, 1 };
00182
00183
00184
00185
00186 #define DEFAULT_COMMUNITY "public"
00187 #define DEFAULT_RETRIES 5
00188 #define DEFAULT_TIMEOUT 1000000L
00189 #define DEFAULT_REMPORT SNMP_PORT
00190 #define DEFAULT_ENTERPRISE default_enterprise
00191 #define DEFAULT_TIME 0
00192
00193
00194
00195
00196
00197 #define MAXIMUM_PACKET_SIZE 0x7fffffff
00198
00199
00200
00201
00202 struct snmp_internal_session {
00203 netsnmp_request_list *requests;
00204 netsnmp_request_list *requestsEnd;
00205 int (*hook_pre) (netsnmp_session *, netsnmp_transport *,
00206 void *, int);
00207 int (*hook_parse) (netsnmp_session *, netsnmp_pdu *,
00208 u_char *, size_t);
00209 int (*hook_post) (netsnmp_session *, netsnmp_pdu *, int);
00210 int (*hook_build) (netsnmp_session *, netsnmp_pdu *,
00211 u_char *, size_t *);
00212 int (*hook_realloc_build) (netsnmp_session *,
00213 netsnmp_pdu *, u_char **,
00214 size_t *, size_t *);
00215 int (*check_packet) (u_char *, size_t);
00216 netsnmp_pdu *(*hook_create_pdu) (netsnmp_transport *,
00217 void *, size_t);
00218
00219 u_char *packet;
00220 size_t packet_len, packet_size;
00221 };
00222
00223
00224
00225
00226 struct session_list {
00227 struct session_list *next;
00228 netsnmp_session *session;
00229 netsnmp_transport *transport;
00230 struct snmp_internal_session *internal;
00231 };
00232
00233
00234
00235 static const char *api_errors[-SNMPERR_MAX + 1] = {
00236 "No error",
00237 "Generic error",
00238 "Invalid local port",
00239 "Unknown host",
00240 "Unknown session",
00241 "Too long",
00242 "No socket",
00243 "Cannot send V2 PDU on V1 session",
00244 "Cannot send V1 PDU on V2 session",
00245 "Bad value for non-repeaters",
00246 "Bad value for max-repetitions",
00247 "Error building ASN.1 representation",
00248 "Failure in sendto",
00249 "Bad parse of ASN.1 type",
00250 "Bad version specified",
00251 "Bad source party specified",
00252 "Bad destination party specified",
00253 "Bad context specified",
00254 "Bad community specified",
00255 "Cannot send noAuth/Priv",
00256 "Bad ACL definition",
00257 "Bad Party definition",
00258 "Session abort failure",
00259 "Unknown PDU type",
00260 "Timeout",
00261 "Failure in recvfrom",
00262 "Unable to determine contextEngineID",
00263 "No securityName specified",
00264 "Unable to determine securityLevel",
00265 "ASN.1 parse error in message",
00266 "Unknown security model in message",
00267 "Invalid message (e.g. msgFlags)",
00268 "Unknown engine ID",
00269 "Unknown user name",
00270 "Unsupported security level",
00271 "Authentication failure (incorrect password, community or key)",
00272 "Not in time window",
00273 "Decryption error",
00274 "SCAPI general failure",
00275 "SCAPI sub-system not configured",
00276 "Key tools not available",
00277 "Unknown Report message",
00278 "USM generic error",
00279 "USM unknown security name (no such user exists)",
00280 "USM unsupported security level (this user has not been configured for that level of security)",
00281 "USM encryption error",
00282 "USM authentication failure (incorrect password or key)",
00283 "USM parse error",
00284 "USM unknown engineID",
00285 "USM not in time window",
00286 "USM decryption error",
00287 "MIB not initialized",
00288 "Value out of range",
00289 "Sub-id out of range",
00290 "Bad sub-id in object identifier",
00291 "Object identifier too long",
00292 "Bad value name",
00293 "Bad value notation",
00294 "Unknown Object Identifier",
00295 "No PDU in snmp_send",
00296 "Missing variables in PDU",
00297 "Bad variable type",
00298 "Out of memory (malloc failure)",
00299 "Kerberos related error",
00300 "Protocol error",
00301 };
00302
00303 static const char *secLevelName[] = {
00304 "BAD_SEC_LEVEL",
00305 "noAuthNoPriv",
00306 "authNoPriv",
00307 "authPriv"
00308 };
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323 struct session_list *Sessions = NULL;
00324 static long Reqid = 0;
00325 static long Msgid = 0;
00326 static long Sessid = 0;
00327 static long Transid = 0;
00328 int snmp_errno = 0;
00329
00330
00331
00332
00333
00334
00335
00336 static char snmp_detail[192];
00337 static int snmp_detail_f = 0;
00338
00339
00340
00341
00342 int snmp_build(u_char ** pkt, size_t * pkt_len,
00343 size_t * offset, netsnmp_session * pss,
00344 netsnmp_pdu *pdu);
00345 static int snmp_parse(void *, netsnmp_session *, netsnmp_pdu *,
00346 u_char *, size_t);
00347
00348 static void snmpv3_calc_msg_flags(int, int, u_char *);
00349 static int snmpv3_verify_msg(netsnmp_request_list *, netsnmp_pdu *);
00350 static int snmpv3_build_probe_pdu(netsnmp_pdu **);
00351 static int snmpv3_build(u_char ** pkt, size_t * pkt_len,
00352 size_t * offset, netsnmp_session * session,
00353 netsnmp_pdu *pdu);
00354 static int snmp_parse_version(u_char *, size_t);
00355 static int snmp_resend_request(struct session_list *slp,
00356 netsnmp_request_list *rp,
00357 int incr_retries);
00358 static void register_default_handlers(void);
00359 static struct session_list *snmp_sess_copy(netsnmp_session * pss);
00360 int snmp_get_errno(void);
00361 void snmp_synch_reset(netsnmp_session * notused);
00362 void snmp_synch_setup(netsnmp_session * notused);
00363
00364 #ifndef HAVE_STRERROR
00365 const char *
00366 strerror(int err)
00367 {
00368 extern const char *sys_errlist[];
00369 extern int sys_nerr;
00370
00371 if (err < 0 || err >= sys_nerr)
00372 return "Unknown error";
00373 return sys_errlist[err];
00374 }
00375 #endif
00376
00377 const char *
00378 snmp_pdu_type(int type)
00379 {
00380 static char unknown[20];
00381 switch(type) {
00382 case SNMP_MSG_GET:
00383 return "GET";
00384 case SNMP_MSG_GETNEXT:
00385 return "GETNEXT";
00386 case SNMP_MSG_RESPONSE:
00387 return "RESPONSE";
00388 case SNMP_MSG_SET:
00389 return "SET";
00390 case SNMP_MSG_GETBULK:
00391 return "GETBULK";
00392 case SNMP_MSG_INFORM:
00393 return "INFORM";
00394 case SNMP_MSG_TRAP2:
00395 return "TRAP2";
00396 case SNMP_MSG_REPORT:
00397 return "REPORT";
00398 default:
00399 snprintf(unknown, sizeof(unknown), "?0x%2X?", type);
00400 return unknown;
00401 }
00402 }
00403
00404 #define DEBUGPRINTPDUTYPE(token, type) \
00405 DEBUGDUMPSECTION(token, snmp_pdu_type(type))
00406
00407 long
00408 snmp_get_next_reqid(void)
00409 {
00410 long retVal;
00411 snmp_res_lock(MT_LIBRARY_ID, MT_LIB_REQUESTID);
00412 retVal = 1 + Reqid;
00413 if (!retVal)
00414 retVal = 2;
00415 Reqid = retVal;
00416 snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_REQUESTID);
00417 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_16BIT_IDS))
00418 return (retVal & 0x7fff);
00419 else
00420 return retVal;
00421 }
00422
00423 long
00424 snmp_get_next_msgid(void)
00425 {
00426 long retVal;
00427 snmp_res_lock(MT_LIBRARY_ID, MT_LIB_MESSAGEID);
00428 retVal = 1 + Msgid;
00429 if (!retVal)
00430 retVal = 2;
00431 Msgid = retVal;
00432 snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_MESSAGEID);
00433 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_16BIT_IDS))
00434 return (retVal & 0x7fff);
00435 else
00436 return retVal;
00437 }
00438
00439 long
00440 snmp_get_next_sessid(void)
00441 {
00442 long retVal;
00443 snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSIONID);
00444 retVal = 1 + Sessid;
00445 if (!retVal)
00446 retVal = 2;
00447 Sessid = retVal;
00448 snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSIONID);
00449 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_16BIT_IDS))
00450 return (retVal & 0x7fff);
00451 else
00452 return retVal;
00453 }
00454
00455 long
00456 snmp_get_next_transid(void)
00457 {
00458 long retVal;
00459 snmp_res_lock(MT_LIBRARY_ID, MT_LIB_TRANSID);
00460 retVal = 1 + Transid;
00461 if (!retVal)
00462 retVal = 2;
00463 Transid = retVal;
00464 snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_TRANSID);
00465 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_16BIT_IDS))
00466 return (retVal & 0x7fff);
00467 else
00468 return retVal;
00469 }
00470
00471 void
00472 snmp_perror(const char *prog_string)
00473 {
00474 const char *str;
00475 int xerr;
00476 xerr = snmp_errno;
00477 str = snmp_api_errstring(xerr);
00478 snmp_log(LOG_ERR, "%s: %s\n", prog_string, str);
00479 }
00480
00481 void
00482 snmp_set_detail(const char *detail_string)
00483 {
00484 if (detail_string != NULL) {
00485 strncpy((char *) snmp_detail, detail_string, sizeof(snmp_detail));
00486 snmp_detail[sizeof(snmp_detail) - 1] = '\0';
00487 snmp_detail_f = 1;
00488 }
00489 }
00490
00491
00492
00493
00494
00495
00496
00497 const char *
00498 snmp_api_errstring(int snmp_errnumber)
00499 {
00500 const char *msg = "";
00501 static char msg_buf[SPRINT_MAX_LEN];
00502 if (snmp_errnumber >= SNMPERR_MAX && snmp_errnumber <= SNMPERR_GENERR) {
00503 msg = api_errors[-snmp_errnumber];
00504 } else if (snmp_errnumber != SNMPERR_SUCCESS) {
00505 msg = NULL;
00506 }
00507 if (!msg)
00508 snprintf(msg_buf, sizeof(msg_buf), "Unknown error: %d", snmp_errnumber);
00509 else if (snmp_detail_f) {
00510 snprintf(msg_buf, sizeof(msg_buf), "%s (%s)", msg, snmp_detail);
00511 snmp_detail_f = 0;
00512 } else {
00513 strncpy(msg_buf, msg, sizeof(msg_buf));
00514 }
00515 msg_buf[sizeof(msg_buf)-1] = '\0';
00516
00517 return (msg_buf);
00518 }
00519
00520
00521
00522
00523
00524
00525 void
00526 snmp_error(netsnmp_session * psess,
00527 int *p_errno, int *p_snmp_errno, char **p_str)
00528 {
00529 char buf[SPRINT_MAX_LEN];
00530 int snmp_errnumber;
00531
00532 if (p_errno)
00533 *p_errno = psess->s_errno;
00534 if (p_snmp_errno)
00535 *p_snmp_errno = psess->s_snmp_errno;
00536 if (p_str == NULL)
00537 return;
00538
00539 strcpy(buf, "");
00540 snmp_errnumber = psess->s_snmp_errno;
00541 if (snmp_errnumber >= SNMPERR_MAX && snmp_errnumber <= SNMPERR_GENERR) {
00542 if (snmp_detail_f) {
00543 snprintf(buf, sizeof(buf), "%s (%s)", api_errors[-snmp_errnumber],
00544 snmp_detail);
00545 snmp_detail_f = 0;
00546 }
00547 else
00548 strncpy(buf, api_errors[-snmp_errnumber], sizeof(buf));
00549 } else {
00550 if (snmp_errnumber)
00551 snprintf(buf, sizeof(buf), "Unknown Error %d", snmp_errnumber);
00552 }
00553 buf[sizeof(buf)-1] = '\0';
00554
00555
00556
00557
00558 if (psess->s_errno) {
00559 const char* error = strerror(psess->s_errno);
00560 if(error == NULL)
00561 error = "Unknown Error";
00562 snprintf (&buf[strlen(buf)], sizeof(buf)-strlen(buf),
00563 " (%s)", error);
00564 }
00565 buf[sizeof(buf)-1] = '\0';
00566 *p_str = strdup(buf);
00567 }
00568
00569
00570
00571
00572 void
00573 snmp_sess_error(void *sessp, int *p_errno, int *p_snmp_errno, char **p_str)
00574 {
00575 struct session_list *slp = (struct session_list *) sessp;
00576
00577 if ((slp) && (slp->session))
00578 snmp_error(slp->session, p_errno, p_snmp_errno, p_str);
00579 }
00580
00581
00582
00583
00584 void
00585 netsnmp_sess_log_error(int priority,
00586 const char *prog_string, netsnmp_session * ss)
00587 {
00588 char *err;
00589 snmp_error(ss, NULL, NULL, &err);
00590 snmp_log(priority, "%s: %s\n", prog_string, err);
00591 SNMP_FREE(err);
00592 }
00593
00594
00595
00596
00597 void
00598 snmp_sess_perror(const char *prog_string, netsnmp_session * ss)
00599 {
00600 netsnmp_sess_log_error(LOG_ERR, prog_string, ss);
00601 }
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615 static void
00616 _init_snmp(void)
00617 {
00618 #ifdef HAVE_GETSERVBYNAME
00619 struct servent *servp;
00620 #endif
00621 static char have_done_init = 0;
00622
00623 struct timeval tv;
00624 long tmpReqid, tmpMsgid;
00625 u_short s_port = SNMP_PORT;
00626
00627 if (have_done_init)
00628 return;
00629 have_done_init = 1;
00630 Reqid = 1;
00631
00632 snmp_res_init();
00633 #ifndef DISABLE_MIB_LOADING
00634 init_mib_internals();
00635 #endif
00636 netsnmp_tdomain_init();
00637
00638 gettimeofday(&tv, (struct timezone *) 0);
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649 #ifdef SVR4
00650 srand48(tv.tv_sec ^ tv.tv_usec);
00651 tmpReqid = lrand48();
00652 tmpMsgid = lrand48();
00653 #else
00654 srandom(tv.tv_sec ^ tv.tv_usec);
00655 tmpReqid = random();
00656 tmpMsgid = random();
00657 #endif
00658
00659 if (tmpReqid == 0)
00660 tmpReqid = 1;
00661 if (tmpMsgid == 0)
00662 tmpMsgid = 1;
00663 Reqid = tmpReqid;
00664 Msgid = tmpMsgid;
00665
00666 #ifdef HAVE_GETSERVBYNAME
00667 servp = getservbyname("snmp", "udp");
00668 if (servp) {
00669
00670
00671
00672 s_port = ntohs(servp->s_port);
00673 }
00674 #endif
00675
00676 netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
00677 NETSNMP_DS_LIB_DEFAULT_PORT, s_port);
00678 netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
00679 NETSNMP_DS_LIB_HEX_OUTPUT_LENGTH, 16);
00680
00681 #ifdef USE_REVERSE_ASNENCODING
00682 netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
00683 NETSNMP_DS_LIB_REVERSE_ENCODE,
00684 DEFAULT_ASNENCODING_DIRECTION);
00685 #endif
00686 }
00687
00688
00689
00690
00691
00692
00693 void
00694 snmp_sess_init(netsnmp_session * session)
00695 {
00696 _init_snmp();
00697
00698
00699
00700
00701
00702 memset(session, 0, sizeof(netsnmp_session));
00703 session->remote_port = SNMP_DEFAULT_REMPORT;
00704 session->timeout = SNMP_DEFAULT_TIMEOUT;
00705 session->retries = SNMP_DEFAULT_RETRIES;
00706 session->version = SNMP_DEFAULT_VERSION;
00707 session->securityModel = SNMP_DEFAULT_SECMODEL;
00708 session->rcvMsgMaxSize = SNMP_MAX_MSG_SIZE;
00709 session->flags |= SNMP_FLAGS_DONT_PROBE;
00710 }
00711
00712
00713 static void
00714 register_default_handlers(void)
00715 {
00716 netsnmp_ds_register_config(ASN_BOOLEAN, "snmp", "dumpPacket",
00717 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DUMP_PACKET);
00718 netsnmp_ds_register_config(ASN_BOOLEAN, "snmp", "reverseEncodeBER",
00719 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_REVERSE_ENCODE);
00720 netsnmp_ds_register_config(ASN_INTEGER, "snmp", "defaultPort",
00721 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DEFAULT_PORT);
00722 #if !defined(DISABLE_SNMPV1) || !defined(DISABLE_SNMPV2C)
00723 netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "defCommunity",
00724 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_COMMUNITY);
00725 #endif
00726 netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "noTokenWarnings",
00727 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NO_TOKEN_WARNINGS);
00728 netsnmp_ds_register_config(ASN_BOOLEAN, "snmp", "noRangeCheck",
00729 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_CHECK_RANGE);
00730 netsnmp_ds_register_premib(ASN_OCTET_STR, "snmp", "persistentDir",
00731 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PERSISTENT_DIR);
00732 netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "tempFilePattern",
00733 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_TEMP_FILE_PATTERN);
00734 netsnmp_ds_register_config(ASN_BOOLEAN, "snmp", "noDisplayHint",
00735 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NO_DISPLAY_HINT);
00736 netsnmp_ds_register_config(ASN_BOOLEAN, "snmp", "16bitIDs",
00737 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_16BIT_IDS);
00738 netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "clientaddr",
00739 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_CLIENT_ADDR);
00740 netsnmp_ds_register_config(ASN_INTEGER, "snmp", "serverSendBuf",
00741 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_SERVERSENDBUF);
00742 netsnmp_ds_register_config(ASN_INTEGER, "snmp", "serverRecvBuf",
00743 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_SERVERRECVBUF);
00744 netsnmp_ds_register_config(ASN_INTEGER, "snmp", "clientSendBuf",
00745 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_CLIENTSENDBUF);
00746 netsnmp_ds_register_config(ASN_INTEGER, "snmp", "clientRecvBuf",
00747 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_CLIENTRECVBUF);
00748 netsnmp_ds_register_config(ASN_BOOLEAN, "snmp", "noPersistentLoad",
00749 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DISABLE_PERSISTENT_LOAD);
00750 netsnmp_ds_register_config(ASN_BOOLEAN, "snmp", "noPersistentSave",
00751 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DISABLE_PERSISTENT_SAVE);
00752 }
00753
00754 void
00755 init_snmp_enums(void)
00756 {
00757 se_add_pair_to_slist("asntypes", strdup("integer"), ASN_INTEGER);
00758 se_add_pair_to_slist("asntypes", strdup("counter"), ASN_COUNTER);
00759 se_add_pair_to_slist("asntypes", strdup("uinteger"), ASN_GAUGE);
00760 se_add_pair_to_slist("asntypes", strdup("timeticks"), ASN_TIMETICKS);
00761 se_add_pair_to_slist("asntypes", strdup("counter64"), ASN_COUNTER64);
00762 se_add_pair_to_slist("asntypes", strdup("octet_str"), ASN_OCTET_STR);
00763 se_add_pair_to_slist("asntypes", strdup("ipaddress"), ASN_IPADDRESS);
00764 se_add_pair_to_slist("asntypes", strdup("opaque"), ASN_OPAQUE);
00765 se_add_pair_to_slist("asntypes", strdup("nsap"), ASN_NSAP);
00766 se_add_pair_to_slist("asntypes", strdup("object_id"), ASN_OBJECT_ID);
00767 se_add_pair_to_slist("asntypes", strdup("null"), ASN_NULL);
00768 #ifdef OPAQUE_SPECIAL_TYPES
00769 se_add_pair_to_slist("asntypes", strdup("opaque_counter64"),
00770 ASN_OPAQUE_COUNTER64);
00771 se_add_pair_to_slist("asntypes", strdup("opaque_u64"), ASN_OPAQUE_U64);
00772 se_add_pair_to_slist("asntypes", strdup("opaque_float"),
00773 ASN_OPAQUE_FLOAT);
00774 se_add_pair_to_slist("asntypes", strdup("opaque_double"),
00775 ASN_OPAQUE_DOUBLE);
00776 se_add_pair_to_slist("asntypes", strdup("opaque_i64"), ASN_OPAQUE_I64);
00777 #endif
00778 }
00779
00780
00781
00792 void
00793 init_snmp(const char *type)
00794 {
00795 static int done_init = 0;
00796
00797 if (done_init) {
00798 return;
00799 }
00800
00801 done_init = 1;
00802
00803
00804
00805
00806 if (type && !netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
00807 NETSNMP_DS_LIB_APPTYPE)) {
00808 netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID,
00809 NETSNMP_DS_LIB_APPTYPE, type);
00810 }
00811
00812 _init_snmp();
00813
00814
00815
00816
00817 #ifdef HAVE_SETLOCALE
00818 setlocale(LC_CTYPE, "");
00819 #endif
00820
00821 snmp_debug_init();
00822 netsnmp_container_init_list();
00823 init_callbacks();
00824 init_snmp_logging();
00825 snmp_init_statistics();
00826 register_mib_handlers();
00827 register_default_handlers();
00828 init_snmpv3(type);
00829 init_snmp_alarm();
00830 init_snmp_enum(type);
00831 init_snmp_enums();
00832 init_vacm();
00833
00834 read_premib_configs();
00835 #ifndef DISABLE_MIB_LOADING
00836 init_mib();
00837 #endif
00838
00839 read_configs();
00840
00841 }
00842
00843 void
00844 snmp_store(const char *type)
00845 {
00846 DEBUGMSGTL(("snmp_store", "storing stuff...\n"));
00847 snmp_save_persistent(type);
00848 snmp_call_callbacks(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA, NULL);
00849 snmp_clean_persistent(type);
00850 }
00851
00852
00861 void
00862 snmp_shutdown(const char *type)
00863 {
00864 snmp_store(type);
00865 snmp_call_callbacks(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_SHUTDOWN, NULL);
00866 snmp_alarm_unregister_all();
00867 snmp_close_sessions();
00868 #ifndef DISABLE_MIB_LOADING
00869 shutdown_mib();
00870 #endif
00871 unregister_all_config_handlers();
00872 netsnmp_container_free_list();
00873 clear_sec_mod();
00874 clear_snmp_enum();
00875 netsnmp_clear_tdomain_list();
00876 clear_callback();
00877 netsnmp_ds_shutdown();
00878 }
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888 netsnmp_session *
00889 snmp_open(netsnmp_session *session)
00890 {
00891 struct session_list *slp;
00892 slp = (struct session_list *) snmp_sess_open(session);
00893 if (!slp) {
00894 return NULL;
00895 }
00896
00897 snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION);
00898 slp->next = Sessions;
00899 Sessions = slp;
00900 snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION);
00901
00902 return (slp->session);
00903 }
00904
00905
00906
00907
00908 netsnmp_session *
00909 snmp_open_ex(netsnmp_session *session,
00910 int (*fpre_parse) (netsnmp_session *, netsnmp_transport *,
00911 void *, int),
00912 int (*fparse) (netsnmp_session *, netsnmp_pdu *, u_char *,
00913 size_t),
00914 int (*fpost_parse) (netsnmp_session *, netsnmp_pdu *, int),
00915
00916 int (*fbuild) (netsnmp_session *, netsnmp_pdu *, u_char *,
00917 size_t *),
00918 int (*frbuild) (netsnmp_session *, netsnmp_pdu *,
00919 u_char **, size_t *, size_t *),
00920 int (*fcheck) (u_char *, size_t)
00921 )
00922 {
00923 struct session_list *slp;
00924 slp = (struct session_list *) snmp_sess_open(session);
00925 if (!slp) {
00926 return NULL;
00927 }
00928 slp->internal->hook_pre = fpre_parse;
00929 slp->internal->hook_parse = fparse;
00930 slp->internal->hook_post = fpost_parse;
00931 slp->internal->hook_build = fbuild;
00932 slp->internal->hook_realloc_build = frbuild;
00933 slp->internal->check_packet = fcheck;
00934
00935 snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION);
00936 slp->next = Sessions;
00937 Sessions = slp;
00938 snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION);
00939
00940 return (slp->session);
00941 }
00942
00943 static struct session_list *
00944 _sess_copy(netsnmp_session * in_session)
00945 {
00946 struct session_list *slp;
00947 struct snmp_internal_session *isp;
00948 netsnmp_session *session;
00949 struct snmp_secmod_def *sptr;
00950 char *cp;
00951 u_char *ucp;
00952 size_t i;
00953
00954 in_session->s_snmp_errno = 0;
00955 in_session->s_errno = 0;
00956
00957
00958
00959
00960 slp = (struct session_list *) calloc(1, sizeof(struct session_list));
00961 if (slp == NULL) {
00962 in_session->s_snmp_errno = SNMPERR_MALLOC;
00963 return (NULL);
00964 }
00965
00966 slp->transport = NULL;
00967
00968 isp = (struct snmp_internal_session *)calloc(1, sizeof(struct snmp_internal_session));
00969
00970 if (isp == NULL) {
00971 snmp_sess_close(slp);
00972 in_session->s_snmp_errno = SNMPERR_MALLOC;
00973 return (NULL);
00974 }
00975
00976 slp->internal = isp;
00977 slp->session = (netsnmp_session *)malloc(sizeof(netsnmp_session));
00978 if (slp->session == NULL) {
00979 snmp_sess_close(slp);
00980 in_session->s_snmp_errno = SNMPERR_MALLOC;
00981 return (NULL);
00982 }
00983 memmove(slp->session, in_session, sizeof(netsnmp_session));
00984 session = slp->session;
00985
00986
00987
00988
00989
00990 session->peername = NULL;
00991 session->community = NULL;
00992 session->contextEngineID = NULL;
00993 session->contextName = NULL;
00994 session->securityEngineID = NULL;
00995 session->securityName = NULL;
00996 session->securityAuthProto = NULL;
00997 session->securityPrivProto = NULL;
00998
00999
01000
01001
01002
01003
01004 if (in_session->peername != NULL) {
01005 session->peername = (char *)malloc(strlen(in_session->peername) + 1);
01006 if (session->peername == NULL) {
01007 snmp_sess_close(slp);
01008 in_session->s_snmp_errno = SNMPERR_MALLOC;
01009 return (NULL);
01010 }
01011 strcpy(session->peername, in_session->peername);
01012 }
01013
01014
01015
01016
01017 #if !defined(DISABLE_SNMPV1) || !defined(DISABLE_SNMPV2C)
01018 if (in_session->community_len != SNMP_DEFAULT_COMMUNITY_LEN) {
01019 ucp = (u_char *) malloc(in_session->community_len);
01020 if (ucp != NULL)
01021 memmove(ucp, in_session->community, in_session->community_len);
01022 } else {
01023 if ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01024 NETSNMP_DS_LIB_COMMUNITY)) != NULL) {
01025 session->community_len = strlen(cp);
01026 ucp = (u_char *) malloc(session->community_len);
01027 if (ucp)
01028 memmove(ucp, cp, session->community_len);
01029 } else {
01030 #ifdef NO_ZEROLENGTH_COMMUNITY
01031 session->community_len = strlen(DEFAULT_COMMUNITY);
01032 ucp = (u_char *) malloc(session->community_len);
01033 if (ucp)
01034 memmove(ucp, DEFAULT_COMMUNITY, session->community_len);
01035 #else
01036 ucp = (u_char *) strdup("");
01037 #endif
01038 }
01039 }
01040
01041 if (ucp == NULL) {
01042 snmp_sess_close(slp);
01043 in_session->s_snmp_errno = SNMPERR_MALLOC;
01044 return (NULL);
01045 }
01046 session->community = ucp;
01047 #endif
01048
01049 if (session->securityLevel <= 0) {
01050 session->securityLevel =
01051 netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_SECLEVEL);
01052 }
01053
01054 if (session->securityLevel == 0)
01055 session->securityLevel = SNMP_SEC_LEVEL_NOAUTH;
01056
01057 if (in_session->securityAuthProtoLen > 0) {
01058 session->securityAuthProto =
01059 snmp_duplicate_objid(in_session->securityAuthProto,
01060 in_session->securityAuthProtoLen);
01061 if (session->securityAuthProto == NULL) {
01062 snmp_sess_close(slp);
01063 in_session->s_snmp_errno = SNMPERR_MALLOC;
01064 return (NULL);
01065 }
01066 } else if (get_default_authtype(&i) != NULL) {
01067 session->securityAuthProto =
01068 snmp_duplicate_objid(get_default_authtype(NULL), i);
01069 session->securityAuthProtoLen = i;
01070 }
01071
01072 if (in_session->securityPrivProtoLen > 0) {
01073 session->securityPrivProto =
01074 snmp_duplicate_objid(in_session->securityPrivProto,
01075 in_session->securityPrivProtoLen);
01076 if (session->securityPrivProto == NULL) {
01077 snmp_sess_close(slp);
01078 in_session->s_snmp_errno = SNMPERR_MALLOC;
01079 return (NULL);
01080 }
01081 } else if (get_default_privtype(&i) != NULL) {
01082 session->securityPrivProto =
01083 snmp_duplicate_objid(get_default_privtype(NULL), i);
01084 session->securityPrivProtoLen = i;
01085 }
01086
01087 if (in_session->securityEngineIDLen > 0) {
01088 ucp = (u_char *) malloc(in_session->securityEngineIDLen);
01089 if (ucp == NULL) {
01090 snmp_sess_close(slp);
01091 in_session->s_snmp_errno = SNMPERR_MALLOC;
01092 return (NULL);
01093 }
01094 memmove(ucp, in_session->securityEngineID,
01095 in_session->securityEngineIDLen);
01096 session->securityEngineID = ucp;
01097
01098 }
01099
01100 if (in_session->contextEngineIDLen > 0) {
01101 ucp = (u_char *) malloc(in_session->contextEngineIDLen);
01102 if (ucp == NULL) {
01103 snmp_sess_close(slp);
01104 in_session->s_snmp_errno = SNMPERR_MALLOC;
01105 return (NULL);
01106 }
01107 memmove(ucp, in_session->contextEngineID,
01108 in_session->contextEngineIDLen);
01109 session->contextEngineID = ucp;
01110 } else if (in_session->securityEngineIDLen > 0) {
01111
01112
01113
01114 ucp = (u_char *) malloc(in_session->securityEngineIDLen);
01115 if (ucp == NULL) {
01116 snmp_sess_close(slp);
01117 in_session->s_snmp_errno = SNMPERR_MALLOC;
01118 return (NULL);
01119 }
01120 memmove(ucp, in_session->securityEngineID,
01121 in_session->securityEngineIDLen);
01122 session->contextEngineID = ucp;
01123 session->contextEngineIDLen = in_session->securityEngineIDLen;
01124 }
01125
01126 if (in_session->contextName) {
01127 session->contextName = strdup(in_session->contextName);
01128 if (session->contextName == NULL) {
01129 snmp_sess_close(slp);
01130 return (NULL);
01131 }
01132 } else if ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01133 NETSNMP_DS_LIB_CONTEXT)) != NULL) {
01134 cp = strdup(cp);
01135 if (cp == NULL) {
01136 snmp_sess_close(slp);
01137 return (NULL);
01138 }
01139 session->contextName = cp;
01140 session->contextNameLen = strlen(cp);
01141 } else {
01142 cp = strdup(SNMP_DEFAULT_CONTEXT);
01143 session->contextName = cp;
01144 session->contextNameLen = strlen(cp);
01145 }
01146
01147 if (in_session->securityName) {
01148 session->securityName = strdup(in_session->securityName);
01149 if (session->securityName == NULL) {
01150 snmp_sess_close(slp);
01151 return (NULL);
01152 }
01153 } else if ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01154 NETSNMP_DS_LIB_SECNAME)) != NULL) {
01155 cp = strdup(cp);
01156 if (cp == NULL) {
01157 snmp_sess_close(slp);
01158 return (NULL);
01159 }
01160 session->securityName = cp;
01161 session->securityNameLen = strlen(cp);
01162 }
01163
01164 if ((in_session->securityAuthKeyLen <= 0) &&
01165 ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01166 NETSNMP_DS_LIB_AUTHMASTERKEY)))) {
01167 size_t buflen = sizeof(session->securityAuthKey);
01168 u_char *tmpp = session->securityAuthKey;
01169 session->securityAuthKeyLen = 0;
01170
01171 if (!snmp_hex_to_binary(&tmpp, &buflen,
01172 &session->securityAuthKeyLen, 0, cp)) {
01173 snmp_set_detail("error parsing authentication master key");
01174 snmp_sess_close(slp);
01175 return NULL;
01176 }
01177 } else if ((in_session->securityAuthKeyLen <= 0) &&
01178 ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01179 NETSNMP_DS_LIB_AUTHPASSPHRASE)) ||
01180 (cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01181 NETSNMP_DS_LIB_PASSPHRASE)))) {
01182 session->securityAuthKeyLen = USM_AUTH_KU_LEN;
01183 if (generate_Ku(session->securityAuthProto,
01184 session->securityAuthProtoLen,
01185 (u_char *) cp, strlen(cp),
01186 session->securityAuthKey,
01187 &session->securityAuthKeyLen) != SNMPERR_SUCCESS) {
01188 snmp_set_detail
01189 ("Error generating a key (Ku) from the supplied authentication pass phrase.");
01190 snmp_sess_close(slp);
01191 return NULL;
01192 }
01193 }
01194
01195
01196 if ((in_session->securityPrivKeyLen <= 0) &&
01197 ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01198 NETSNMP_DS_LIB_PRIVMASTERKEY)))) {
01199 size_t buflen = sizeof(session->securityPrivKey);
01200 u_char *tmpp = session->securityPrivKey;
01201 session->securityPrivKeyLen = 0;
01202
01203 if (!snmp_hex_to_binary(&tmpp, &buflen,
01204 &session->securityPrivKeyLen, 0, cp)) {
01205 snmp_set_detail("error parsing encryption master key");
01206 snmp_sess_close(slp);
01207 return NULL;
01208 }
01209 } else if ((in_session->securityPrivKeyLen <= 0) &&
01210 ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01211 NETSNMP_DS_LIB_PRIVPASSPHRASE)) ||
01212 (cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01213 NETSNMP_DS_LIB_PASSPHRASE)))) {
01214 session->securityPrivKeyLen = USM_PRIV_KU_LEN;
01215 if (generate_Ku(session->securityAuthProto,
01216 session->securityAuthProtoLen,
01217 (u_char *) cp, strlen(cp),
01218 session->securityPrivKey,
01219 &session->securityPrivKeyLen) != SNMPERR_SUCCESS) {
01220 snmp_set_detail
01221 ("Error generating a key (Ku) from the supplied privacy pass phrase.");
01222 snmp_sess_close(slp);
01223 return NULL;
01224 }
01225 }
01226
01227 if (session->retries == SNMP_DEFAULT_RETRIES)
01228 session->retries = DEFAULT_RETRIES;
01229 if (session->timeout == SNMP_DEFAULT_TIMEOUT)
01230 session->timeout = DEFAULT_TIMEOUT;
01231 session->sessid = snmp_get_next_sessid();
01232
01233 snmp_call_callbacks(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_SESSION_INIT,
01234 session);
01235
01236 if ((sptr = find_sec_mod(session->securityModel)) != NULL &&
01237 sptr->session_open != NULL) {
01238
01239
01240
01241 (*sptr->session_open) (session);
01242 }
01243
01244 return (slp);
01245 }
01246
01247 static struct session_list *
01248 snmp_sess_copy(netsnmp_session * pss)
01249 {
01250 struct session_list *psl;
01251 psl = _sess_copy(pss);
01252 if (!psl) {
01253 if (!pss->s_snmp_errno) {
01254 pss->s_snmp_errno = SNMPERR_GENERR;
01255 }
01256 SET_SNMP_ERROR(pss->s_snmp_errno);
01257 }
01258 return psl;
01259 }
01260
01261
01277 int
01278 snmpv3_engineID_probe(struct session_list *slp,
01279 netsnmp_session * in_session)
01280 {
01281 netsnmp_pdu *pdu = NULL, *response = NULL;
01282 netsnmp_session *session;
01283 unsigned int i;
01284 int status;
01285
01286 if (slp == NULL || slp->session == NULL) {
01287 return 0;
01288 }
01289
01290 session = slp->session;
01291
01292
01293
01294
01295
01296
01297
01298 if ((session->flags & SNMP_FLAGS_DONT_PROBE) == SNMP_FLAGS_DONT_PROBE)
01299 return 1;
01300
01301 if (session->version == SNMP_VERSION_3) {
01302 if (session->securityEngineIDLen == 0) {
01303 if (snmpv3_build_probe_pdu(&pdu) != 0) {
01304 DEBUGMSGTL(("snmp_api", "unable to create probe PDU\n"));
01305 return 0;
01306 }
01307 DEBUGMSGTL(("snmp_api", "probing for engineID...\n"));
01308 session->flags |= SNMP_FLAGS_DONT_PROBE;
01309 status = snmp_sess_synch_response(slp, pdu, &response);
01310
01311 if ((response == NULL) && (status == STAT_SUCCESS)) {
01312 status = STAT_ERROR;
01313 }
01314
01315 switch (status) {
01316 case STAT_SUCCESS:
01317 in_session->s_snmp_errno = SNMPERR_INVALID_MSG;
01318 DEBUGMSGTL(("snmp_sess_open",
01319 "error: expected Report as response to probe: %s (%d)\n",
01320 snmp_errstring(response->errstat),
01321 response->errstat));
01322 break;
01323 case STAT_ERROR:
01324 in_session->s_snmp_errno = SNMPERR_UNKNOWN_ENG_ID;
01325 break;
01326 case STAT_TIMEOUT:
01327 in_session->s_snmp_errno = SNMPERR_TIMEOUT;
01328 default:
01329 DEBUGMSGTL(("snmp_sess_open",
01330 "unable to connect with remote engine: %s (%d)\n",
01331 snmp_api_errstring(session->s_snmp_errno),
01332 session->s_snmp_errno));
01333 break;
01334 }
01335
01336 if (slp->session->securityEngineIDLen == 0) {
01337 DEBUGMSGTL(("snmp_api",
01338 "unable to determine remote engine ID\n"));
01339 return 0;
01340 }
01341
01342 in_session->s_snmp_errno = SNMPERR_SUCCESS;
01343 if (snmp_get_do_debugging()) {
01344 DEBUGMSGTL(("snmp_sess_open",
01345 " probe found engineID: "));
01346 for (i = 0; i < slp->session->securityEngineIDLen; i++)
01347 DEBUGMSG(("snmp_sess_open", "%02x",
01348 slp->session->securityEngineID[i]));
01349 DEBUGMSG(("snmp_sess_open", "\n"));
01350 }
01351 }
01352
01353
01354
01355
01356 if (session->engineBoots || session->engineTime) {
01357 set_enginetime(session->securityEngineID,
01358 session->securityEngineIDLen,
01359 session->engineBoots, session->engineTime,
01360 TRUE);
01361 }
01362
01363 if (create_user_from_session(slp->session) != SNMPERR_SUCCESS) {
01364 in_session->s_snmp_errno = SNMPERR_UNKNOWN_USER_NAME;
01365 DEBUGMSGTL(("snmp_api",
01366 "snmp_sess_open(): failed(2) to create a new user from session\n"));
01367 return 0;
01368 }
01369 }
01370
01371 return 1;
01372 }
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388 static void *
01389 _sess_open(netsnmp_session * in_session)
01390 {
01391 struct session_list *slp;
01392 netsnmp_session *session;
01393 char *clientaddr_save = NULL;
01394
01395 in_session->s_snmp_errno = 0;
01396 in_session->s_errno = 0;
01397
01398 _init_snmp();
01399
01400 if ((slp = snmp_sess_copy(in_session)) == NULL) {
01401 return (NULL);
01402 }
01403 session = slp->session;
01404 slp->transport = NULL;
01405
01406 if (NULL != session->localname) {
01407 clientaddr_save = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01408 NETSNMP_DS_LIB_CLIENT_ADDR);
01409 netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID,
01410 NETSNMP_DS_LIB_CLIENT_ADDR, session->localname);
01411 }
01412
01413 if (session->flags & SNMP_FLAGS_STREAM_SOCKET) {
01414 slp->transport = netsnmp_tdomain_transport(session->peername,
01415 session->local_port,
01416 "tcp");
01417 } else {
01418 slp->transport = netsnmp_tdomain_transport(session->peername,
01419 session->local_port,
01420 "udp");
01421 }
01422
01423 if (NULL != session->localname)
01424 netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID,
01425 NETSNMP_DS_LIB_CLIENT_ADDR, clientaddr_save);
01426
01427 if (slp->transport == NULL) {
01428 DEBUGMSGTL(("_sess_open", "couldn't interpret peername\n"));
01429 in_session->s_snmp_errno = SNMPERR_BAD_ADDRESS;
01430 in_session->s_errno = errno;
01431 snmp_set_detail(session->peername);
01432 snmp_sess_close(slp);
01433 return NULL;
01434 }
01435
01436 session->rcvMsgMaxSize = slp->transport->msgMaxSize;
01437
01438 if (!snmpv3_engineID_probe(slp, in_session)) {
01439 snmp_sess_close(slp);
01440 return 0;
01441 }
01442 if (create_user_from_session(slp->session) != SNMPERR_SUCCESS) {
01443 in_session->s_snmp_errno = SNMPERR_UNKNOWN_USER_NAME;
01444 DEBUGMSGTL(("snmp_api",
01445 "_sess_open(): failed(2) to create a new user from session\n"));
01446 return 0;
01447 }
01448
01449 session->flags &= ~SNMP_FLAGS_DONT_PROBE;
01450
01451
01452 return (void *) slp;
01453 }
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469 netsnmp_session *
01470 snmp_add(netsnmp_session * in_session,
01471 netsnmp_transport *transport,
01472 int (*fpre_parse) (netsnmp_session *, netsnmp_transport *, void *,
01473 int), int (*fpost_parse) (netsnmp_session *,
01474 netsnmp_pdu *, int))
01475 {
01476 struct session_list *slp;
01477 slp = (struct session_list *) snmp_sess_add_ex(in_session, transport,
01478 fpre_parse, NULL,
01479 fpost_parse, NULL, NULL,
01480 NULL, NULL);
01481 if (slp == NULL) {
01482 return NULL;
01483 }
01484
01485 snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION);
01486 slp->next = Sessions;
01487 Sessions = slp;
01488 snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION);
01489
01490 return (slp->session);
01491 }
01492
01493 netsnmp_session *
01494 snmp_add_full(netsnmp_session * in_session,
01495 netsnmp_transport *transport,
01496 int (*fpre_parse) (netsnmp_session *, netsnmp_transport *,
01497 void *, int),
01498 int (*fparse) (netsnmp_session *, netsnmp_pdu *, u_char *,
01499 size_t),
01500 int (*fpost_parse) (netsnmp_session *, netsnmp_pdu *, int),
01501 int (*fbuild) (netsnmp_session *, netsnmp_pdu *, u_char *,
01502 size_t *), int (*frbuild) (netsnmp_session *,
01503 netsnmp_pdu *,
01504 u_char **,
01505 size_t *,
01506 size_t *),
01507 int (*fcheck) (u_char *, size_t),
01508 netsnmp_pdu *(*fcreate_pdu) (netsnmp_transport *, void *,
01509 size_t))
01510 {
01511 struct session_list *slp;
01512 slp = (struct session_list *) snmp_sess_add_ex(in_session, transport,
01513 fpre_parse, fparse,
01514 fpost_parse, fbuild,
01515 frbuild, fcheck,
01516 fcreate_pdu);
01517 if (slp == NULL) {
01518 return NULL;
01519 }
01520
01521 snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION);
01522 slp->next = Sessions;
01523 Sessions = slp;
01524 snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION);
01525
01526 return (slp->session);
01527 }
01528
01529
01530
01531 void *
01532 snmp_sess_add_ex(netsnmp_session * in_session,
01533 netsnmp_transport *transport,
01534 int (*fpre_parse) (netsnmp_session *, netsnmp_transport *,
01535 void *, int),
01536 int (*fparse) (netsnmp_session *, netsnmp_pdu *, u_char *,
01537 size_t),
01538 int (*fpost_parse) (netsnmp_session *, netsnmp_pdu *,
01539 int),
01540 int (*fbuild) (netsnmp_session *, netsnmp_pdu *, u_char *,
01541 size_t *),
01542 int (*frbuild) (netsnmp_session *, netsnmp_pdu *,
01543 u_char **, size_t *, size_t *),
01544 int (*fcheck) (u_char *, size_t),
01545 netsnmp_pdu *(*fcreate_pdu) (netsnmp_transport *, void *,
01546 size_t))
01547 {
01548 struct session_list *slp;
01549
01550 _init_snmp();
01551
01552 if (in_session == NULL || transport == NULL) {
01553 return NULL;
01554 }
01555
01556 DEBUGMSGTL(("snmp_sess_add", "fd %d\n", transport->sock));
01557
01558 if ((slp = snmp_sess_copy(in_session)) == NULL) {
01559 return (NULL);
01560 }
01561
01562 slp->transport = transport;
01563 slp->internal->hook_pre = fpre_parse;
01564 slp->internal->hook_parse = fparse;
01565 slp->internal->hook_post = fpost_parse;
01566 slp->internal->hook_build = fbuild;
01567 slp->internal->hook_realloc_build = frbuild;
01568 slp->internal->check_packet = fcheck;
01569 slp->internal->hook_create_pdu = fcreate_pdu;
01570
01571 slp->session->rcvMsgMaxSize = transport->msgMaxSize;
01572
01573 if (slp->session->version == SNMP_VERSION_3) {
01574 DEBUGMSGTL(("snmp_sess_add",
01575 "adding v3 session -- engineID probe now\n"));
01576 if (!snmpv3_engineID_probe(slp, in_session)) {
01577 DEBUGMSGTL(("snmp_sess_add", "engine ID probe failed\n"));
01578 snmp_sess_close(slp);
01579 slp = NULL;
01580 }
01581 if (create_user_from_session(slp->session) != SNMPERR_SUCCESS) {
01582 slp->session->s_snmp_errno = SNMPERR_UNKNOWN_USER_NAME;
01583 DEBUGMSGTL(("snmp_api",
01584 "_sess_open(): failed(2) to create a new user from session\n"));
01585 return 0;
01586 }
01587 }
01588
01589 return (void *) slp;
01590 }
01591
01592
01593
01594 void *
01595 snmp_sess_add(netsnmp_session * in_session,
01596 netsnmp_transport *transport,
01597 int (*fpre_parse) (netsnmp_session *, netsnmp_transport *,
01598 void *, int),
01599 int (*fpost_parse) (netsnmp_session *, netsnmp_pdu *, int))
01600 {
01601 return snmp_sess_add_ex(in_session, transport, fpre_parse, NULL,
01602 fpost_parse, NULL, NULL, NULL, NULL);
01603 }
01604
01605
01606
01607 void *
01608 snmp_sess_open(netsnmp_session * pss)
01609 {
01610 void *pvoid;
01611 pvoid = _sess_open(pss);
01612 if (!pvoid) {
01613 SET_SNMP_ERROR(pss->s_snmp_errno);
01614 }
01615 return pvoid;
01616 }
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634 int
01635 create_user_from_session(netsnmp_session * session)
01636 {
01637 struct usmUser *user;
01638 int user_just_created = 0;
01639 u_char *cp;
01640
01641
01642
01643
01644
01645 if (SNMP_FLAGS_USER_CREATED == (session->flags & SNMP_FLAGS_USER_CREATED) ||
01646 session->securityModel != SNMP_SEC_MODEL_USM ||
01647 session->version != SNMP_VERSION_3 ||
01648 session->securityEngineIDLen == 0)
01649 return SNMPERR_SUCCESS;
01650
01651 session->flags |= SNMP_FLAGS_USER_CREATED;
01652
01653
01654
01655
01656
01657 user = usm_get_user_from_list(session->securityEngineID,
01658 session->securityEngineIDLen,
01659 session->securityName,
01660 usm_get_userList(), 0);
01661 if (user == NULL) {
01662 DEBUGMSGTL(("snmp_api", "Building user %s...\n",
01663 session->securityName));
01664
01665
01666
01667 user = (struct usmUser *) calloc(1, sizeof(struct usmUser));
01668 if (user == NULL)
01669 return SNMPERR_GENERR;
01670
01671
01672
01673
01674 if (session->securityName) {
01675 user->name = strdup(session->securityName);
01676 user->secName = strdup(session->securityName);
01677 if (user->name == NULL || user->secName == NULL) {
01678 usm_free_user(user);
01679 return SNMPERR_GENERR;
01680 }
01681 }
01682
01683
01684
01685
01686 if (memdup(&user->engineID, session->securityEngineID,
01687 session->securityEngineIDLen) != SNMPERR_SUCCESS) {
01688 usm_free_user(user);
01689 return SNMPERR_GENERR;
01690 }
01691 user->engineIDLen = session->securityEngineIDLen;
01692
01693 user_just_created = 1;
01694 }
01695
01696
01697
01698 if (session->securityAuthProto != NULL) {
01699 SNMP_FREE(user->authProtocol);
01700 user->authProtocol =
01701 snmp_duplicate_objid(session->securityAuthProto,
01702 session->securityAuthProtoLen);
01703 if (user->authProtocol == NULL) {
01704 usm_free_user(user);
01705 return SNMPERR_GENERR;
01706 }
01707 user->authProtocolLen = session->securityAuthProtoLen;
01708 }
01709
01710
01711
01712
01713 if (session->securityPrivProto != NULL) {
01714 SNMP_FREE(user->privProtocol);
01715 user->privProtocol =
01716 snmp_duplicate_objid(session->securityPrivProto,
01717 session->securityPrivProtoLen);
01718 if (user->privProtocol == NULL) {
01719 usm_free_user(user);
01720 return SNMPERR_GENERR;
01721 }
01722 user->privProtocolLen = session->securityPrivProtoLen;
01723 }
01724
01725
01726
01727
01728 if (session->securityAuthLocalKey != NULL
01729 && session->securityAuthLocalKeyLen != 0) {
01730
01731 if (memdup(&user->authKey, session->securityAuthLocalKey,
01732 session->securityAuthLocalKeyLen) != SNMPERR_SUCCESS) {
01733 usm_free_user(user);
01734 return SNMPERR_GENERR;
01735 }
01736 user->authKeyLen = session->securityAuthLocalKeyLen;
01737 } else if (session->securityAuthKey != NULL
01738 && session->securityAuthKeyLen != 0) {
01739 SNMP_FREE(user->authKey);
01740 user->authKey = (u_char *) calloc(1, USM_LENGTH_KU_HASHBLOCK);
01741 if (user->authKey == NULL) {
01742 usm_free_user(user);
01743 return SNMPERR_GENERR;
01744 }
01745 user->authKeyLen = USM_LENGTH_KU_HASHBLOCK;
01746 if (generate_kul(user->authProtocol, user->authProtocolLen,
01747 session->securityEngineID,
01748 session->securityEngineIDLen,
01749 session->securityAuthKey,
01750 session->securityAuthKeyLen, user->authKey,
01751 &user->authKeyLen) != SNMPERR_SUCCESS) {
01752 usm_free_user(user);
01753 return SNMPERR_GENERR;
01754 }
01755 } else if ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01756 NETSNMP_DS_LIB_AUTHLOCALIZEDKEY))) {
01757 size_t buflen = USM_AUTH_KU_LEN;
01758 user->authKey = malloc(buflen);
01759 user->authKeyLen = 0;
01760
01761 if (!snmp_hex_to_binary(&user->authKey, &buflen, &user->authKeyLen,
01762 0, cp)) {
01763 usm_free_user(user);
01764 return SNMPERR_GENERR;
01765 }
01766 }
01767
01768
01769
01770
01771 if (session->securityPrivLocalKey != NULL
01772 && session->securityPrivLocalKeyLen != 0) {
01773
01774 if (memdup(&user->privKey, session->securityPrivLocalKey,
01775