Logo
Home page Net-SNMP

Archive Search:

Require all words?

Site Search:
Google
Main Page | Modules | Data Structures | File List | Data Fields | Related Pages | Examples

snmp_api.c

00001 /* Portions of this file are subject to the following copyright(s).  See
00002  * the Net-SNMP's COPYING file for more details and other copyrights
00003  * that may apply:
00004  */
00005 /******************************************************************
00006         Copyright 1989, 1991, 1992 by Carnegie Mellon University
00007 
00008                       All Rights Reserved
00009 
00010 Permission to use, copy, modify, and distribute this software and its
00011 documentation for any purpose and without fee is hereby granted,
00012 provided that the above copyright notice appear in all copies and that
00013 both that copyright notice and this permission notice appear in
00014 supporting documentation, and that the name of CMU not be
00015 used in advertising or publicity pertaining to distribution of the
00016 software without specific, written prior permission.
00017 
00018 CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
00019 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
00020 CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
00021 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
00022 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
00023 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
00024 SOFTWARE.
00025 ******************************************************************/
00026 /*
00027  * Portions of this file are copyrighted by:
00028  * Copyright Copyright 2003 Sun Microsystems, Inc. All rights reserved.
00029  * Use is subject to license terms specified in the COPYING file
00030  * distributed with the Net-SNMP package.
00031  */
00032 
00036 /*
00037  * snmp_api.c - API for access to snmp.
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>      /* for xdump & {build,parse}_var_op */
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         /* CSTYLED */ \
00149         ((tvp)->tv_sec cmp (uvp)->tv_sec || \
00150         ((tvp)->tv_sec == (uvp)->tv_sec && \
00151         /* CSTYLED */ \
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  * Globals.
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)        /* bits per mask */
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  * enterprises.cmu.systems.cmuSNMP 
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  * don't set higher than 0x7fffffff, and I doubt it should be that high
00195  * * = 4 gig snmp messages max 
00196  */
00197 #define MAXIMUM_PACKET_SIZE 0x7fffffff
00198 
00199 /*
00200  * Internal information about the state of the snmp session.
00201  */
00202 struct snmp_internal_session {
00203     netsnmp_request_list *requests;     /* Info about outstanding requests */
00204     netsnmp_request_list *requestsEnd;  /* ptr to end of list */
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  * The list of active/open sessions.
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",                 /* SNMPERR_SUCCESS */
00237     "Generic error",            /* SNMPERR_GENERR */
00238     "Invalid local port",       /* SNMPERR_BAD_LOCPORT */
00239     "Unknown host",             /* SNMPERR_BAD_ADDRESS */
00240     "Unknown session",          /* SNMPERR_BAD_SESSION */
00241     "Too long",                 /* SNMPERR_TOO_LONG */
00242     "No socket",                /* SNMPERR_NO_SOCKET */
00243     "Cannot send V2 PDU on V1 session", /* SNMPERR_V2_IN_V1 */
00244     "Cannot send V1 PDU on V2 session", /* SNMPERR_V1_IN_V2 */
00245     "Bad value for non-repeaters",      /* SNMPERR_BAD_REPEATERS */
00246     "Bad value for max-repetitions",    /* SNMPERR_BAD_REPETITIONS */
00247     "Error building ASN.1 representation",      /* SNMPERR_BAD_ASN1_BUILD */
00248     "Failure in sendto",        /* SNMPERR_BAD_SENDTO */
00249     "Bad parse of ASN.1 type",  /* SNMPERR_BAD_PARSE */
00250     "Bad version specified",    /* SNMPERR_BAD_VERSION */
00251     "Bad source party specified",       /* SNMPERR_BAD_SRC_PARTY */
00252     "Bad destination party specified",  /* SNMPERR_BAD_DST_PARTY */
00253     "Bad context specified",    /* SNMPERR_BAD_CONTEXT */
00254     "Bad community specified",  /* SNMPERR_BAD_COMMUNITY */
00255     "Cannot send noAuth/Priv",       /* SNMPERR_NOAUTH_DESPRIV */
00256     "Bad ACL definition",       /* SNMPERR_BAD_ACL */
00257     "Bad Party definition",     /* SNMPERR_BAD_PARTY */
00258     "Session abort failure",    /* SNMPERR_ABORT */
00259     "Unknown PDU type",         /* SNMPERR_UNKNOWN_PDU */
00260     "Timeout",                  /* SNMPERR_TIMEOUT */
00261     "Failure in recvfrom",      /* SNMPERR_BAD_RECVFROM */
00262     "Unable to determine contextEngineID",      /* SNMPERR_BAD_ENG_ID */
00263     "No securityName specified",        /* SNMPERR_BAD_SEC_NAME */
00264     "Unable to determine securityLevel",        /* SNMPERR_BAD_SEC_LEVEL  */
00265     "ASN.1 parse error in message",     /* SNMPERR_ASN_PARSE_ERR */
00266     "Unknown security model in message",        /* SNMPERR_UNKNOWN_SEC_MODEL */
00267     "Invalid message (e.g. msgFlags)",  /* SNMPERR_INVALID_MSG */
00268     "Unknown engine ID",        /* SNMPERR_UNKNOWN_ENG_ID */
00269     "Unknown user name",        /* SNMPERR_UNKNOWN_USER_NAME */
00270     "Unsupported security level",       /* SNMPERR_UNSUPPORTED_SEC_LEVEL */
00271     "Authentication failure (incorrect password, community or key)",    /* SNMPERR_AUTHENTICATION_FAILURE */
00272     "Not in time window",       /* SNMPERR_NOT_IN_TIME_WINDOW */
00273     "Decryption error",         /* SNMPERR_DECRYPTION_ERR */
00274     "SCAPI general failure",    /* SNMPERR_SC_GENERAL_FAILURE */
00275     "SCAPI sub-system not configured",  /* SNMPERR_SC_NOT_CONFIGURED */
00276     "Key tools not available",  /* SNMPERR_KT_NOT_AVAILABLE */
00277     "Unknown Report message",   /* SNMPERR_UNKNOWN_REPORT */
00278     "USM generic error",        /* SNMPERR_USM_GENERICERROR */
00279     "USM unknown security name (no such user exists)",  /* SNMPERR_USM_UNKNOWNSECURITYNAME */
00280     "USM unsupported security level (this user has not been configured for that level of security)",    /* SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL */
00281     "USM encryption error",     /* SNMPERR_USM_ENCRYPTIONERROR */
00282     "USM authentication failure (incorrect password or key)",   /* SNMPERR_USM_AUTHENTICATIONFAILURE */
00283     "USM parse error",          /* SNMPERR_USM_PARSEERROR */
00284     "USM unknown engineID",     /* SNMPERR_USM_UNKNOWNENGINEID */
00285     "USM not in time window",   /* SNMPERR_USM_NOTINTIMEWINDOW */
00286     "USM decryption error",     /* SNMPERR_USM_DECRYPTIONERROR */
00287     "MIB not initialized",      /* SNMPERR_NOMIB */
00288     "Value out of range",       /* SNMPERR_RANGE */
00289     "Sub-id out of range",      /* SNMPERR_MAX_SUBID */
00290     "Bad sub-id in object identifier",  /* SNMPERR_BAD_SUBID */
00291     "Object identifier too long",       /* SNMPERR_LONG_OID */
00292     "Bad value name",           /* SNMPERR_BAD_NAME */
00293     "Bad value notation",       /* SNMPERR_VALUE */
00294     "Unknown Object Identifier",        /* SNMPERR_UNKNOWN_OBJID */
00295     "No PDU in snmp_send",      /* SNMPERR_NULL_PDU */
00296     "Missing variables in PDU", /* SNMPERR_NO_VARS */
00297     "Bad variable type",        /* SNMPERR_VAR_TYPE */
00298     "Out of memory (malloc failure)",   /* SNMPERR_MALLOC */
00299     "Kerberos related error",   /* SNMPERR_KRB5 */
00300     "Protocol error",           /* SNMPERR_PROTOCOL */
00301 };
00302 
00303 static const char *secLevelName[] = {
00304     "BAD_SEC_LEVEL",
00305     "noAuthNoPriv",
00306     "authNoPriv",
00307     "authPriv"
00308 };
00309 
00310 /*
00311  * Multiple threads may changes these variables.
00312  * Suggest using the Single API, which does not use Sessions.
00313  *
00314  * Reqid may need to be protected. Time will tell...
00315  *
00316  */
00317 /*
00318  * MTCRITICAL_RESOURCE
00319  */
00320 /*
00321  * use token in comments to individually protect these resources 
00322  */
00323 struct session_list *Sessions = NULL;   /* MT_LIB_SESSION */
00324 static long     Reqid = 0;      /* MT_LIB_REQUESTID */
00325 static long     Msgid = 0;      /* MT_LIB_MESSAGEID */
00326 static long     Sessid = 0;     /* MT_LIB_SESSIONID */
00327 static long     Transid = 0;    /* MT_LIB_TRANSID */
00328 int             snmp_errno = 0;
00329 /*
00330  * END MTCRITICAL_RESOURCE
00331  */
00332 
00333 /*
00334  * global error detail storage
00335  */
00336 static char     snmp_detail[192];
00337 static int      snmp_detail_f = 0;
00338 
00339 /*
00340  * Prototypes.
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;         /*MTCRITICAL_RESOURCE */
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);       /* mask to 15 bits */
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;         /*MTCRITICAL_RESOURCE */
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);       /* mask to 15 bits */
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;        /*MTCRITICAL_RESOURCE */
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);       /* mask to 15 bits */
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;       /*MTCRITICAL_RESOURCE */
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);       /* mask to 15 bits */
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;          /*MTCRITICAL_RESOURCE */
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  * returns pointer to static data 
00493  */
00494 /*
00495  * results not guaranteed in multi-threaded use 
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  * snmp_error - return error data
00522  * Inputs :  address of errno, address of snmp_errno, address of string
00523  * Caller must free the string returned after use.
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      * append a useful system errno interpretation. 
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  * snmp_sess_error - same as snmp_error for single session API use.
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  * snmp_sess_perror(): print a error stored in a session pointer 
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  * snmp_sess_perror(): print a error stored in a session pointer 
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  * Primordial SNMP library initialization.
00607  * Initializes mutex locks.
00608  * Invokes minimum required initialization for displaying MIB objects.
00609  * Gets initial request ID for all transactions,
00610  * and finds which port SNMP over UDP uses.
00611  * SNMP over AppleTalk is not currently supported.
00612  *
00613  * Warning: no debug messages here.
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();            /* initialize the mt locking structures */
00633 #ifndef DISABLE_MIB_LOADING
00634     init_mib_internals();
00635 #endif /* DISABLE_MIB_LOADING */
00636     netsnmp_tdomain_init();
00637 
00638     gettimeofday(&tv, (struct timezone *) 0);
00639     /*
00640      * Now = tv;
00641      */
00642 
00643     /*
00644      * get pseudo-random values for request ID and message ID 
00645      */
00646     /*
00647      * don't allow zero value to repeat init 
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          * store it in host byte order 
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  * Initializes the session structure.
00690  * May perform one time minimal library initialization.
00691  * No MIB file processing is done via this call.
00692  */
00693 void
00694 snmp_sess_init(netsnmp_session * session)
00695 {
00696     _init_snmp();
00697 
00698     /*
00699      * initialize session to default values 
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;      /* To prevent double init's. */
00796 
00797     if (done_init) {
00798         return;
00799     }
00800 
00801     done_init = 1;
00802 
00803     /*
00804      * make the type available everywhere else 
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      * set our current locale properly to initialize isprint() type functions 
00816      */
00817 #ifdef HAVE_SETLOCALE
00818     setlocale(LC_CTYPE, "");
00819 #endif
00820 
00821     snmp_debug_init();    /* should be done first, to turn on debugging ASAP */
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 /* DISABLE_MIB_LOADING */
00838 
00839     read_configs();
00840 
00841 }                               /* end init_snmp() */
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 /* DISABLE_MIB_LOADING */
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  * Sets up the session with the snmp_session information provided by the user.
00883  * Then opens and binds the necessary low-level transport.  A handle to the
00884  * created session is returned (this is NOT the same as the pointer passed to
00885  * snmp_open()).  On any error, NULL is returned and snmp_errno is set to the
00886  * appropriate error code.
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  * extended open 
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      * Copy session structure and link into list 
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      * zero out pointers so if we have to free the session we wont free mem
00988      * owned by in_session 
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      * session now points to the new structure that still contains pointers to
01000      * data allocated elsewhere.  Some of this data is copied to space malloc'd
01001      * here, and the pointer replaced with the new one.
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      * Fill in defaults if necessary 
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;   /* replace pointer with pointer to new data */
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          * default contextEngineID to securityEngineIDLen if defined 
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         /* it will be a hex string */
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         /* it will be a hex string */
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          * security module specific inialization 
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      * If we are opening a V3 session and we don't know engineID we must probe
01294      * it -- this must be done after the session is created and inserted in the
01295      * list so that the response can handled correctly. 
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; /* prevent recursion */
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; /* XX?? */
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:   /* this is what we expected -> Report == 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          * if boot/time supplied set it for this engineID 
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;       /* XX?? */
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 /*******************************************************************-o-******
01377  * snmp_sess_open
01378  *
01379  * Parameters:
01380  *      *in_session
01381  *
01382  * Returns:
01383  *      Pointer to a session in the session list   -OR-         FIX -- right?
01384  *      NULL on failure.
01385  *
01386  * The "spin-free" version of snmp_open.
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;       /* XX?? */
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 }                               /* end snmp_sess_open() */
01454 
01455 
01456 
01457 /*
01458  * EXPERIMENTAL API EXTENSIONS ------------------------------------------ 
01459  * 
01460  * snmp_sess_add_ex, snmp_sess_add, snmp_add 
01461  * 
01462  * Analogous to snmp_open family of functions, but taking a netsnmp_transport
01463  * pointer as an extra argument.  Unlike snmp_open et al. it doesn't attempt
01464  * to interpret the in_session->peername as a transport endpoint specifier,
01465  * but instead uses the supplied transport.  JBPN
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 }                               /*  end snmp_sess_add_ex()  */
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  * create_user_from_session(netsnmp_session *session):
01622  * 
01623  * creates a user in the usm table from the information in a session.
01624  * If the user already exists, it is updated with the current
01625  * information from the session
01626  * 
01627  * Parameters:
01628  * session -- IN: pointer to the session to use when creating the user.
01629  * 
01630  * Returns:
01631  * SNMPERR_SUCCESS
01632  * SNMPERR_GENERR 
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      * - don't create-another/copy-into user for this session by default
01643      * - bail now (no error) if we don't have an engineID
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      * now that we have the engineID, create an entry in the USM list
01655      * for this user using the information in the session 
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          * user doesn't exist so we create and add it 
01666          */
01667         user = (struct usmUser *) calloc(1, sizeof(struct usmUser));
01668         if (user == NULL)
01669             return SNMPERR_GENERR;
01670 
01671         /*
01672          * copy in the securityName 
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          * copy in the engineID 
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      * copy the auth protocol 
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      * copy the priv protocol 
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      * copy in the authentication Key.  If not localized, localize it 
01727      */
01728     if (session->securityAuthLocalKey != NULL
01729         && session->securityAuthLocalKeyLen != 0) {
01730         /* already localized key passed in.  use it */
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); /* max length needed */
01759         user->authKeyLen = 0;
01760         /* it will be a hex string */
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      * copy in the privacy Key.  If not localized, localize it 
01770      */
01771     if (session->securityPrivLocalKey != NULL
01772         && session->securityPrivLocalKeyLen != 0) {
01773         /* already localized key passed in.  use it */
01774         if (memdup(&user->privKey, session->securityPrivLocalKey,
01775