Commit message: libsnmp, USM: Introduce a reference count in struct usmStateReference

This patch fixes https://sourceforge.net/p/net-snmp/bugs/2956/.
CVE: CVE-2019-20892
CWE: CWE-415
Vulnerability description: net-snmp before 5.8.1.pre1 has a double free in usm_free_usmStateReference in snmplib/snmpusm.c via an SNMPv3 GetBulk request. NOTE: this affects net-snmp packages shipped to end users by multiple Linux distributions, but might not affect an upstream release.

Project: net-snmp
File: snmpusm.c

usm_set_usmStateReference_engine_id(struct usmStateReference *ref,
                                    u_char * engine_id,
                                    size_t engine_id_len)
{
    MAKE_ENTRY(ref, u_char, engine_id, engine_id_len,
               usr_engine_id, usr_engine_id_length);
}

Project: net-snmp
File: snmp_client.c

snmp_reset_var_types(netsnmp_variable_list * vbl, u_char new_type)
{
    while (vbl) {
        snmp_set_var_typed_value(vbl, new_type, NULL, 0);
        vbl = vbl->next_variable;
    }
}

Project: net-snmp
File: snmp_client.c

count_varbinds(netsnmp_variable_list * var_ptr)
{
    int             count = 0;

    for (; var_ptr != NULL; var_ptr = var_ptr->next_variable)
        count++;

    return count;
}

Project: net-snmp
File: snmpusm.c

get_default_authtype(size_t * len)
{
    if (defaultAuthType == NULL) {
        defaultAuthType = SNMP_DEFAULT_AUTH_PROTO;
        defaultAuthTypeLen = SNMP_DEFAULT_AUTH_PROTOLEN;
    }
    if (len)
        *len = defaultAuthTypeLen;
    return defaultAuthType;
}

Project: net-snmp
File: snmp_client.c

snmp_replace_var_types(netsnmp_variable_list * vbl, u_char old_type,
                       u_char new_type)
{
    while (vbl) {
        if (vbl->type == old_type) {
            snmp_set_var_typed_value(vbl, new_type, NULL, 0);
        }
        vbl = vbl->next_variable;
    }
}

Project: net-snmp
File: snmpusm.c

usm_create_user_from_session(netsnmp_session * session)
{
    struct usmUser *user;
    int             user_just_created = 0;
    char *cp;

    /*
     * - don't create-another/copy-into user for this session by default
     * - bail now (no error) if we don't have an engineID
     */
    if (SNMP_FLAGS_USER_CREATED == (session->flags & SNMP_FLAGS_USER_CREATED) ||
        session->securityModel != SNMP_SEC_MODEL_USM ||
        session->version != SNMP_VERSION_3 ||
        session->securityNameLen == 0 ||
        session->securityEngineIDLen == 0)
        return SNMPERR_SUCCESS;

    DEBUGMSGTL(("usm", "no flag defined...  continuing\n"));
    session->flags |= SNMP_FLAGS_USER_CREATED;

    /*
     * now that we have the engineID, create an entry in the USM list
     * for this user using the information in the session 
     */
    user = usm_get_user_from_list(session->securityEngineID,
                                  session->securityEngineIDLen,
                                  session->securityName,
                                  usm_get_userList(), 0);
    if (NULL != user) 
        DEBUGMSGTL(("usm", "user exists x=%p\n", user));
    else
    if (user == NULL) {
        DEBUGMSGTL(("usm", "Building user %s...\n",
                    session->securityName));
        /*
         * user doesn't exist so we create and add it 
         */
        user = (struct usmUser *) calloc(1, sizeof(struct usmUser));
        if (user == NULL)
            return SNMPERR_GENERR;

        /*
         * copy in the securityName 
         */
        if (session->securityName) {
            user->name = strdup(session->securityName);
            user->secName = strdup(session->securityName);
            if (user->name == NULL || user->secName == NULL) {
                usm_free_user(user);
                return SNMPERR_GENERR;
            }
        }

        /*
         * copy in the engineID 
         */
        user->engineID = netsnmp_memdup(session->securityEngineID,
                                        session->securityEngineIDLen);
        if (session->securityEngineID && !user->engineID) {
            usm_free_user(user);
            return SNMPERR_GENERR;
        }
        user->engineIDLen = session->securityEngineIDLen;

        user_just_created = 1;
    }

    /*
     * copy the auth protocol 
     */
    if (user->authProtocol == NULL && session->securityAuthProto != NULL) {
        SNMP_FREE(user->authProtocol);
        user->authProtocol =
            snmp_duplicate_objid(session->securityAuthProto,
                                 session->securityAuthProtoLen);
        if (user->authProtocol == NULL) {
            usm_free_user(user);
            return SNMPERR_GENERR;
        }
        user->authProtocolLen = session->securityAuthProtoLen;
    }

    /*
     * copy the priv protocol 
     */
    if (user->privProtocol == NULL && session->securityPrivProto != NULL) {
        SNMP_FREE(user->privProtocol);
        user->privProtocol =
            snmp_duplicate_objid(session->securityPrivProto,
                                 session->securityPrivProtoLen);
        if (user->privProtocol == NULL) {
            usm_free_user(user);
            return SNMPERR_GENERR;
        }
        user->privProtocolLen = session->securityPrivProtoLen;
    }

    /*
     * copy in the authentication Key.  If not localized, localize it 
     */
    if (user->authKey == NULL) {
        if (session->securityAuthLocalKey != NULL
            && session->securityAuthLocalKeyLen != 0) {
            /* already localized key passed in.  use it */
            SNMP_FREE(user->authKey);
            user->authKey = netsnmp_memdup(session->securityAuthLocalKey,
                                           session->securityAuthLocalKeyLen);
            if (!user->authKey) {
                usm_free_user(user);
                return SNMPERR_GENERR;
            }
            user->authKeyLen = session->securityAuthLocalKeyLen;
        } else if (session->securityAuthKeyLen != 0) {
            SNMP_FREE(user->authKey);
            user->authKey = (u_char *) calloc(1, USM_LENGTH_KU_HASHBLOCK);
            user->authKeyLen = USM_LENGTH_KU_HASHBLOCK;
            if ((user->authKey == NULL) ||
                generate_kul(user->authProtocol, user->authProtocolLen,
                             user->engineID, user->engineIDLen,
                             session->securityAuthKey,
                             session->securityAuthKeyLen, user->authKey,
                             &user->authKeyLen) != SNMPERR_SUCCESS) {
                usm_free_user(user);
                return SNMPERR_GENERR;
            }
        } else if ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 
                                               NETSNMP_DS_LIB_AUTHLOCALIZEDKEY))) {
            size_t buflen = USM_AUTH_KU_LEN;
            SNMP_FREE(user->authKey);
            user->authKey = (u_char *)malloc(buflen); /* max length needed */
            user->authKeyLen = 0;
            /* it will be a hex string */
            if ((NULL == user->authKey) ||
                !snmp_hex_to_binary(&user->authKey, &buflen, &user->authKeyLen,
                                    0, cp)) {
                usm_free_user(user);
                return SNMPERR_GENERR;
            }
        }
    }

    /*
     * copy in the privacy Key.  If not localized, localize it 
     */
    if (user->privKey == NULL) {
        /** save buffer size in case we need to extend key */
        int keyBufSize = USM_PRIV_KU_LEN;

        DEBUGMSGTL(("usm", "copying privKey\n"));
        if (session->securityPrivLocalKey != NULL
            && session->securityPrivLocalKeyLen != 0) {
            /* already localized key passed in.  use it */
            SNMP_FREE(user->privKey);
            user->privKey = netsnmp_memdup(session->securityPrivLocalKey,
                                           session->securityPrivLocalKeyLen);
            if (!user->privKey) {
                usm_free_user(user);
                return SNMPERR_GENERR;
            }
            keyBufSize = user->privKeyLen = session->securityPrivLocalKeyLen;
        } else if (session->securityPrivKeyLen != 0) {
            SNMP_FREE(user->privKey);
            user->privKey = (u_char *) calloc(1, keyBufSize);
            user->privKeyLen = keyBufSize;
            if ((user->privKey == NULL) ||
                generate_kul(user->authProtocol, user->authProtocolLen,
                             user->engineID, user->engineIDLen,
                             session->securityPrivKey,
                             session->securityPrivKeyLen, user->privKey,
                             &user->privKeyLen) != SNMPERR_SUCCESS) {
                usm_free_user(user);
                return SNMPERR_GENERR;
            }
        } else if ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 
                                               NETSNMP_DS_LIB_PRIVLOCALIZEDKEY))) {
            size_t buflen = keyBufSize;
            user->privKey = (u_char *)malloc(buflen); /* max length needed */
            user->privKeyLen = 0;
            /* it will be a hex string */
            if ((NULL == user->privKey) ||
                !snmp_hex_to_binary(&user->privKey, &buflen, &user->privKeyLen,
                                    0, cp)) {
                usm_free_user(user);
                return SNMPERR_GENERR;
            }
        }
        if (usm_extend_user_kul(user, keyBufSize) != SNMPERR_SUCCESS) {
            usm_free_user(user);
            return SNMPERR_GENERR;
        }
    }

    if (user_just_created) {
        /*
         * add the user into the database 
         */
        user->userStatus = RS_ACTIVE;
        user->userStorageType = ST_READONLY;
        usm_add_user(user);
    }
    DEBUGMSGTL(("9:usm", "user created\n"));

    return SNMPERR_SUCCESS;


}

Project: net-snmp
File: snmpusm.c

usm_lookup_auth_type(const char *str)
{
    return usm_lookup_alg_type(str, usm_auth_type );
}

Project: net-snmp
File: snmpusm.c

usm_check_secLevel(int level, struct usmUser *user)
{

    if (user->userStatus != RS_ACTIVE)
        return -1;

    DEBUGMSGTL(("comparex", "Comparing: %" NETSNMP_PRIo "u %" NETSNMP_PRIo "u ",
                usmNoPrivProtocol[0], usmNoPrivProtocol[1]));
    DEBUGMSGOID(("comparex", usmNoPrivProtocol,
                 sizeof(usmNoPrivProtocol) / sizeof(oid)));
    DEBUGMSG(("comparex", "\n"));
    if (level == SNMP_SEC_LEVEL_AUTHPRIV
        && (netsnmp_oid_equals(user->privProtocol, user->privProtocolLen,
                             usmNoPrivProtocol,
                             sizeof(usmNoPrivProtocol) / sizeof(oid)) ==
            0)) {
        DEBUGMSGTL(("usm", "Level: %d\n", level));
        DEBUGMSGTL(("usm", "User (%s) Auth Protocol: ", user->name));
        DEBUGMSGOID(("usm", user->authProtocol, user->authProtocolLen));
        DEBUGMSG(("usm", ", User Priv Protocol: "));
        DEBUGMSGOID(("usm", user->privProtocol, user->privProtocolLen));
        DEBUGMSG(("usm", "\n"));
        return 1;
    }
    if ((level == SNMP_SEC_LEVEL_AUTHPRIV
         || level == SNMP_SEC_LEVEL_AUTHNOPRIV)
        &&
        (netsnmp_oid_equals
         (user->authProtocol, user->authProtocolLen, usmNoAuthProtocol,
          sizeof(usmNoAuthProtocol) / sizeof(oid)) == 0)) {
        DEBUGMSGTL(("usm", "Level: %d\n", level));
        DEBUGMSGTL(("usm", "User (%s) Auth Protocol: ", user->name));
        DEBUGMSGOID(("usm", user->authProtocol, user->authProtocolLen));
        DEBUGMSG(("usm", ", User Priv Protocol: "));
        DEBUGMSGOID(("usm", user->privProtocol, user->privProtocolLen));
        DEBUGMSG(("usm", "\n"));
        return 1;
    }

    return 0;
}                               /* end usm_check_secLevel() */

Project: net-snmp
File: snmpusm.c

usm_add_user_to_list(struct usmUser *user, struct usmUser *puserList)
{
    struct usmUser *nptr, *pptr, *optr;

    /*
     * loop through puserList till we find the proper, sorted place to
     * insert the new user
     */
    /* XXX - how to handle a NULL user->name ?? */
    /* XXX - similarly for a NULL nptr->name ?? */
    for (nptr = puserList, pptr = NULL; nptr != NULL;
         pptr = nptr, nptr = nptr->next) {
        if (nptr->engineIDLen > user->engineIDLen)
            break;

        if (user->engineID == NULL && nptr->engineID != NULL)
            break;

        if (nptr->engineIDLen == user->engineIDLen &&
            (nptr->engineID != NULL && user->engineID != NULL &&
             memcmp(nptr->engineID, user->engineID,
                    user->engineIDLen) > 0))
            break;

        if (!(nptr->engineID == NULL && user->engineID != NULL)) {
            if (nptr->engineIDLen == user->engineIDLen &&
                ((nptr->engineID == NULL && user->engineID == NULL) ||
                 memcmp(nptr->engineID, user->engineID,
                        user->engineIDLen) == 0)
                && strlen(nptr->name) > strlen(user->name))
                break;

            if (nptr->engineIDLen == user->engineIDLen &&
                ((nptr->engineID == NULL && user->engineID == NULL) ||
                 memcmp(nptr->engineID, user->engineID,
                        user->engineIDLen) == 0)
                && strlen(nptr->name) == strlen(user->name)
                && strcmp(nptr->name, user->name) > 0)
                break;

            if (nptr->engineIDLen == user->engineIDLen &&
                ((nptr->engineID == NULL && user->engineID == NULL) ||
                 memcmp(nptr->engineID, user->engineID,
                        user->engineIDLen) == 0)
                && strlen(nptr->name) == strlen(user->name)
                && strcmp(nptr->name, user->name) == 0) {
                /*
                 * the user is an exact match of a previous entry.
                 * Credentials may be different, though, so remove
                 * the old entry (and add the new one)!
                 */
                if (pptr) { /* change prev's next pointer */
                  pptr->next = nptr->next;
                }
                if (nptr->next) { /* change next's prev pointer */
                  nptr->next->prev = pptr;
                }
                optr = nptr;
                nptr = optr->next; /* add new user at this position */
                /* free the old user */
                optr->next=NULL;
                optr->prev=NULL;
                usm_free_user(optr);
                break; /* new user will be added below */
            }
        }
    }

    /*
     * nptr should now point to the user that we need to add ourselves
     * in front of, and pptr should be our new 'prev'.
     */

    /*
     * change our pointers
     */
    user->prev = pptr;
    user->next = nptr;

    /*
     * change the next's prev pointer
     */
    if (user->next)
        user->next->prev = user;

    /*
     * change the prev's next pointer
     */
    if (user->prev)
        user->prev->next = user;

    /*
     * rewind to the head of the list and return it (since the new head
     * could be us, we need to notify the above routine who the head now is.
     */
    for (pptr = user; pptr->prev != NULL; pptr = pptr->prev);
    return pptr;
}

Project: net-snmp
File: snmp_client.c

count_varbinds_of_type(netsnmp_variable_list * var_ptr, u_char type)
{
    int             count = 0;

    for (; var_ptr != NULL; var_ptr = var_ptr->next_variable)
        if (var_ptr->type == type)
            count++;

    return count;
}

Project: net-snmp
File: snmpusm.c

usm_store_users(int majorID, int minorID, void *serverarg, void *clientarg)
{
    /*
     * figure out our application name 
     */
    char           *appname = (char *) clientarg;
    if (appname == NULL) {
        appname = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 
					NETSNMP_DS_LIB_APPTYPE);
    }

    /*
     * save the user base 
     */
    usm_save_users("usmUser", appname);

    /*
     * never fails 
     */
    return SNMPERR_SUCCESS;
}

Project: net-snmp
File: snmp_client.c

snmp_synch_response_cb(netsnmp_session * ss,
                       netsnmp_pdu *pdu,
                       netsnmp_pdu **response, snmp_callback pcb)
{
    struct synch_state    lstate, *state;
    snmp_callback         cbsav;
    void                 *cbmagsav;
    int                   numfds, count;
    netsnmp_large_fd_set  fdset;
    struct timeval        timeout, *tvp;
    int                   block;

    memset((void *) &lstate, 0, sizeof(lstate));
    state = &lstate;
    cbsav = ss->callback;
    cbmagsav = ss->callback_magic;
    ss->callback = pcb;
    ss->callback_magic = (void *) state;
    netsnmp_large_fd_set_init(&fdset, FD_SETSIZE);

    if (snmp_send(ss, pdu) == 0) {
        snmp_free_pdu(pdu);
        state->status = STAT_ERROR;
    } else {
        state->reqid = pdu->reqid;
        state->waiting = 1;
    }

    while (state->waiting) {
        numfds = 0;
        NETSNMP_LARGE_FD_ZERO(&fdset);
        block = NETSNMP_SNMPBLOCK;
        tvp = &timeout;
        timerclear(tvp);
        snmp_sess_select_info2_flags(NULL, &numfds, &fdset, tvp, &block,
                                     NETSNMP_SELECT_NOALARMS);
        if (block == 1)
            tvp = NULL;         /* block without timeout */
        count = netsnmp_large_fd_set_select(numfds, &fdset, NULL, NULL, tvp);
        if (count > 0) {
            snmp_read2(&fdset);
        } else {
            switch (count) {
            case 0:
                snmp_timeout();
                break;
            case -1:
                if (errno == EINTR) {
                    continue;
                } else {
                    snmp_errno = SNMPERR_GENERR;    /*MTCRITICAL_RESOURCE */
                    /*
                     * CAUTION! if another thread closed the socket(s)
                     * waited on here, the session structure was freed.
                     * It would be nice, but we can't rely on the pointer.
                     * ss->s_snmp_errno = SNMPERR_GENERR;
                     * ss->s_errno = errno;
                     */
                    snmp_set_detail(strerror(errno));
                }
                /* FALLTHRU */
            default:
                state->status = STAT_ERROR;
                state->waiting = 0;
            }
        }

        if ( ss->flags & SNMP_FLAGS_RESP_CALLBACK ) {
            void (*cb)(void);
            cb = (void (*)(void))(ss->myvoid);
            cb();        /* Used to invoke 'netsnmp_check_outstanding_agent_requests();'
                            on internal AgentX queries.  */
        }
    }
    *response = state->pdu;
    ss->callback = cbsav;
    ss->callback_magic = cbmagsav;
    netsnmp_large_fd_set_cleanup(&fdset);
    return state->status;
}

Project: net-snmp
File: snmpusm.c

usm_set_usmStateReference_priv_key(struct usmStateReference *ref,
                                   u_char * priv_key, size_t priv_key_len)
{
    MAKE_ENTRY(ref, u_char, priv_key, priv_key_len,
               usr_priv_key, usr_priv_key_length);
}

Project: net-snmp
File: snmpusm.c

usm_lookup_priv_type(const char *str)
{
    return usm_lookup_alg_type(str, usm_priv_type );
}

Project: net-snmp
File: snmp_client.c

_copy_varlist(netsnmp_variable_list * var,      /* source varList */
              int errindex,     /* index of variable to drop (if any) */
              int copy_count)
{                               /* !=0 number variables to copy */
    netsnmp_variable_list *newhead, *newvar, *oldvar;
    int             ii = 0;

    newhead = NULL;
    oldvar = NULL;

    while (var && (copy_count-- > 0)) {
        /*
         * Drop the specified variable (if applicable) 
         * xxx hmm, is it intentional that dropping the errindex
         *     counts towards copy_count?
         */
        if (++ii == errindex) {
            var = var->next_variable;
            continue;
        }

        /*
         * clone the next variable. Cleanup if alloc fails 
         */
        newvar = (netsnmp_variable_list *)
            malloc(sizeof(netsnmp_variable_list));
        if (snmp_clone_var(var, newvar)) {
            if (newvar)
                free((char *) newvar);
            snmp_free_varbind(newhead);
            return NULL;
        }

        /*
         * add cloned variable to new list  
         */
        if (NULL == newhead)
            newhead = newvar;
        if (oldvar)
            oldvar->next_variable = newvar;
        oldvar = newvar;

        var = var->next_variable;
    }
    return newhead;
}

Project: net-snmp
File: snmp_client.c

snmp_split_pdu(netsnmp_pdu *pdu, int skip_count, int copy_count)
{
    netsnmp_pdu    *newpdu;
    newpdu = _clone_pdu_header(pdu);
    newpdu = _copy_pdu_vars(pdu, newpdu, 0,     /* don't drop any variables */
                            skip_count, copy_count);

    return newpdu;
}

Project: net-snmp
File: snmp_client.c

_copy_pdu_vars(netsnmp_pdu *pdu,        /* source PDU */
               netsnmp_pdu *newpdu,     /* target PDU */
               int drop_err,    /* !=0 drop errored variable */
               int skip_count,  /* !=0 number of variables to skip */
               int copy_count)
{                               /* !=0 number of variables to copy */
    netsnmp_variable_list *var;
#if TEMPORARILY_DISABLED
    int             copied;
#endif
    int             drop_idx;

    if (!newpdu)
        return NULL;            /* where is PDU to copy to ? */

    if (drop_err)
        drop_idx = pdu->errindex - skip_count;
    else
        drop_idx = 0;

    var = pdu->variables;
    while (var && (skip_count-- > 0))   /* skip over pdu variables */
        var = var->next_variable;

#if TEMPORARILY_DISABLED
    copied = 0;
    if (pdu->flags & UCD_MSG_FLAG_FORCE_PDU_COPY)
        copied = 1;             /* We're interested in 'empty' responses too */
#endif

    newpdu->variables = _copy_varlist(var, drop_idx, copy_count);
#if TEMPORARILY_DISABLED
    if (newpdu->variables)
        copied = 1;
#endif

#if ALSO_TEMPORARILY_DISABLED
    /*
     * Error if bad errindex or if target PDU has no variables copied 
     */
    if ((drop_err && (ii < pdu->errindex))
#if TEMPORARILY_DISABLED
        /*
         * SNMPv3 engineID probes are allowed to be empty.
         * See the comment in snmp_api.c for further details 
         */
        || copied == 0
#endif
        ) {
        snmp_free_pdu(newpdu);
        return 0;
    }
#endif
    return newpdu;
}

Project: net-snmp
File: snmpusm.c

usm_save_users_from_list(struct usmUser *puserList, const char *token,
                         const char *type)
{
    struct usmUser *uptr;
    for (uptr = puserList; uptr != NULL; uptr = uptr->next) {
        if (uptr->userStorageType == ST_NONVOLATILE)
            usm_save_user(uptr, token, type);
    }
}

Project: net-snmp
File: snmp_client.c

snmp_errstring(int errstat)
{
    const char * const error_string[19] = {
        "(noError) No Error",
        "(tooBig) Response message would have been too large.",
        "(noSuchName) There is no such variable name in this MIB.",
        "(badValue) The value given has the wrong type or length.",
        "(readOnly) The two parties used do not have access to use the specified SNMP PDU.",
        "(genError) A general failure occured",
        "noAccess",
        "wrongType (The set datatype does not match the data type the agent expects)",
        "wrongLength (The set value has an illegal length from what the agent expects)",
        "wrongEncoding",
        "wrongValue (The set value is illegal or unsupported in some way)",
        "noCreation (That table does not support row creation or that object can not ever be created)",
        "inconsistentValue (The set value is illegal or unsupported in some way)",
        "resourceUnavailable (This is likely a out-of-memory failure within the agent)",
        "commitFailed",
        "undoFailed",
        "authorizationError (access denied to that object)",
        "notWritable (That object does not support modification)",
        "inconsistentName (That object can not currently be created)"
    };

    if (errstat <= MAX_SNMP_ERR && errstat >= SNMP_ERR_NOERROR) {
        return error_string[errstat];
    } else {
        return "Unknown Error";
    }
}

Project: net-snmp
File: snmp_client.c

snmp_varbind_len(netsnmp_pdu *pdu)
{
    register netsnmp_variable_list *vars;
    unsigned long   retVal = 0;
    if (pdu)
        for (vars = pdu->variables; vars; vars = vars->next_variable) {
            retVal++;
        }

    return retVal;
}

Project: net-snmp
File: snmpusm.c

usm_lookup_priv_str(int value)
{
    return usm_lookup_alg_str(value, usm_priv_type );
}

Project: net-snmp
File: snmpusm.c

static int usm_discover_engineid(struct session_list *slp,
                                 netsnmp_session *session)
{
    netsnmp_pdu    *pdu = NULL, *response = NULL;
    int status, i;

    if (usm_build_probe_pdu(&pdu) != 0) {
        DEBUGMSGTL(("snmp_api", "unable to create probe PDU\n"));
        return SNMP_ERR_GENERR;
    }
    DEBUGMSGTL(("snmp_api", "probing for engineID...\n"));
    session->flags |= SNMP_FLAGS_DONT_PROBE; /* prevent recursion */
    status = snmp_sess_synch_response(slp, pdu, &response);

    if ((response == NULL) && (status == STAT_SUCCESS)) {
        status = STAT_ERROR;
    }

    switch (status) {
    case STAT_SUCCESS:
        session->s_snmp_errno = SNMPERR_INVALID_MSG; /* XX?? */
        DEBUGMSGTL(("snmp_sess_open",
                    "error: expected Report as response to probe: %s (%ld)\n",
                    snmp_errstring(response->errstat),
                    response->errstat));
        break;
    case STAT_ERROR:   /* this is what we expected -> Report == STAT_ERROR */
        session->s_snmp_errno = SNMPERR_UNKNOWN_ENG_ID;
        break;
    case STAT_TIMEOUT:
        session->s_snmp_errno = SNMPERR_TIMEOUT;
        break;
    default:
        DEBUGMSGTL(("snmp_sess_open",
                    "unable to connect with remote engine: %s (%d)\n",
                    snmp_api_errstring(session->s_snmp_errno),
                    session->s_snmp_errno));
        break;
    }

    if (slp->session->securityEngineIDLen == 0) {
        DEBUGMSGTL(("snmp_api",
                    "unable to determine remote engine ID\n"));
        /* clear the flag so that probe occurs on next inform */
        session->flags &= ~SNMP_FLAGS_DONT_PROBE;
        return SNMP_ERR_GENERR;
    }

    session->s_snmp_errno = SNMPERR_SUCCESS;
    if (snmp_get_do_debugging()) {
        DEBUGMSGTL(("snmp_sess_open",
                    "  probe found engineID:  "));
        for (i = 0; i < slp->session->securityEngineIDLen; i++)
            DEBUGMSG(("snmp_sess_open", "%02x",
                      slp->session->securityEngineID[i]));
        DEBUGMSG(("snmp_sess_open", "\n"));
    }

    /*
     * if boot/time supplied set it for this engineID 
     */
    if (session->engineBoots || session->engineTime) {
        set_enginetime(session->securityEngineID,
                       session->securityEngineIDLen,
                       session->engineBoots, session->engineTime,
                       TRUE);
    }
    return SNMPERR_SUCCESS;
}

Project: net-snmp
File: snmpusm.c

usm_free_usmStateReference(void *old)
{
    struct usmStateReference *ref = old;

    if (!ref)
        return;

    if (--ref->refcnt > 0)
        return;

    SNMP_FREE(ref->usr_name);
    SNMP_FREE(ref->usr_engine_id);
    SNMP_FREE(ref->usr_auth_protocol);
    SNMP_FREE(ref->usr_priv_protocol);

    if (ref->usr_auth_key_length && ref->usr_auth_key) {
        SNMP_ZERO(ref->usr_auth_key, ref->usr_auth_key_length);
        SNMP_FREE(ref->usr_auth_key);
    }
    if (ref->usr_priv_key_length && ref->usr_priv_key) {
        SNMP_ZERO(ref->usr_priv_key, ref->usr_priv_key_length);
        SNMP_FREE(ref->usr_priv_key);
    }

    SNMP_FREE(ref);
}                               /* end usm_free_usmStateReference() */

Project: net-snmp
File: snmpusm.c

usm_add_user(struct usmUser *user)
{
    struct usmUser *uptr;
    uptr = usm_add_user_to_list(user, userList);
    if (uptr != NULL)
        userList = uptr;
    return uptr;
}

Project: net-snmp
File: snmp_client.c

snmp_clone_mem(void **dstPtr, const void *srcPtr, unsigned len)
{
    *dstPtr = NULL;
    if (srcPtr) {
        *dstPtr = malloc(len + 1);
        if (!*dstPtr) {
            return 1;
        }
        memmove(*dstPtr, srcPtr, len);
        /*
         * this is for those routines that expect 0-terminated strings!!!
         * someone should rather have called strdup
         */
        ((char *) *dstPtr)[len] = 0;
    }
    return 0;
}

Project: net-snmp
File: snmpusm.c

usm_malloc_usmStateReference(void)
{
    struct usmStateReference *retval;

    retval = calloc(1, sizeof(struct usmStateReference));
    if (retval)
        retval->refcnt = 1;

    return retval;
}                               /* end usm_malloc_usmStateReference() */

Project: net-snmp
File: snmpusm.c

usm_remove_user_from_list(struct usmUser *user,
                          struct usmUser **ppuserList)
{
    int rc = usm_remove_usmUser_from_list(user, ppuserList);
    if (rc != SNMPERR_SUCCESS || NULL == ppuserList)
        return NULL;

    return *ppuserList;
}                               /* end usm_remove_user_from_list() */

Project: net-snmp
File: snmp_client.c

snmp_clone_varbind(netsnmp_variable_list * varlist)
{
    return _copy_varlist(varlist, 0, 10000);    /* skip none, copy all */
}

Project: net-snmp
File: snmpusm.c

usm_get_user(u_char * engineID, size_t engineIDLen, char *name)
{
    DEBUGMSGTL(("usm", "getting user %s\n", name));
    return usm_get_user_from_list(engineID, engineIDLen, name, userList,
                                  1);
}

Project: net-snmp
File: snmp_client.c

snmp_synch_response(netsnmp_session * ss,
                    netsnmp_pdu *pdu, netsnmp_pdu **response)
{
    return snmp_synch_response_cb(ss, pdu, response, snmp_synch_input);
}

Project: net-snmp
File: snmp_client.c

_row_status_state_all_values_createAndWait(netsnmp_state_machine_input *input,
                                           netsnmp_state_machine_step *step)
{
    rowcreate_state       *ctx;
    netsnmp_variable_list *vars, *rs_var;
    int                    rc;

    netsnmp_require_ptr_LRV( input, SNMPERR_GENERR );
    netsnmp_require_ptr_LRV( step, SNMPERR_GENERR );
    netsnmp_require_ptr_LRV( input->input_context, SNMPERR_GENERR );

    ctx = (rowcreate_state *)input->input_context;

    DEBUGMSGT(("row_create:called", "called %s\n", step->name));

    vars = snmp_clone_varbind(ctx->vars);
    netsnmp_require_ptr_LRV(vars, SNMPERR_GENERR);

    /*
     * make sure row stats is createAndWait
     */
    rs_var = _get_vb_num(vars, ctx->row_status_index);
    if (NULL == rs_var) {
        snmp_free_varbind(vars);
        return SNMPERR_GENERR;
    }

    if (*rs_var->val.integer != RS_CREATEANDWAIT)
        *rs_var->val.integer = RS_CREATEANDWAIT;

    /*
     * send set
     */
    rc = netsnmp_query_set( vars, ctx->session );
    if (-2 == rc)
        rc = SNMPERR_ABORT;

    snmp_free_varbind(vars);

    return rc;
}

Project: net-snmp
File: snmp_client.c

_row_status_state_multiple_values_cols(netsnmp_state_machine_input *input,
                                       netsnmp_state_machine_step *step)
{
    rowcreate_state       *ctx;
    netsnmp_variable_list *vars, *var, *last, *row_status;
    int                    rc;

    netsnmp_require_ptr_LRV( input, SNMPERR_GENERR );
    netsnmp_require_ptr_LRV( step, SNMPERR_GENERR );
    netsnmp_require_ptr_LRV( input->input_context, SNMPERR_GENERR );

    ctx = (rowcreate_state *)input->input_context;

    DEBUGMSGT(("row_create:called", "called %s\n", step->name));

    vars = snmp_clone_varbind(ctx->vars);
    netsnmp_require_ptr_LRV(vars, SNMPERR_GENERR);

    row_status = _get_vb_num(vars, ctx->row_status_index);
    if (NULL == row_status) {
        snmp_free_varbind(vars);
        return SNMPERR_GENERR;
    }

    /*
     * remove row status varbind
     */
    if (row_status == vars) {
        vars = row_status->next_variable;
        row_status->next_variable = NULL;
    }
    else {
        for (last=vars, var=last->next_variable;
             var;
             last=var, var = var->next_variable) {
            if (var == row_status) {
                last->next_variable = var->next_variable;
                break;
            }
        }
    }
    snmp_free_var(row_status);

    /*
     * send set
     */
    rc = netsnmp_query_set( vars, ctx->session );
    if (-2 == rc)
        rc = SNMPERR_ABORT;

    snmp_free_varbind(vars);

    return rc;
}

Project: net-snmp
File: snmp_client.c

snmp_clone_var(netsnmp_variable_list * var, netsnmp_variable_list * newvar)
{
    if (!newvar || !var)
        return 1;

    memmove(newvar, var, sizeof(netsnmp_variable_list));
    newvar->next_variable = NULL;
    newvar->name = NULL;
    newvar->val.string = NULL;
    newvar->data = NULL;
    newvar->dataFreeHook = NULL;
    newvar->index = 0;

    /*
     * Clone the object identifier and the value.
     * Allocate memory iff original will not fit into local storage.
     */
    if (snmp_set_var_objid(newvar, var->name, var->name_length))
        return 1;

    /*
     * need a pointer to copy a string value. 
     */
    if (var->val.string) {
        if (var->val.string != &var->buf[0]) {
            if (var->val_len <= sizeof(var->buf))
                newvar->val.string = newvar->buf;
            else {
                newvar->val.string = (u_char *) malloc(var->val_len);
                if (!newvar->val.string)
                    return 1;
            }
            memmove(newvar->val.string, var->val.string, var->val_len);
        } else {                /* fix the pointer to new local store */
            newvar->val.string = newvar->buf;
            /*
             * no need for a memmove, since we copied the whole var
             * struct (and thus var->buf) at the beginning of this function.
             */
        }
    } else {
        newvar->val.string = NULL;
        newvar->val_len = 0;
    }

    return 0;
}

Project: net-snmp
File: snmp_client.c

int netsnmp_query_getnext(netsnmp_variable_list *list,
                          netsnmp_session       *session){
    return _query( list, SNMP_MSG_GETNEXT, session );
}

Project: net-snmp
File: snmpusm.c

usm_session_init(netsnmp_session *in_session, netsnmp_session *session)
{
    char *cp;
    size_t i;
    
    if (in_session->securityAuthProtoLen > 0) {
        session->securityAuthProto =
            snmp_duplicate_objid(in_session->securityAuthProto,
                                 in_session->securityAuthProtoLen);
        if (session->securityAuthProto == NULL) {
            in_session->s_snmp_errno = SNMPERR_MALLOC;
            return SNMPERR_MALLOC;
        }
    } else if (get_default_authtype(&i) != NULL) {
        session->securityAuthProto =
            snmp_duplicate_objid(get_default_authtype(NULL), i);
        session->securityAuthProtoLen = i;
    }

    if (in_session->securityPrivProtoLen > 0) {
        session->securityPrivProto =
            snmp_duplicate_objid(in_session->securityPrivProto,
                                 in_session->securityPrivProtoLen);
        if (session->securityPrivProto == NULL) {
            in_session->s_snmp_errno = SNMPERR_MALLOC;
            return SNMPERR_MALLOC;
        }
    } else if (get_default_privtype(&i) != NULL) {
        session->securityPrivProto =
            snmp_duplicate_objid(get_default_privtype(NULL), i);
        session->securityPrivProtoLen = i;
    }

    if ((in_session->securityAuthKeyLen <= 0) &&
        ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 
				     NETSNMP_DS_LIB_AUTHMASTERKEY)))) {
        size_t buflen = sizeof(session->securityAuthKey);
        u_char *tmpp = session->securityAuthKey;
        session->securityAuthKeyLen = 0;
        /* it will be a hex string */
        if (!snmp_hex_to_binary(&tmpp, &buflen,
                                &session->securityAuthKeyLen, 0, cp)) {
            snmp_set_detail("error parsing authentication master key");
            return SNMP_ERR_GENERR;
        }
    } else if ((in_session->securityAuthKeyLen <= 0) &&
               ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 
                                            NETSNMP_DS_LIB_AUTHPASSPHRASE)) ||
                (cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 
                                            NETSNMP_DS_LIB_PASSPHRASE)))) {
        session->securityAuthKeyLen = USM_AUTH_KU_LEN;
        if (generate_Ku(session->securityAuthProto,
                        session->securityAuthProtoLen,
                        (u_char *) cp, strlen(cp),
                        session->securityAuthKey,
                        &session->securityAuthKeyLen) != SNMPERR_SUCCESS) {
            snmp_set_detail
                ("Error generating a key (Ku) from the supplied authentication pass phrase.");
            return SNMP_ERR_GENERR;
        }
    }

    
    if ((in_session->securityPrivKeyLen <= 0) &&
        ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 
				     NETSNMP_DS_LIB_PRIVMASTERKEY)))) {
        size_t buflen = sizeof(session->securityPrivKey);
        u_char *tmpp = session->securityPrivKey;
        session->securityPrivKeyLen = 0;
        /* it will be a hex string */
        if (!snmp_hex_to_binary(&tmpp, &buflen,
                                &session->securityPrivKeyLen, 0, cp)) {
            snmp_set_detail("error parsing encryption master key");
            return SNMP_ERR_GENERR;
        }
    } else if ((in_session->securityPrivKeyLen <= 0) &&
               ((cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 
                                            NETSNMP_DS_LIB_PRIVPASSPHRASE)) ||
                (cp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 
                                            NETSNMP_DS_LIB_PASSPHRASE)))) {
        session->securityPrivKeyLen = USM_PRIV_KU_LEN;
        if (generate_Ku(session->securityAuthProto,
                        session->securityAuthProtoLen,
                        (u_char *) cp, strlen(cp),
                        session->securityPrivKey,
                        &session->securityPrivKeyLen) != SNMPERR_SUCCESS) {
            snmp_set_detail
                ("Error generating a key (Ku) from the supplied privacy pass phrase.");
            return SNMP_ERR_GENERR;
        }
    }

    return SNMPERR_SUCCESS;
}

Project: net-snmp
File: snmpusm.c

usm_handle_report(struct session_list *slp,
                  netsnmp_transport *transport, netsnmp_session *session,
                  int result, netsnmp_pdu *pdu)
{
    /*
     * handle reportable errors 
     */

    /* this will get in our way */
    usm_free_usmStateReference(pdu->securityStateRef);
    pdu->securityStateRef = NULL;

    switch (result) {
    case SNMPERR_USM_AUTHENTICATIONFAILURE:
    {
        int res = session->s_snmp_errno;
        session->s_snmp_errno = result;
        if (session->callback) {
            session->callback(NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE,
                              session, pdu->reqid, pdu,
                              session->callback_magic);
        }
        session->s_snmp_errno = res;
    }  
    /* fallthrough */
    case SNMPERR_USM_UNKNOWNENGINEID:
    case SNMPERR_USM_UNKNOWNSECURITYNAME:
    case SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL:
    case SNMPERR_USM_NOTINTIMEWINDOW:
    case SNMPERR_USM_DECRYPTIONERROR:

        if (SNMP_CMD_CONFIRMED(pdu->command) ||
            (pdu->command == 0
             && (pdu->flags & SNMP_MSG_FLAG_RPRT_BIT))) {
            netsnmp_pdu    *pdu2;
            int             flags = pdu->flags;

            pdu->flags |= UCD_MSG_FLAG_FORCE_PDU_COPY;
            pdu2 = snmp_clone_pdu(pdu);
            pdu->flags = pdu2->flags = flags;
            snmpv3_make_report(pdu2, result);
            if (0 == snmp_sess_send(slp, pdu2)) {
                snmp_free_pdu(pdu2);
                /*
                 * TODO: indicate error 
                 */
            }
        }
        break;
    }       
}

Project: net-snmp
File: snmpusm.c

shutdown_usm(void)
{
    free_etimelist();
    clear_user_list();
}

Project: net-snmp
File: snmpusm.c

usm_lookup_alg_str(int value, usm_alg_type_t *types)
{
    int i;
    for (i = 0; types[i].label; ++i)
        if (value == types[i].value)
            return types[i].label;

    return NULL;
}

Project: net-snmp
File: snmpusm.c

usm_create_initial_user(const char *name,
                        const oid * authProtocol, size_t authProtocolLen,
                        const oid * privProtocol, size_t privProtocolLen)
{
    struct usmUser *newUser = usm_create_user();
    if (newUser == NULL)
        return NULL;

    if ((newUser->name = strdup(name)) == NULL)
        return usm_free_user(newUser);

    if ((newUser->secName = strdup(name)) == NULL)
        return usm_free_user(newUser);

    if ((newUser->engineID =
         snmpv3_generate_engineID(&newUser->engineIDLen)) == NULL)
        return usm_free_user(newUser);

    if ((newUser->cloneFrom = (oid *) malloc(sizeof(oid) * 2)) == NULL)
        return usm_free_user(newUser);
    newUser->cloneFrom[0] = 0;
    newUser->cloneFrom[1] = 0;
    newUser->cloneFromLen = 2;

    SNMP_FREE(newUser->privProtocol);
    if ((newUser->privProtocol = snmp_duplicate_objid(privProtocol,
                                                      privProtocolLen)) ==
        NULL) {
        return usm_free_user(newUser);
    }
    newUser->privProtocolLen = privProtocolLen;

    SNMP_FREE(newUser->authProtocol);
    if ((newUser->authProtocol = snmp_duplicate_objid(authProtocol,
                                                      authProtocolLen)) ==
        NULL) {
        return usm_free_user(newUser);
    }
    newUser->authProtocolLen = authProtocolLen;

    newUser->userStatus = RS_ACTIVE;
    newUser->userStorageType = ST_READONLY;

    return newUser;
}

Project: net-snmp
File: snmp_client.c

snmp_synch_input(int op,
                 netsnmp_session * session,
                 int reqid, netsnmp_pdu *pdu, void *magic)
{
    struct synch_state *state = (struct synch_state *) magic;
    int             rpt_type;

    if (reqid != state->reqid && pdu && pdu->command != SNMP_MSG_REPORT) {
        DEBUGMSGTL(("snmp_synch", "Unexpected response (ReqID: %d,%d - Cmd %d)\n",
                                   reqid, state->reqid, pdu->command ));
        return 0;
    }

    state->waiting = 0;
    DEBUGMSGTL(("snmp_synch", "Response (ReqID: %d - Cmd %d)\n",
                               reqid, (pdu ? pdu->command : -1)));

    if (op == NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE && pdu) {
        if (pdu->command == SNMP_MSG_REPORT) {
            rpt_type = snmpv3_get_report_type(pdu);
            if (SNMPV3_IGNORE_UNAUTH_REPORTS ||
                rpt_type == SNMPERR_NOT_IN_TIME_WINDOW) {
                state->waiting = 1;
            }
            state->pdu = NULL;
            state->status = STAT_ERROR;
            session->s_snmp_errno = rpt_type;
            SET_SNMP_ERROR(rpt_type);
        } else if (pdu->command == SNMP_MSG_RESPONSE) {
            /*
             * clone the pdu to return to snmp_synch_response 
             */
            state->pdu = snmp_clone_pdu(pdu);
            state->status = STAT_SUCCESS;
            session->s_snmp_errno = SNMPERR_SUCCESS;
        }
        else {
            char msg_buf[50];
            state->status = STAT_ERROR;
            session->s_snmp_errno = SNMPERR_PROTOCOL;
            SET_SNMP_ERROR(SNMPERR_PROTOCOL);
            snprintf(msg_buf, sizeof(msg_buf), "Expected RESPONSE-PDU but got %s-PDU",
                     snmp_pdu_type(pdu->command));
            snmp_set_detail(msg_buf);
            return 0;
        }
    } else if (op == NETSNMP_CALLBACK_OP_TIMED_OUT) {
        state->pdu = NULL;
        state->status = STAT_TIMEOUT;
        session->s_snmp_errno = SNMPERR_TIMEOUT;
        SET_SNMP_ERROR(SNMPERR_TIMEOUT);
    } else if (op == NETSNMP_CALLBACK_OP_SEC_ERROR) {
        state->pdu = NULL;
        /*
         * If we already have an error in status, then leave it alone.
         */
        if (state->status == STAT_SUCCESS) {
            state->status = STAT_ERROR;
            session->s_snmp_errno = SNMPERR_GENERR;
            SET_SNMP_ERROR(SNMPERR_GENERR);
        }
    } else if (op == NETSNMP_CALLBACK_OP_DISCONNECT) {
        state->pdu = NULL;
        state->status = STAT_ERROR;
        session->s_snmp_errno = SNMPERR_ABORT;
        SET_SNMP_ERROR(SNMPERR_ABORT);
    }
    DEBUGMSGTL(("snmp_synch", "status = %d errno = %d\n",
                               state->status, session->s_snmp_errno));

    return 1;
}

Project: net-snmp
File: snmp_client.c

netsnmp_state_machine_run( netsnmp_state_machine_input *input)
{
    netsnmp_state_machine_step *current, *last;

    netsnmp_require_ptr_LRV( input, SNMPERR_GENERR );
    netsnmp_require_ptr_LRV( input->steps, SNMPERR_GENERR );
    last = current = input->steps;

    DEBUGMSGT(("state_machine:run", "starting step: %s\n", current->name));

    while (current) {

        /*
         * log step and check for required data
         */
        DEBUGMSGT(("state_machine:run", "at step: %s\n", current->name));
        if (NULL == current->run) {
            DEBUGMSGT(("state_machine:run", "no run step\n"));
            current->result = last->result;
            break;
        }

        /*
         * run step
         */
        DEBUGMSGT(("state_machine:run", "running step: %s\n", current->name));
        current->result = (*current->run)( input, current );
        ++input->steps_so_far;
        
        /*
         * log result and move to next step
         */
        input->last_run = current;
        DEBUGMSGT(("state_machine:run:result", "step %s returned %d\n",
                   current->name, current->result));
        if (SNMPERR_SUCCESS == current->result)
            current = current->on_success;
        else if (SNMPERR_ABORT == current->result) {
            DEBUGMSGT(("state_machine:run:result", "ABORT from %s\n",
                       current->name));
            break;
        }
        else
            current = current->on_error;
    }

    /*
     * run cleanup
     */
    if ((input->cleanup) && (input->cleanup->run))
        (*input->cleanup->run)( input, input->last_run );

    return input->last_run->result;
}

Project: net-snmp
File: snmp_client.c

snmp_sess_synch_response(void *sessp,
                         netsnmp_pdu *pdu, netsnmp_pdu **response)
{
    netsnmp_session      *ss;
    struct synch_state    lstate, *state;
    snmp_callback         cbsav;
    void                 *cbmagsav;
    int                   numfds, count;
    netsnmp_large_fd_set  fdset;
    struct timeval        timeout, *tvp;
    int                   block;

    ss = snmp_sess_session(sessp);
    if (ss == NULL) {
        return STAT_ERROR;
    }

    memset((void *) &lstate, 0, sizeof(lstate));
    state = &lstate;
    cbsav = ss->callback;
    cbmagsav = ss->callback_magic;
    ss->callback = snmp_synch_input;
    ss->callback_magic = (void *) state;
    netsnmp_large_fd_set_init(&fdset, FD_SETSIZE);

    if (snmp_sess_send(sessp, pdu) == 0) {
        snmp_free_pdu(pdu);
        state->status = STAT_ERROR;
    } else {
        state->waiting = 1;
        state->reqid = pdu->reqid;
    }

    while (state->waiting) {
        numfds = 0;
        NETSNMP_LARGE_FD_ZERO(&fdset);
        block = NETSNMP_SNMPBLOCK;
        tvp = &timeout;
        timerclear(tvp);
        snmp_sess_select_info2_flags(sessp, &numfds, &fdset, tvp, &block,
                                     NETSNMP_SELECT_NOALARMS);
        if (block == 1)
            tvp = NULL;         /* block without timeout */
        count = netsnmp_large_fd_set_select(numfds, &fdset, NULL, NULL, tvp);
        if (count > 0) {
            snmp_sess_read2(sessp, &fdset);
        } else
            switch (count) {
            case 0:
                snmp_sess_timeout(sessp);
                break;
            case -1:
                if (errno == EINTR) {
                    continue;
                } else {
                    snmp_errno = SNMPERR_GENERR;    /*MTCRITICAL_RESOURCE */
                    /*
                     * CAUTION! if another thread closed the socket(s)
                     * waited on here, the session structure was freed.
                     * It would be nice, but we can't rely on the pointer.
                     * ss->s_snmp_errno = SNMPERR_GENERR;
                     * ss->s_errno = errno;
                     */
                    snmp_set_detail(strerror(errno));
                }
                /* FALLTHRU */
            default:
                state->status = STAT_ERROR;
                state->waiting = 0;
            }
    }
    *response = state->pdu;
    ss->callback = cbsav;
    ss->callback_magic = cbmagsav;
    netsnmp_large_fd_set_cleanup(&fdset);
    return state->status;
}

Project: net-snmp
File: snmpusm.c

usm_set_aes_iv(u_char * iv,
               size_t * iv_length,
               u_int net_boots,
               u_int net_time,
               u_char * salt)
{
    /*
     * net_* should be encoded in network byte order.
     */
    int             net_salt_int1, net_salt_int2;
#define PROPER_AES_IV_SIZE 64

    /*
     * Sanity check.
     */
    if (!iv || !iv_length) {
        return -1;
    }

    net_salt_int1 = htonl(salt_integer64_1);
    net_salt_int2 = htonl(salt_integer64_2);

    if ((salt_integer64_2 += 1) == 0)
        salt_integer64_2 += 1;
    
    /* XXX: warning: hard coded proper lengths */
    memcpy(iv, &net_boots, 4);
    memcpy(iv+4, &net_time, 4);
    memcpy(iv+8, &net_salt_int1, 4);
    memcpy(iv+12, &net_salt_int2, 4);

    memcpy(salt, iv+8, 8); /* only copy the needed portion */
    return 0;
}                               /* end usm_set_aes_iv() */

Project: net-snmp
File: snmpusm.c

usm_create_user(void)
{
    struct usmUser *newUser;

    /*
     * create the new user 
     */
    newUser = (struct usmUser *) calloc(1, sizeof(struct usmUser));
    if (newUser == NULL)
        return NULL;

    /*
     * fill the auth/priv protocols 
     */
    if ((newUser->authProtocol =
         snmp_duplicate_objid(usmNoAuthProtocol,
                              sizeof(usmNoAuthProtocol) / sizeof(oid))) ==
        NULL)
        return usm_free_user(newUser);
    newUser->authProtocolLen = sizeof(usmNoAuthProtocol) / sizeof(oid);

    if ((newUser->privProtocol =
         snmp_duplicate_objid(usmNoPrivProtocol,
                              sizeof(usmNoPrivProtocol) / sizeof(oid))) ==
        NULL)
        return usm_free_user(newUser);
    newUser->privProtocolLen = sizeof(usmNoPrivProtocol) / sizeof(oid);

    /*
     * set the storage type to nonvolatile, and the status to ACTIVE 
     */
    newUser->userStorageType = ST_NONVOLATILE;
    newUser->userStatus = RS_ACTIVE;
    return newUser;

}                               /* end usm_clone_user() */

Project: net-snmp
File: snmp_client.c

netsnmp_query_get_default_session_unchecked( void ) {
    DEBUGMSGTL(("iquery", "get default session %p\n", _def_query_session));
    return _def_query_session;
}

Project: net-snmp
File: snmpusm.c

usm_remove_usmUser_from_list(struct usmUser *user, struct usmUser **ppuserList)
{
    struct usmUser *nptr, *pptr;

    /*
     * NULL pointers aren't allowed
     */
    if (ppuserList == NULL)
        ppuserList = &userList;

    if (*ppuserList == NULL)
        return SNMPERR_USM_UNKNOWNSECURITYNAME;

    /*
     * find the user in the list
     */
    for (nptr = *ppuserList, pptr = NULL; nptr != NULL;
         pptr = nptr, nptr = nptr->next) {
        if (nptr == user)
            break;
    }

    if (nptr) {
        /*
         * remove the user from the linked list
         */
        if (pptr) {
            pptr->next = nptr->next;
        }
        if (nptr->next) {
            nptr->next->prev = pptr;
        }
    } else {
        /*
         * user didn't exist
         */
        return SNMPERR_USM_UNKNOWNSECURITYNAME;
    }
    if (nptr == *ppuserList)    /* we're the head of the list, need to change
                                 * * the head to the next user */
        *ppuserList = nptr->next;
    return SNMPERR_SUCCESS;
}                               /* end usm_remove_usmUser_from_list() */

Project: net-snmp
File: snmpusm.c

clear_user_list(void)
{
    struct usmUser *tmp = userList, *next = NULL;

    while (tmp != NULL) {
	next = tmp->next;
	usm_free_user(tmp);
	tmp = next;
    }
    userList = NULL;

}

Project: net-snmp
File: snmpusm.c

usm_create_user_from_session_hook(struct session_list *slp,
                                  netsnmp_session *session)
{
    DEBUGMSGTL(("usm", "potentially bootstrapping the USM table from session data\n"));
    return usm_create_user_from_session(session);
}

Project: net-snmp
File: snmpusm.c

usm_extend_user_kul(struct usmUser *user, u_int privKeyBufSize)
{
    netsnmp_priv_alg_info *pai;

    DEBUGMSGTL(("usm", "extending key\n"));

    if (NULL == user) {
        DEBUGMSGTL(("usm", "null user!\n"));
        return SNMPERR_GENERR;
    }

    pai = sc_get_priv_alg_byoid(user->privProtocol, user->privProtocolLen);
    if (NULL == pai) {
        DEBUGMSGTL(("usm", "privProtocol lookup failed!\n"));
        return SNMPERR_GENERR;
    }

    return netsnmp_extend_kul(pai->proper_length, user->authProtocol,
                              user->authProtocolLen, pai->type, user->engineID,
                              user->engineIDLen, &user->privKey,
                              &user->privKeyLen, privKeyBufSize);
}

Project: net-snmp
File: snmpusm.c

free_enginetime_on_shutdown(int majorid, int minorid, void *serverarg,
			    void *clientarg)
{
    u_char engineID[SNMP_MAX_ENG_SIZE];
    size_t engineID_len = sizeof(engineID);

    DEBUGMSGTL(("snmpv3", "free enginetime callback called\n"));

    engineID_len = snmpv3_get_engineID(engineID, engineID_len);
    if (engineID_len > 0)
	free_enginetime(engineID, engineID_len);
    return 0;
}

Project: net-snmp
File: snmp_client.c

snmp_add_null_var(netsnmp_pdu *pdu, const oid * name, size_t name_length)
{
    return snmp_pdu_add_variable(pdu, name, name_length, ASN_NULL, NULL, 0);
}

Project: net-snmp
File: snmp_client.c

snmp_pdu_create(int command)
{
    netsnmp_pdu    *pdu;

    pdu = (netsnmp_pdu *) calloc(1, sizeof(netsnmp_pdu));
    if (pdu) {
        pdu->version = SNMP_DEFAULT_VERSION;
        pdu->command = command;
        pdu->errstat = SNMP_DEFAULT_ERRSTAT;
        pdu->errindex = SNMP_DEFAULT_ERRINDEX;
        pdu->securityModel = SNMP_DEFAULT_SECMODEL;
        pdu->transport_data = NULL;
        pdu->transport_data_length = 0;
        pdu->securityNameLen = 0;
        pdu->contextNameLen = 0;
        pdu->time = 0;
        pdu->reqid = snmp_get_next_reqid();
        pdu->msgid = snmp_get_next_msgid();
    }
    return pdu;

}

Project: net-snmp
File: snmpusm.c

usm_cloneFrom_user(struct usmUser *from, struct usmUser *to)
{
    to->flags = from->flags;

    /*
     * copy the authProtocol oid row pointer 
     */
    SNMP_FREE(to->authProtocol);

    if ((to->authProtocol =
         snmp_duplicate_objid(from->authProtocol,
                              from->authProtocolLen)) != NULL)
        to->authProtocolLen = from->authProtocolLen;
    else
        to->authProtocolLen = 0;


    /*
     * copy the authKey 
     */
    SNMP_FREE(to->authKey);

    if (from->authKeyLen > 0 &&
        (to->authKey = (u_char *) malloc(from->authKeyLen))
        != NULL) {
        to->authKeyLen = from->authKeyLen;
        memcpy(to->authKey, from->authKey, to->authKeyLen);
    } else {
        to->authKey = NULL;
        to->authKeyLen = 0;
    }

    /*
     * copy the authKeyKu
     */
    SNMP_FREE(to->authKeyKu);

    if (from->authKeyKuLen > 0 &&
        (to->authKeyKu = (u_char *) malloc(from->authKeyKuLen)) != NULL) {
        to->authKeyKuLen = from->authKeyKuLen;
        memcpy(to->authKeyKu, from->authKeyKu, to->authKeyKuLen);
    } else {
        to->authKeyKu = NULL;
        to->authKeyKuLen = 0;
    }


    /*
     * copy the privProtocol oid row pointer 
     */
    SNMP_FREE(to->privProtocol);

    if ((to->privProtocol =
         snmp_duplicate_objid(from->privProtocol,
                              from->privProtocolLen)) != NULL)
        to->privProtocolLen = from->privProtocolLen;
    else
        to->privProtocolLen = 0;

    /*
     * copy the privKey 
     */
    SNMP_FREE(to->privKey);

    if (from->privKeyLen > 0 &&
        (to->privKey = (u_char *) malloc(from->privKeyLen))
        != NULL) {
        to->privKeyLen = from->privKeyLen;
        memcpy(to->privKey, from->privKey, to->privKeyLen);
    } else {
        to->privKey = NULL;
        to->privKeyLen = 0;
    }

    /*
     * copy the privKeyKu
     */
    SNMP_FREE(to->privKeyKu);
    if (from->privKeyKuLen > 0 &&
        (to->privKeyKu = (u_char *) malloc(from->privKeyKuLen)) != NULL) {
        to->privKeyKuLen = from->privKeyKuLen;
        memcpy(to->privKeyKu, from->privKeyKu, to->privKeyKuLen);
    } else {
        to->privKeyKu = NULL;
        to->privKeyKuLen = 0;
    }
    return to;
}

Project: net-snmp
File: snmpusm.c

init_usm_post_config(int majorid, int minorid, void *serverarg,
                     void *clientarg)
{
    size_t          salt_integer_len = sizeof(salt_integer);

    if (sc_random((u_char *) & salt_integer, &salt_integer_len) !=
        SNMPERR_SUCCESS) {
        DEBUGMSGTL(("usm", "sc_random() failed: using time() as salt.\n"));
        salt_integer = (u_int) time(NULL);
    }

#ifdef HAVE_AES
    salt_integer_len = sizeof (salt_integer64_1);
    if (sc_random((u_char *) & salt_integer64_1, &salt_integer_len) !=
        SNMPERR_SUCCESS) {
        DEBUGMSGTL(("usm", "sc_random() failed: using time() as aes1 salt.\n"));
        salt_integer64_1 = (u_int) time(NULL);
    }
    salt_integer_len = sizeof (salt_integer64_1);
    if (sc_random((u_char *) & salt_integer64_2, &salt_integer_len) !=
        SNMPERR_SUCCESS) {
        DEBUGMSGTL(("usm", "sc_random() failed: using time() as aes2 salt.\n"));
        salt_integer64_2 = (u_int) time(NULL);
    }
#endif

#ifndef NETSNMP_DISABLE_MD5
    noNameUser = usm_create_initial_user("", usmHMACMD5AuthProtocol,
                                         OID_LENGTH(usmHMACMD5AuthProtocol),
                                         SNMP_DEFAULT_PRIV_PROTO,
                                         SNMP_DEFAULT_PRIV_PROTOLEN);
#else
    noNameUser = usm_create_initial_user("", usmHMACSHA1AuthProtocol,
                                         OID_LENGTH(usmHMACSHA1AuthProtocol),
                                         SNMP_DEFAULT_PRIV_PROTO,
                                         SNMP_DEFAULT_PRIV_PROTOLEN);
#endif

    if ( noNameUser ) {
        SNMP_FREE(noNameUser->engineID);
        noNameUser->engineIDLen = 0;
    }

    return SNMPERR_SUCCESS;
}                               /* end init_usm_post_config() */

Project: net-snmp
File: snmp_client.c

_row_status_state_all_values_createAndGo(netsnmp_state_machine_input *input,
                                         netsnmp_state_machine_step *step)
{
    rowcreate_state       *ctx;
    netsnmp_variable_list *vars, *rs_var;
    int                    rc;

    netsnmp_require_ptr_LRV( input, SNMPERR_GENERR );
    netsnmp_require_ptr_LRV( step, SNMPERR_GENERR );
    netsnmp_require_ptr_LRV( input->input_context, SNMPERR_GENERR );

    ctx = (rowcreate_state *)input->input_context;

    DEBUGMSGT(("row_create:called", "called %s\n", step->name));

    vars = snmp_clone_varbind(ctx->vars);
    netsnmp_require_ptr_LRV(vars, SNMPERR_GENERR);

    /*
     * make sure row stats is createAndGo
     */
    rs_var = _get_vb_num(vars, ctx->row_status_index + 1);
    if (NULL == rs_var) {
        snmp_free_varbind(vars);
        return SNMPERR_GENERR;
    }

    if (*rs_var->val.integer != RS_CREATEANDGO)
        *rs_var->val.integer = RS_CREATEANDGO;

    /*
     * send set
     */
    rc = netsnmp_query_set( vars, ctx->session );
    if (-2 == rc)
        rc = SNMPERR_ABORT;

    snmp_free_varbind(vars);

    return rc;
}

Project: net-snmp
File: snmpusm.c

usm_parse_config_usmUser(const char *token, char *line)
{
    struct usmUser *uptr;

    uptr = usm_read_user(line);
    if ( uptr)
        usm_add_user(uptr);
}

Project: net-snmp
File: snmpusm.c

usm_check_secLevel_vs_protocols(int level,
                                const oid * authProtocol,
                                u_int authProtocolLen,
                                const oid * privProtocol,
                                u_int privProtocolLen)
{

    if (level == SNMP_SEC_LEVEL_AUTHPRIV
        &&
        (netsnmp_oid_equals
         (privProtocol, privProtocolLen, usmNoPrivProtocol,
          sizeof(usmNoPrivProtocol) / sizeof(oid)) == 0)) {
        DEBUGMSGTL(("usm", "Level: %d\n", level));
        DEBUGMSGTL(("usm", "Auth Protocol: "));
        DEBUGMSGOID(("usm", authProtocol, authProtocolLen));
        DEBUGMSG(("usm", ", Priv Protocol: "));
        DEBUGMSGOID(("usm", privProtocol, privProtocolLen));
        DEBUGMSG(("usm", "\n"));
        return 1;
    }
    if ((level == SNMP_SEC_LEVEL_AUTHPRIV
         || level == SNMP_SEC_LEVEL_AUTHNOPRIV)
        &&
        (netsnmp_oid_equals
         (authProtocol, authProtocolLen, usmNoAuthProtocol,
          sizeof(usmNoAuthProtocol) / sizeof(oid)) == 0)) {
        DEBUGMSGTL(("usm", "Level: %d\n", level));
        DEBUGMSGTL(("usm", "Auth Protocol: "));
        DEBUGMSGOID(("usm", authProtocol, authProtocolLen));
        DEBUGMSG(("usm", ", Priv Protocol: "));
        DEBUGMSGOID(("usm", privProtocol, privProtocolLen));
        DEBUGMSG(("usm", "\n"));
        return 1;
    }

    return 0;

}                               /* end usm_check_secLevel_vs_protocols() */

Project: net-snmp
File: snmpusm.c

init_usm_conf(const char *app)
{
    register_config_handler(app, "usmUser",
                                  usm_parse_config_usmUser, NULL, NULL);
    register_config_handler(app, "createUser",
                                  usm_parse_create_usmUser, NULL,
                                  "username [-e ENGINEID] (MD5|SHA|SHA-512|SHA-384|SHA-256|SHA-224|default) authpassphrase [(DES|AES|default) [privpassphrase]]");

    /*
     * we need to be called back later
     */
    snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
                           usm_store_users, NULL);
}

Project: net-snmp
File: snmp_client.c

_row_status_state_single_value_createAndWait(netsnmp_state_machine_input *input,
                                             netsnmp_state_machine_step *step)
{
    rowcreate_state       *ctx;
    netsnmp_variable_list *var = NULL, *rs_var;
    int32_t                rc, val = RS_CREATEANDWAIT;

    netsnmp_require_ptr_LRV( input, SNMPERR_GENERR );
    netsnmp_require_ptr_LRV( step, SNMPERR_GENERR );
    netsnmp_require_ptr_LRV( input->input_context, SNMPERR_GENERR );

    ctx = (rowcreate_state *)input->input_context;

    DEBUGMSGT(("row_create:called", "called %s\n", step->name));

    rs_var = _get_vb_num(ctx->vars, ctx->row_status_index);
    netsnmp_require_ptr_LRV(rs_var, SNMPERR_GENERR);

    var = snmp_varlist_add_variable(&var, rs_var->name, rs_var->name_length,
                                    rs_var->type, &val, sizeof(val));
    netsnmp_require_ptr_LRV(var, SNMPERR_GENERR);

    /*
     * send set
     */
    rc = netsnmp_query_set( var, ctx->session );
    if (-2 == rc)
        rc = SNMPERR_ABORT;

    snmp_free_varbind(var);

    return rc;
}

Project: net-snmp
File: snmpusm.c

usm_set_salt(u_char * iv,
             size_t * iv_length,
             u_char * priv_salt, size_t priv_salt_length, u_char * msgSalt)
{
    size_t          propersize_salt = BYTESIZE(USM_DES_SALT_LENGTH);
    int             net_boots;
    int             net_salt_int;
    /*
     * net_* should be encoded in network byte order.  XXX  Why?
     */
    int             iindex;


    /*
     * Sanity check.
     */
    if (!iv || !iv_length || !priv_salt || (*iv_length != propersize_salt)
        || (priv_salt_length < propersize_salt)) {
        return -1;
    }


    net_boots = htonl(snmpv3_local_snmpEngineBoots());
    net_salt_int = htonl(salt_integer);

    salt_integer += 1;

    memcpy(iv, &net_boots, propersize_salt / 2);
    memcpy(iv + (propersize_salt / 2), &net_salt_int, propersize_salt / 2);

    if (msgSalt)
        memcpy(msgSalt, iv, propersize_salt);


    /*
     * Turn the salt into an IV: XOR <boots, salt_int> with salt
     * portion of priv_key.
     */
    for (iindex = 0; iindex < (int) propersize_salt; iindex++)
        iv[iindex] ^= priv_salt[iindex];


    return 0;

}                               /* end usm_set_salt() */

Project: net-snmp
File: snmp_client.c

snmp_set_var_typed_integer(netsnmp_variable_list * newvar,
                           u_char type, long val)
{
    newvar->type = type;
    return snmp_set_var_value(newvar, &val, sizeof(long));
}

Project: net-snmp
File: snmp_client.c

snmp_set_var_objid(netsnmp_variable_list * vp,
                   const oid * objid, size_t name_length)
{
    size_t          len = sizeof(oid) * name_length;

    if (vp->name != vp->name_loc && vp->name != NULL) {
        /*
         * Probably previously-allocated "big storage".  Better free it
         * else memory leaks possible.  
         */
        free(vp->name);
    }

    /*
     * use built-in storage for smaller values 
     */
    if (len <= sizeof(vp->name_loc)) {
        vp->name = vp->name_loc;
    } else {
        vp->name = (oid *) malloc(len);
        if (!vp->name)
            return 1;
    }
    if (objid)
        memmove(vp->name, objid, len);
    vp->name_length = name_length;
    return 0;
}

Project: net-snmp
File: snmp_client.c

_row_status_state_cleanup(netsnmp_state_machine_input *input,
                 netsnmp_state_machine_step *step)
{
    rowcreate_state       *ctx;

    netsnmp_require_ptr_LRV( input, SNMPERR_ABORT );
    netsnmp_require_ptr_LRV( step, SNMPERR_ABORT );

    DEBUGMSGT(("row_create:called", "_row_status_state_cleanup, last run step was %s rc %d\n",
               step->name, step->result));

    ctx = (rowcreate_state *)input->input_context;
    if (ctx && ctx->vars)
        snmp_free_varbind( ctx->vars );

    return SNMPERR_SUCCESS;
}

Project: net-snmp
File: snmpusm.c

usm_remove_user(struct usmUser *user)
{
    return usm_remove_user_from_list(user, &userList);
}

Project: net-snmp
File: snmp_client.c

netsnmp_query_get_default_session( void ) {
    static int warning_logged = 0;

    if (! _def_query_session && ! warning_logged) {
        if (! netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID,
                                    NETSNMP_DS_AGENT_INTERNAL_SECNAME)) {
            snmp_log(LOG_WARNING,
                     "iquerySecName has not been configured - internal queries will fail\n");
        } else {
            snmp_log(LOG_WARNING,
                     "default session is not available - internal queries will fail\n");
        }
        warning_logged = 1;
    }

    return netsnmp_query_get_default_session_unchecked();
}

Project: net-snmp
File: snmpusm.c

usm_rgenerate_out_msg(int msgProcModel, /* (UNUSED) */
                      u_char * globalData,      /* IN */
                      /*
                       * points at the msgGlobalData, which is of length given by next 
                       * parameter.  
                       */
                      size_t globalDataLen,     /* IN - Length of msg header data.      */
                      int maxMsgSize,   /* (UNUSED) */
                      int secModel,     /* (UNUSED) */
                      u_char * secEngineID,     /* IN - Pointer snmpEngineID.           */
                      size_t secEngineIDLen,    /* IN - SnmpEngineID length.            */
                      char *secName,    /* IN - Pointer to securityName.        */
                      size_t secNameLen,        /* IN - SecurityName length.            */
                      int secLevel,     /* IN - AuthNoPriv, authPriv etc.       */
                      u_char * scopedPdu,       /* IN */
                      /*
                       * Pointer to scopedPdu will be encrypted by USM if needed
                       * * and written to packet buffer immediately following
                       * * securityParameters, entire msg will be authenticated by
                       * * USM if needed.
                       */
                      size_t scopedPduLen,      /* IN - scopedPdu length. */
                      void *secStateRef,        /* IN */
                      /*
                       * secStateRef, pointer to cached info provided only for
                       * * Response, otherwise NULL.
                       */
                      u_char ** wholeMsg,       /*  IN/OUT  */
                      /*
                       * Points at the pointer to the packet buffer, which might get extended
                       * if necessary via realloc().  
                       */
                      size_t * wholeMsgLen,     /*  IN/OUT  */
                      /*
                       * Length of the entire packet buffer, **not** the length of the
                       * packet.  
                       */
                      size_t * offset   /*  IN/OUT  */
                      /*
                       * Offset from the end of the packet buffer to the start of the packet,
                       * also known as the packet length.  
                       */
    )
{
    size_t          msgAuthParmLen = 0;
    u_int           boots_uint;
    u_int           time_uint;
    long            boots_long;
    long            time_long;

    /*
     * Indirection because secStateRef values override parameters.
     * 
     * None of these are to be free'd - they are either pointing to
     * what's in the secStateRef or to something either in the
     * actual parameter list or the user list.
     */

    char           *theName = NULL;
    u_int           theNameLength = 0;
    u_char         *theEngineID = NULL;
    u_int           theEngineIDLength = 0;
    u_char         *theAuthKey = NULL;
    u_int           theAuthKeyLength = 0;
    const oid      *theAuthProtocol = NULL;
    u_int           theAuthProtocolLength = 0;
    u_char         *thePrivKey = NULL;
    u_int           thePrivKeyLength = 0;
    const oid      *thePrivProtocol = NULL;
    u_int           thePrivProtocolLength = 0;
    int             theSecLevel = 0;    /* No defined const for bad
                                         * value (other then err). */
    size_t          salt_length = 0, save_salt_length = 0;
    u_char          salt[BYTESIZE(USM_MAX_SALT_LENGTH)];
    u_char          authParams[USM_MAX_AUTHSIZE];
    u_char          iv[BYTESIZE(USM_MAX_SALT_LENGTH)];
    size_t          sp_offset = 0, mac_offset = 0;
    int             rc = 0;

    DEBUGMSGTL(("usm", "USM processing has begun (offset %d)\n", (int)*offset));

    if (secStateRef != NULL) {
        /*
         * To hush the compiler for now.  XXX 
         */
        struct usmStateReference *ref
            = (struct usmStateReference *) secStateRef;

        theName = ref->usr_name;
        theNameLength = ref->usr_name_length;
        theEngineID = ref->usr_engine_id;
        theEngineIDLength = ref->usr_engine_id_length;

        if (!theEngineIDLength) {
            theEngineID = secEngineID;
            theEngineIDLength = secEngineIDLen;
        }

        theAuthProtocol = ref->usr_auth_protocol;
        theAuthProtocolLength = ref->usr_auth_protocol_length;
        theAuthKey = ref->usr_auth_key;
        theAuthKeyLength = ref->usr_auth_key_length;
        thePrivProtocol = ref->usr_priv_protocol;
        thePrivProtocolLength = ref->usr_priv_protocol_length;
        thePrivKey = ref->usr_priv_key;
        thePrivKeyLength = ref->usr_priv_key_length;
        theSecLevel = ref->usr_sec_level;
    }

    /*
     * * Identify the user record.
     */
    else {
        struct usmUser *user;

        /*
         * we do allow an unknown user name for
         * unauthenticated requests. 
         */
        if ((user = usm_get_user(secEngineID, secEngineIDLen, secName))
            == NULL && secLevel != SNMP_SEC_LEVEL_NOAUTH) {
            DEBUGMSGTL(("usm", "Unknown User\n"));
            return SNMPERR_USM_UNKNOWNSECURITYNAME;
        }

        theName = secName;
        theNameLength = secNameLen;
        theEngineID = secEngineID;
        theSecLevel = secLevel;
        theEngineIDLength = secEngineIDLen;
        if (user) {
            theAuthProtocol = user->authProtocol;
            theAuthProtocolLength = user->authProtocolLen;
            theAuthKey = user->authKey;
            theAuthKeyLength = user->authKeyLen;
            thePrivProtocol = user->privProtocol;
            thePrivProtocolLength = user->privProtocolLen;
            thePrivKey = user->privKey;
            thePrivKeyLength = user->privKeyLen;
        } else {
            /*
             * unknown users can not do authentication (obviously) 
             */
            theAuthProtocol = usmNoAuthProtocol;
            theAuthProtocolLength =
                sizeof(usmNoAuthProtocol) / sizeof(oid);
            theAuthKey = NULL;
            theAuthKeyLength = 0;
            thePrivProtocol = usmNoPrivProtocol;
            thePrivProtocolLength =
                sizeof(usmNoPrivProtocol) / sizeof(oid);
            thePrivKey = NULL;
            thePrivKeyLength = 0;
        }
    }                           /* endif -- secStateRef==NULL */


    /*
     * From here to the end of the function, avoid reference to
     * secName, secEngineID, secLevel, and associated lengths.
     */


    /*
     * Check to see if the user can use the requested sec services.
     */
    if (usm_check_secLevel_vs_protocols(theSecLevel,
                                        theAuthProtocol,
                                        theAuthProtocolLength,
                                        thePrivProtocol,
                                        thePrivProtocolLength) == 1) {
        DEBUGMSGTL(("usm", "Unsupported Security Level or type (%d)\n",
                    theSecLevel));

        return SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL;
    }


    /*
     * * Retrieve the engine information.
     * *
     * * XXX    No error is declared in the EoP when sending messages to
     * *        unknown engines, processing continues w/ boots/time == (0,0).
     */
    if (get_enginetime(theEngineID, theEngineIDLength,
                       &boots_uint, &time_uint, FALSE) == -1) {
        DEBUGMSGTL(("usm", "%s\n", "Failed to find engine data."));
    }

    boots_long = boots_uint;
    time_long = time_uint;

    if (theSecLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
        /*
         * Initially assume that the ciphertext will end up the same size as
         * the plaintext plus some padding.  Really sc_encrypt ought to be able
         * to grow this for us, a la asn_realloc_rbuild_<type> functions, but
         * this will do for now.  
         */
        u_char         *ciphertext = NULL;
        size_t          ciphertextlen = scopedPduLen + 64;
        int             priv_type = sc_get_privtype(thePrivProtocol,
                                                    thePrivProtocolLength);

        if ((ciphertext = (u_char *) malloc(ciphertextlen)) == NULL) {
            DEBUGMSGTL(("usm",
                        "couldn't malloc %d bytes for encrypted PDU\n",
                        (int)ciphertextlen));
            return SNMPERR_MALLOC;
        }

        /*
         * XXX Hardwired to seek into a 1DES private key!  
         */
#ifdef HAVE_AES
        if (USM_CREATE_USER_PRIV_AES == (priv_type & USM_PRIV_MASK_ALG)) {
            salt_length = BYTESIZE(USM_AES_SALT_LENGTH);
            save_salt_length = BYTESIZE(USM_AES_SALT_LENGTH)/2;
            if (!thePrivKey ||
                usm_set_aes_iv(salt, &salt_length,
                               htonl(boots_uint), htonl(time_uint),
                               iv) == -1) {
                DEBUGMSGTL(("usm", "Can't set AES iv.\n"));
                SNMP_FREE(ciphertext);
                return SNMPERR_USM_GENERICERROR;
            }
        } 
#endif
#ifndef NETSNMP_DISABLE_DES
        if (USM_CREATE_USER_PRIV_DES == (priv_type & USM_PRIV_MASK_ALG)) {
            salt_length = BYTESIZE(USM_DES_SALT_LENGTH);
            save_salt_length = BYTESIZE(USM_DES_SALT_LENGTH);
            if (!thePrivKey || (usm_set_salt(salt, &salt_length,
                                             thePrivKey + 8,
                                             thePrivKeyLength - 8,
                                             iv) == -1)) {
                DEBUGMSGTL(("usm", "Can't set DES-CBC salt.\n"));
                SNMP_FREE(ciphertext);
                return SNMPERR_USM_GENERICERROR;
            }
        }
#endif
#ifdef NETSNMP_ENABLE_TESTING_CODE
        if (debug_is_token_registered("usm/dump") == SNMPERR_SUCCESS) {
            dump_chunk("usm/dump", "This data was encrypted:",
                       scopedPdu, scopedPduLen);
        }
#endif

        if (sc_encrypt(thePrivProtocol, thePrivProtocolLength,
                       thePrivKey, thePrivKeyLength,
                       salt, salt_length,
                       scopedPdu, scopedPduLen,
                       ciphertext, &ciphertextlen) != SNMP_ERR_NOERROR) {
            DEBUGMSGTL(("usm", "encryption error.\n"));
            SNMP_FREE(ciphertext);
            return SNMPERR_USM_ENCRYPTIONERROR;
        }

        /*
         * Write the encrypted scopedPdu back into the packet buffer.  
         */

        *offset = 0;
        rc = asn_realloc_rbuild_string(wholeMsg, wholeMsgLen, offset, 1,
                                       (u_char) (ASN_UNIVERSAL |
                                                 ASN_PRIMITIVE |
                                                 ASN_OCTET_STR),
                                       ciphertext, ciphertextlen);
        if (rc == 0) {
            DEBUGMSGTL(("usm", "Encryption failed.\n"));
            SNMP_FREE(ciphertext);
            return SNMPERR_USM_ENCRYPTIONERROR;
        }

#ifdef NETSNMP_ENABLE_TESTING_CODE
        if (debug_is_token_registered("usm/dump") == SNMPERR_SUCCESS) {
            dump_chunk("usm/dump", "salt + Encrypted form: ", salt,
                       salt_length);
            dump_chunk("usm/dump", "wholeMsg:",
                       (*wholeMsg + *wholeMsgLen - *offset), *offset);
        }
#endif

        DEBUGMSGTL(("usm", "Encryption successful.\n"));
        SNMP_FREE(ciphertext);
    } else {
        /*
         * theSecLevel != SNMP_SEC_LEVEL_AUTHPRIV  
         */
    }

    /*
     * Start encoding the msgSecurityParameters.  
     */

    sp_offset = *offset;

    DEBUGDUMPHEADER("send", "msgPrivacyParameters");
    /*
     * msgPrivacyParameters (warning: assumes DES salt).  
     */
    rc = asn_realloc_rbuild_string(wholeMsg, wholeMsgLen, offset, 1,
                                   (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE
                                             | ASN_OCTET_STR),
                                   iv,
                                   save_salt_length);
    DEBUGINDENTLESS();
    if (rc == 0) {
        DEBUGMSGTL(("usm", "building privParams failed.\n"));
        return SNMPERR_TOO_LONG;
    }

    DEBUGDUMPHEADER("send", "msgAuthenticationParameters");
    /*
     * msgAuthenticationParameters.
     */
    if (theSecLevel == SNMP_SEC_LEVEL_AUTHNOPRIV
        || theSecLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
        memset(authParams, 0, sizeof(authParams));
        msgAuthParmLen =
            sc_get_auth_maclen(sc_get_authtype(theAuthProtocol,
                                               theAuthProtocolLength));
    }

    rc = asn_realloc_rbuild_string(wholeMsg, wholeMsgLen, offset, 1,
                                   (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE
                                             | ASN_OCTET_STR), authParams,
                                   msgAuthParmLen);
    DEBUGINDENTLESS();
    if (rc == 0) {
        DEBUGMSGTL(("usm", "building authParams failed.\n"));
        return SNMPERR_TOO_LONG;
    }

    /*
     * Remember where to put the actual HMAC we calculate later on.  An
     * encoded OCTET STRING of length USM_MD5_AND_SHA_AUTH_LEN has an ASN.1
     * header of length 2, hence the fudge factor.  This works as long as
     * auth lengths stay < 127.
     */
    mac_offset = *offset - 2;

    /*
     * msgUserName.  
     */
    DEBUGDUMPHEADER("send", "msgUserName");
    rc = asn_realloc_rbuild_string(wholeMsg, wholeMsgLen, offset, 1,
                                   (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE
                                             | ASN_OCTET_STR),
                                   (u_char *) theName, theNameLength);
    DEBUGINDENTLESS();
    if (rc == 0) {
        DEBUGMSGTL(("usm", "building authParams failed.\n"));
        return SNMPERR_TOO_LONG;
    }

    /*
     * msgAuthoritativeEngineTime.  
     */
    DEBUGDUMPHEADER("send", "msgAuthoritativeEngineTime");
    rc = asn_realloc_rbuild_int(wholeMsg, wholeMsgLen, offset, 1,
                                (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
                                          ASN_INTEGER), &time_long,
                                sizeof(long));
    DEBUGINDENTLESS();
    if (rc == 0) {
        DEBUGMSGTL(("usm",
                    "building msgAuthoritativeEngineTime failed.\n"));
        return SNMPERR_TOO_LONG;
    }

    /*
     * msgAuthoritativeEngineBoots.  
     */
    DEBUGDUMPHEADER("send", "msgAuthoritativeEngineBoots");
    rc = asn_realloc_rbuild_int(wholeMsg, wholeMsgLen, offset, 1,
                                (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
                                          ASN_INTEGER), &boots_long,
                                sizeof(long));
    DEBUGINDENTLESS();
    if (rc == 0) {
        DEBUGMSGTL(("usm",
                    "building msgAuthoritativeEngineBoots failed.\n"));
        return SNMPERR_TOO_LONG;
    }

    DEBUGDUMPHEADER("send", "msgAuthoritativeEngineID");
    rc = asn_realloc_rbuild_string(wholeMsg, wholeMsgLen, offset, 1,
                                   (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE
                                             | ASN_OCTET_STR), theEngineID,
                                   theEngineIDLength);
    DEBUGINDENTLESS();
    if (rc == 0) {
        DEBUGMSGTL(("usm", "building msgAuthoritativeEngineID failed.\n"));
        return SNMPERR_TOO_LONG;
    }

    /*
     * USM msgSecurityParameters sequence header  
     */
    rc = asn_realloc_rbuild_sequence(wholeMsg, wholeMsgLen, offset, 1,
                                     (u_char) (ASN_SEQUENCE |
                                               ASN_CONSTRUCTOR),
                                     *offset - sp_offset);
    if (rc == 0) {
        DEBUGMSGTL(("usm", "building usm security parameters failed.\n"));
        return SNMPERR_TOO_LONG;
    }

    /*
     * msgSecurityParameters OCTET STRING wrapper.  
     */
    rc = asn_realloc_rbuild_header(wholeMsg, wholeMsgLen, offset, 1,
                                   (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE
                                             | ASN_OCTET_STR),
                                   *offset - sp_offset);

    if (rc == 0) {
        DEBUGMSGTL(("usm", "building msgSecurityParameters failed.\n"));
        return SNMPERR_TOO_LONG;
    }

    /*
     * Copy in the msgGlobalData and msgVersion.  
     */
    while ((*wholeMsgLen - *offset) < globalDataLen) {
        if (!asn_realloc(wholeMsg, wholeMsgLen)) {
            DEBUGMSGTL(("usm", "building global data failed.\n"));
            return SNMPERR_TOO_LONG;
        }
    }

    *offset += globalDataLen;
    memcpy(*wholeMsg + *wholeMsgLen - *offset, globalData, globalDataLen);

    /*
     * Total packet sequence.  
     */
    rc = asn_realloc_rbuild_sequence(wholeMsg, wholeMsgLen, offset, 1,
                                     (u_char) (ASN_SEQUENCE |
                                               ASN_CONSTRUCTOR), *offset);
    if (rc == 0) {
        DEBUGMSGTL(("usm", "building master packet sequence failed.\n"));
        return SNMPERR_TOO_LONG;
    }

    /*
     * Now consider / do authentication.  
     */

    if (theSecLevel == SNMP_SEC_LEVEL_AUTHNOPRIV ||
        theSecLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
        size_t          temp_sig_len = msgAuthParmLen;
        u_char         *temp_sig = (u_char *) malloc(temp_sig_len);
        u_char         *proto_msg = *wholeMsg + *wholeMsgLen - *offset;
        size_t          proto_msg_len = *offset;


        if (temp_sig == NULL) {
            DEBUGMSGTL(("usm", "Out of memory.\n"));
            return SNMPERR_USM_GENERICERROR;
        }

        if (sc_generate_keyed_hash(theAuthProtocol, theAuthProtocolLength,
                                   theAuthKey, theAuthKeyLength,
                                   proto_msg, proto_msg_len,
                                   temp_sig, &temp_sig_len)
            != SNMP_ERR_NOERROR) {
            SNMP_FREE(temp_sig);
            DEBUGMSGTL(("usm", "Signing failed.\n"));
            return SNMPERR_USM_AUTHENTICATIONFAILURE;
        }

        if (temp_sig_len != msgAuthParmLen) {
            SNMP_FREE(temp_sig);
            DEBUGMSGTL(("usm", "Signing lengths failed.\n"));
            return SNMPERR_USM_AUTHENTICATIONFAILURE;
        }

        memcpy(*wholeMsg + *wholeMsgLen - mac_offset, temp_sig,
               msgAuthParmLen);
        SNMP_FREE(temp_sig);
    }
    /*
     * endif -- create keyed hash 
     */
    DEBUGMSGTL(("usm", "USM processing completed.\n"));
    return SNMPERR_SUCCESS;
}                               /* end usm_rgenerate_out_msg() */

Project: net-snmp
File: snmp_client.c

int netsnmp_query_get(netsnmp_variable_list *list,
                      netsnmp_session       *session){
    return _query( list, SNMP_MSG_GET, session );
}

Project: net-snmp
File: snmpusm.c

emergency_print(u_char * field, u_int length)
{
    int             iindex;
    int             start = 0;
    int             stop = 25;

    while (start < stop) {
        for (iindex = start; iindex < stop; iindex++)
            printf("%02X ", field[iindex]);

        printf("\n");
        start = stop;
        stop = stop + 25 < length ? stop + 25 : length;
    }
    fflush(0);

}                               /* end emergency_print() */

Project: net-snmp
File: snmp_client.c

find_varbind_of_type(netsnmp_variable_list * var_ptr, u_char type)
{
    for (; var_ptr != NULL && var_ptr->type != type;
         var_ptr = var_ptr->next_variable);

    return var_ptr;
}

Project: net-snmp
File: snmp_client.c

netsnmp_row_create(netsnmp_session *sess, netsnmp_variable_list *vars,
                   int row_status_index)
{
    netsnmp_state_machine_step rc_cleanup =
        { "row_create_cleanup", 0, _row_status_state_cleanup,
          0, NULL, NULL, 0, NULL };
    netsnmp_state_machine_step rc_activate =
        { "row_create_activate", 0, _row_status_state_activate,
          0, NULL, NULL, 0, NULL };
    netsnmp_state_machine_step rc_sv_cols =
        { "row_create_single_value_cols", 0,
          _row_status_state_single_value_cols, 0, &rc_activate,NULL, 0, NULL };
    netsnmp_state_machine_step rc_mv_cols =
        { "row_create_multiple_values_cols", 0,
          _row_status_state_multiple_values_cols, 0, &rc_activate, &rc_sv_cols,
          0, NULL };
    netsnmp_state_machine_step rc_sv_caw =
        { "row_create_single_value_createAndWait", 0,
          _row_status_state_single_value_createAndWait, 0, &rc_mv_cols, NULL,
          0, NULL };
    netsnmp_state_machine_step rc_av_caw =
        { "row_create_all_values_createAndWait", 0,
          _row_status_state_all_values_createAndWait, 0, &rc_activate,
          &rc_sv_caw, 0, NULL };
    netsnmp_state_machine_step rc_av_cag =
        { "row_create_all_values_createAndGo", 0,
          _row_status_state_all_values_createAndGo, 0, NULL, &rc_av_caw, 0,
          NULL };

    netsnmp_state_machine_input sm_input = { "row_create_machine", 0,
                                             &rc_av_cag, &rc_cleanup };
    rowcreate_state state;

    netsnmp_require_ptr_LRV( sess, SNMPERR_GENERR);
    netsnmp_require_ptr_LRV( vars, SNMPERR_GENERR);

    state.session = sess;
    state.vars = vars;

    state.row_status_index = row_status_index;
    sm_input.input_context = &state;

    netsnmp_state_machine_run( &sm_input);

    return SNMPERR_SUCCESS;
}

Project: net-snmp
File: snmpusm.c

usm_generate_out_msg(int msgProcModel,  /* (UNUSED) */
                     u_char * globalData,       /* IN */
                     /*
                      * Pointer to msg header data will point to the beginning
                      * * of the entire packet buffer to be transmitted on wire,
                      * * memory will be contiguous with secParams, typically
                      * * this pointer will be passed back as beginning of
                      * * wholeMsg below.  asn seq. length is updated w/ new length.
                      * *
                      * * While this points to a buffer that should be big enough
                      * * for the whole message, only the first two parts
                      * * of the message are completed, namely SNMPv3Message and
                      * * HeaderData.  globalDataLen (next parameter) represents
                      * * the length of these two completed parts.
                      */
                     size_t globalDataLen,      /* IN - Length of msg header data.      */
                     int maxMsgSize,    /* (UNUSED) */
                     int secModel,      /* (UNUSED) */
                     u_char * secEngineID,      /* IN - Pointer snmpEngineID.           */
                     size_t secEngineIDLen,     /* IN - SnmpEngineID length.            */
                     char *secName,     /* IN - Pointer to securityName.        */
                     size_t secNameLen, /* IN - SecurityName length.            */
                     int secLevel,      /* IN - AuthNoPriv, authPriv etc.       */
                     u_char * scopedPdu,        /* IN */
                     /*
                      * Pointer to scopedPdu will be encrypted by USM if needed
                      * * and written to packet buffer immediately following
                      * * securityParameters, entire msg will be authenticated by
                      * * USM if needed.
                      */
                     size_t scopedPduLen,       /* IN - scopedPdu length. */
                     void *secStateRef, /* IN */
                     /*
                      * secStateRef, pointer to cached info provided only for
                      * * Response, otherwise NULL.
                      */
                     u_char * secParams,        /* OUT */
                     /*
                      * BER encoded securityParameters pointer to offset within
                      * * packet buffer where secParams should be written, the
                      * * entire BER encoded OCTET STRING (including header) is
                      * * written here by USM secParams = globalData +
                      * * globalDataLen.
                      */
                     size_t * secParamsLen,     /* IN/OUT - Len available, len returned. */
                     u_char ** wholeMsg,        /* OUT */
                     /*
                      * Complete authenticated/encrypted message - typically
                      * * the pointer to start of packet buffer provided in
                      * * globalData is returned here, could also be a separate
                      * * buffer.
                      */
                     size_t * wholeMsgLen)
{                               /* IN/OUT - Len available, len returned. */
    size_t          otstlen;
    size_t          seq_len;
    size_t          msgAuthParmLen;
    size_t          msgPrivParmLen;
    size_t          msgSecParmLen;
    size_t          authParamsOffset;
    size_t          privParamsOffset;
    size_t          datalen;
    size_t          dataOffset;
    size_t          theTotalLength;

    u_char         *ptr;
    size_t          ptr_len;
    size_t          remaining;
    size_t          offSet;
    u_int           boots_uint;
    u_int           time_uint;
    long            boots_long;
    long            time_long;

    /*
     * Indirection because secStateRef values override parameters.
     * 
     * None of these are to be free'd - they are either pointing to
     * what's in the secStateRef or to something either in the
     * actual prarmeter list or the user list.
     */

    char           *theName = NULL;
    u_int           theNameLength = 0;
    u_char         *theEngineID = NULL;
    u_int           theEngineIDLength = 0;
    u_char         *theAuthKey = NULL;
    u_int           theAuthKeyLength = 0;
    const oid      *theAuthProtocol = NULL;
    u_int           theAuthProtocolLength = 0;
    u_char         *thePrivKey = NULL;
    u_int           thePrivKeyLength = 0;
    const oid      *thePrivProtocol = NULL;
    u_int           thePrivProtocolLength = 0;
    int             theSecLevel = 0;    /* No defined const for bad
                                         * value (other then err).
                                         */

    DEBUGMSGTL(("usm", "USM processing has begun.\n"));

    if (secStateRef != NULL) {
        /*
         * To hush the compiler for now.  XXX 
         */
        struct usmStateReference *ref
            = (struct usmStateReference *) secStateRef;

        theName = ref->usr_name;
        theNameLength = ref->usr_name_length;
        theEngineID = ref->usr_engine_id;
        theEngineIDLength = ref->usr_engine_id_length;

        if (!theEngineIDLength) {
            theEngineID = secEngineID;
            theEngineIDLength = secEngineIDLen;
        }

        theAuthProtocol = ref->usr_auth_protocol;
        theAuthProtocolLength = ref->usr_auth_protocol_length;
        theAuthKey = ref->usr_auth_key;
        theAuthKeyLength = ref->usr_auth_key_length;
        thePrivProtocol = ref->usr_priv_protocol;
        thePrivProtocolLength = ref->usr_priv_protocol_length;
        thePrivKey = ref->usr_priv_key;
        thePrivKeyLength = ref->usr_priv_key_length;
        theSecLevel = ref->usr_sec_level;
    }

    /*
     * Identify the user record.
     */
    else {
        struct usmUser *user;

        /*
         * we do allow an unknown user name for
         * unauthenticated requests. 
         */
        if ((user = usm_get_user(secEngineID, secEngineIDLen, secName))
            == NULL && secLevel != SNMP_SEC_LEVEL_NOAUTH) {
            DEBUGMSGTL(("usm", "Unknown User(%s)\n", secName));
            return SNMPERR_USM_UNKNOWNSECURITYNAME;
        }

        theName = secName;
        theNameLength = secNameLen;
        theEngineID = secEngineID;
        theSecLevel = secLevel;
        theEngineIDLength = secEngineIDLen;
        if (user) {
            theAuthProtocol = user->authProtocol;
            theAuthProtocolLength = user->authProtocolLen;
            theAuthKey = user->authKey;
            theAuthKeyLength = user->authKeyLen;
            thePrivProtocol = user->privProtocol;
            thePrivProtocolLength = user->privProtocolLen;
            thePrivKey = user->privKey;
            thePrivKeyLength = user->privKeyLen;
        } else {
            /*
             * unknown users can not do authentication (obviously) 
             */
            theAuthProtocol = usmNoAuthProtocol;
            theAuthProtocolLength =
                sizeof(usmNoAuthProtocol) / sizeof(oid);
            theAuthKey = NULL;
            theAuthKeyLength = 0;
            thePrivProtocol = usmNoPrivProtocol;
            thePrivProtocolLength =
                sizeof(usmNoPrivProtocol) / sizeof(oid);
            thePrivKey = NULL;
            thePrivKeyLength = 0;
        }
    }                           /* endif -- secStateRef==NULL */


    /*
     * From here to the end of the function, avoid reference to
     * secName, secEngineID, secLevel, and associated lengths.
     */


    /*
     * Check to see if the user can use the requested sec services.
     */
    if (usm_check_secLevel_vs_protocols(theSecLevel,
                                        theAuthProtocol,
                                        theAuthProtocolLength,
                                        thePrivProtocol,
                                        thePrivProtocolLength) == 1) {
        DEBUGMSGTL(("usm", "Unsupported Security Level (%d)\n",
                    theSecLevel));
        return SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL;
    }


    /*
     * Retrieve the engine information.
     *
     * XXX  No error is declared in the EoP when sending messages to
     *      unknown engines, processing continues w/ boots/time == (0,0).
     */
    if (get_enginetime(theEngineID, theEngineIDLength,
                       &boots_uint, &time_uint, FALSE) == -1) {
        DEBUGMSGTL(("usm", "%s\n", "Failed to find engine data."));
    }

    boots_long = boots_uint;
    time_long = time_uint;


    /*
     * Set up the Offsets.
     */
    if (usm_calc_offsets(globalDataLen, theSecLevel, theEngineIDLength,
                         theNameLength, scopedPduLen, boots_long,
                         time_long, &theTotalLength, &authParamsOffset,
                         &privParamsOffset, &dataOffset, &datalen,
                         &msgAuthParmLen, &msgPrivParmLen, &otstlen,
                         &seq_len, &msgSecParmLen) == -1) {
        DEBUGMSGTL(("usm", "Failed calculating offsets.\n"));
        return SNMPERR_USM_GENERICERROR;
    }

    /*
     * So, we have the offsets for the three parts that need to be
     * determined, and an overall length.  Now we need to make
     * sure all of this would fit in the outgoing buffer, and
     * whether or not we need to make a new buffer, etc.
     */


    /*
     * Set wholeMsg as a pointer to globalData.  Sanity check for
     * the proper size.
     * 
     * Mark workspace in the message with bytes of all 1's to make it
     * easier to find mistakes in raw message dumps.
     */
    ptr = *wholeMsg = globalData;
    if (theTotalLength > *wholeMsgLen) {
        DEBUGMSGTL(("usm", "Message won't fit in buffer.\n"));
        return SNMPERR_USM_GENERICERROR;
    }

    ptr_len = *wholeMsgLen = theTotalLength;

#ifdef NETSNMP_ENABLE_TESTING_CODE
    memset(&ptr[globalDataLen], 0xFF, theTotalLength - globalDataLen);
#endif                          /* NETSNMP_ENABLE_TESTING_CODE */

    /*
     * Do the encryption.
     */
    if (theSecLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
        size_t          encrypted_length = theTotalLength - dataOffset;
        size_t          salt_length = BYTESIZE(USM_MAX_SALT_LENGTH);
        u_char          salt[BYTESIZE(USM_MAX_SALT_LENGTH)];
        int             priv_type = sc_get_privtype(thePrivProtocol,
                                                    thePrivProtocolLength);
#ifdef HAVE_AES
        if (USM_CREATE_USER_PRIV_AES == (priv_type & USM_PRIV_MASK_ALG)) {
            if (!thePrivKey ||
                usm_set_aes_iv(salt, &salt_length,
                               htonl(boots_uint), htonl(time_uint),
                               &ptr[privParamsOffset]) == -1) {
                DEBUGMSGTL(("usm", "Can't set AES iv.\n"));
                return SNMPERR_USM_GENERICERROR;
            }
        }
#endif
#ifndef NETSNMP_DISABLE_DES
        /*
         * XXX  Hardwired to seek into a 1DES private key!
         */
        if (USM_CREATE_USER_PRIV_DES == (priv_type & USM_PRIV_MASK_ALG)) {
            if (!thePrivKey ||
                (usm_set_salt(salt, &salt_length,
                              thePrivKey + 8, thePrivKeyLength - 8,
                              &ptr[privParamsOffset])
                 == -1)) {
                DEBUGMSGTL(("usm", "Can't set DES-CBC salt.\n"));
                return SNMPERR_USM_GENERICERROR;
            }
        }
#endif

        if (sc_encrypt(thePrivProtocol, thePrivProtocolLength,
                       thePrivKey, thePrivKeyLength,
                       salt, salt_length,
                       scopedPdu, scopedPduLen,
                       &ptr[dataOffset], &encrypted_length)
            != SNMP_ERR_NOERROR) {
            DEBUGMSGTL(("usm", "encryption error.\n"));
            return SNMPERR_USM_ENCRYPTIONERROR;
        }
#ifdef NETSNMP_ENABLE_TESTING_CODE
        if (debug_is_token_registered("usm/dump") == SNMPERR_SUCCESS) {
            dump_chunk("usm/dump", "This data was encrypted:",
                       scopedPdu, scopedPduLen);
            dump_chunk("usm/dump", "salt + Encrypted form:",
                       salt, salt_length);
            dump_chunk("usm/dump", NULL,
                       &ptr[dataOffset], encrypted_length);
            dump_chunk("usm/dump", "*wholeMsg:",
                       *wholeMsg, theTotalLength);
        }
#endif


        ptr = *wholeMsg;
        ptr_len = *wholeMsgLen = theTotalLength;


        /*
         * XXX  Sanity check for salt length should be moved up
         *      under usm_calc_offsets() or tossed.
         */
        if ((encrypted_length != (theTotalLength - dataOffset))
            || (salt_length != msgPrivParmLen)) {
            DEBUGMSGTL(("usm", "encryption length error.\n"));
            return SNMPERR_USM_ENCRYPTIONERROR;
        }

        DEBUGMSGTL(("usm", "Encryption successful.\n"));
    }

    /*
     * No encryption for you!
     */
    else {
        memcpy(&ptr[dataOffset], scopedPdu, scopedPduLen);
    }



    /*
     * Start filling in the other fields (in prep for authentication).
     * 
     * offSet is an octet string header, which is different from all
     * the other headers.
     */
    remaining = ptr_len - globalDataLen;

    offSet = ptr_len - remaining;
    asn_build_header(&ptr[offSet], &remaining,
                     (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
                               ASN_OCTET_STR), otstlen);

    offSet = ptr_len - remaining;
    asn_build_sequence(&ptr[offSet], &remaining,
                       (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), seq_len);

    offSet = ptr_len - remaining;
    DEBUGDUMPHEADER("send", "msgAuthoritativeEngineID");
    asn_build_string(&ptr[offSet], &remaining,
                     (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
                               ASN_OCTET_STR), theEngineID,
                     theEngineIDLength);
    DEBUGINDENTLESS();

    offSet = ptr_len - remaining;
    DEBUGDUMPHEADER("send", "msgAuthoritativeEngineBoots");
    asn_build_int(&ptr[offSet], &remaining,
                  (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
                  &boots_long, sizeof(long));
    DEBUGINDENTLESS();

    offSet = ptr_len - remaining;
    DEBUGDUMPHEADER("send", "msgAuthoritativeEngineTime");
    asn_build_int(&ptr[offSet], &remaining,
                  (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
                  &time_long, sizeof(long));
    DEBUGINDENTLESS();

    offSet = ptr_len - remaining;
    DEBUGDUMPHEADER("send", "msgUserName");
    asn_build_string(&ptr[offSet], &remaining,
                     (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
                               ASN_OCTET_STR), (u_char *) theName,
                     theNameLength);
    DEBUGINDENTLESS();


    /*
     * Note: if there is no authentication being done,
     * msgAuthParmLen is 0, and there is no effect (other than
     * inserting a zero-length header) of the following
     * statements.
     */

    offSet = ptr_len - remaining;
    asn_build_header(&ptr[offSet],
                     &remaining,
                     (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
                               ASN_OCTET_STR), msgAuthParmLen);

    if (theSecLevel == SNMP_SEC_LEVEL_AUTHNOPRIV
        || theSecLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
        offSet = ptr_len - remaining;
        memset(&ptr[offSet], 0, msgAuthParmLen);
    }

    remaining -= msgAuthParmLen;


    /*
     * Note: if there is no encryption being done, msgPrivParmLen
     * is 0, and there is no effect (other than inserting a
     * zero-length header) of the following statements.
     */

    offSet = ptr_len - remaining;
    asn_build_header(&ptr[offSet],
                     &remaining,
                     (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
                               ASN_OCTET_STR), msgPrivParmLen);

    remaining -= msgPrivParmLen;        /* Skipping the IV already there. */


    /*
     * For privacy, need to add the octet string header for it.
     */
    if (theSecLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
        offSet = ptr_len - remaining;
        asn_build_header(&ptr[offSet],
                         &remaining,
                         (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
                                   ASN_OCTET_STR),
                         theTotalLength - dataOffset);
    }


    /*
     * Adjust overall length and store it as the first SEQ length
     * of the SNMPv3Message.
     *
     * FIX  4 is a magic number!
     */
    remaining = theTotalLength;
    asn_build_sequence(ptr, &remaining,
                       (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
                       theTotalLength - 4);


    /*
     * Now, time to consider / do authentication.
     */
    if (theSecLevel == SNMP_SEC_LEVEL_AUTHNOPRIV
        || theSecLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
        size_t          temp_sig_len = msgAuthParmLen;
        u_char         *temp_sig = (u_char *) malloc(temp_sig_len);

        if (temp_sig == NULL) {
            DEBUGMSGTL(("usm", "Out of memory.\n"));
            return SNMPERR_USM_GENERICERROR;
        }

        if (sc_generate_keyed_hash(theAuthProtocol, theAuthProtocolLength,
                                   theAuthKey, theAuthKeyLength,
                                   ptr, ptr_len, temp_sig, &temp_sig_len)
            != SNMP_ERR_NOERROR) {
            /*
             * FIX temp_sig_len defined?!
             */
            SNMP_ZERO(temp_sig, temp_sig_len);
            SNMP_FREE(temp_sig);
            DEBUGMSGTL(("usm", "Signing failed.\n"));
            return SNMPERR_USM_AUTHENTICATIONFAILURE;
        }

        if (temp_sig_len != msgAuthParmLen) {
            SNMP_ZERO(temp_sig, temp_sig_len);
            SNMP_FREE(temp_sig);
            DEBUGMSGTL(("usm", "Signing lengths failed.\n"));
            return SNMPERR_USM_AUTHENTICATIONFAILURE;
        }

        memcpy(&ptr[authParamsOffset], temp_sig, msgAuthParmLen);

        SNMP_ZERO(temp_sig, temp_sig_len);
        SNMP_FREE(temp_sig);

    }

    /*
     * endif -- create keyed hash 
     */

    DEBUGMSGTL(("usm", "USM processing completed.\n"));

    return SNMPERR_SUCCESS;

}                               /* end usm_generate_out_msg() */

Project: net-snmp
File: snmpusm.c

snmpv3_authtype_conf(const char *word, char *cptr)
{
    int auth_type = usm_lookup_auth_type(cptr);
    if (auth_type < 0)
        config_perror("Unknown authentication type");
    defaultAuthType = sc_get_auth_oid(auth_type, &defaultAuthTypeLen);
    DEBUGMSGTL(("snmpv3", "set default authentication type: %s\n", cptr));
}

Project: net-snmp
File: snmpusm.c

deinit_usm_post_config(int majorid, int minorid, void *serverarg,
		       void *clientarg)
{
    if (usm_free_user(noNameUser) != NULL) {
	DEBUGMSGTL(("deinit_usm_post_config", "could not free initial user\n"));
	return SNMPERR_GENERR;
    }
    noNameUser = NULL;

    DEBUGMSGTL(("deinit_usm_post_config", "initial user removed\n"));
    return SNMPERR_SUCCESS;
}                               /* end deinit_usm_post_config() */

Project: net-snmp
File: snmp_client.c

snmp_fix_pdu(netsnmp_pdu *pdu, int command)
{
    netsnmp_pdu    *newpdu;

    if ((pdu->command != SNMP_MSG_RESPONSE)
        || (pdu->errstat == SNMP_ERR_NOERROR)
        || (NULL == pdu->variables)
        || (pdu->errindex > (int)snmp_varbind_len(pdu))
        || (pdu->errindex <= 0)) {
        return NULL;            /* pre-condition tests fail */
    }

    newpdu = _clone_pdu(pdu, 1);        /* copies all except errored variable */
    if (!newpdu)
        return NULL;
    if (!newpdu->variables) {
        snmp_free_pdu(newpdu);
        return NULL;            /* no variables. "should not happen" */
    }
    newpdu->command = command;
    newpdu->reqid = snmp_get_next_reqid();
    newpdu->msgid = snmp_get_next_msgid();
    newpdu->errstat = SNMP_DEFAULT_ERRSTAT;
    newpdu->errindex = SNMP_DEFAULT_ERRINDEX;

    return newpdu;
}

Project: net-snmp
File: snmp_client.c

snmp_reset_var_buffers(netsnmp_variable_list * var)
{
    while (var) {
        if (var->name != var->name_loc) {
            if(NULL != var->name)
                free(var->name);
            var->name = var->name_loc;
            var->name_length = 0;
        }
        if (var->val.string != var->buf) {
            if (NULL != var->val.string)
                free(var->val.string);
            var->val.string = var->buf;
            var->val_len = 0;
        }
        var = var->next_variable;
    }
}

Project: net-snmp
File: snmpusm.c

usm_free_user(struct usmUser *user)
{
    if (user == NULL)
        return NULL;

    SNMP_FREE(user->engineID);
    SNMP_FREE(user->name);
    SNMP_FREE(user->secName);
    SNMP_FREE(user->cloneFrom);
    SNMP_FREE(user->userPublicString);
    SNMP_FREE(user->authProtocol);
    SNMP_FREE(user->privProtocol);

    if (user->authKey != NULL) {
        SNMP_ZERO(user->authKey, user->authKeyLen);
        SNMP_FREE(user->authKey);
    }

    if (user->privKey != NULL) {
        SNMP_ZERO(user->privKey, user->privKeyLen);
        SNMP_FREE(user->privKey);
    }

    if (user->authKeyKu != NULL) {
        SNMP_ZERO(user->authKeyKu, user->authKeyKuLen);
        SNMP_FREE(user->authKeyKu);
    }

    if (user->privKeyKu != NULL) {
        SNMP_ZERO(user->privKeyKu, user->privKeyKuLen);
        SNMP_FREE(user->privKeyKu);
    }


    /*
     * FIX  Why not put this check *first?*
     */
    if (user->prev != NULL) {   /* ack, this shouldn't happen */
        user->prev->next = user->next;
    }
    if (user->next != NULL) {
        user->next->prev = user->prev;
        if (user->prev != NULL) /* ack this is really bad, because it means
                                 * * we'll loose the head of some structure tree */
            DEBUGMSGTL(("usm",
                        "Severe: Asked to free the head of a usmUser tree somewhere."));
    }


    SNMP_ZERO(user, sizeof(*user));
    SNMP_FREE(user);

    return NULL;                /* for convenience to returns from calling functions */

}                               /* end usm_free_user() */

Project: net-snmp
File: snmpusm.c

usm_check_and_update_timeliness(u_char * secEngineID,
                                size_t secEngineIDLen,
                                u_int boots_uint,
                                u_int time_uint, int *error)
{
    u_char          myID[USM_MAX_ID_LENGTH];
    u_long          myIDLength =
        snmpv3_get_engineID(myID, USM_MAX_ID_LENGTH);
    u_int           myBoots;
    u_int           myTime;



    if ((myIDLength > USM_MAX_ID_LENGTH) || (myIDLength == 0)) {
        /*
         * We're probably already screwed...buffer overwrite.  XXX? 
         */
        DEBUGMSGTL(("usm", "Buffer overflow.\n"));
        *error = SNMPERR_USM_GENERICERROR;
        return -1;
    }

    myBoots = snmpv3_local_snmpEngineBoots();
    myTime = snmpv3_local_snmpEngineTime();


    /*
     * IF the time involved is local
     *     Make sure  message is inside the time window 
     * ELSE 
     *      IF boots is higher or boots is the same and time is higher
     *              remember this new data
     *      ELSE
     *              IF !(boots same and time within USM_TIME_WINDOW secs)
     *                      Message is too old 
     *              ELSE    
     *                      Message is ok, but don't take time
     *              ENDIF
     *      ENDIF
     * ENDIF
     */

    /*
     * This is a local reference.
     */
    if (secEngineIDLen == myIDLength
        && memcmp(secEngineID, myID, myIDLength) == 0) {
        u_int           time_difference = myTime > time_uint ?
            myTime - time_uint : time_uint - myTime;

        if (boots_uint == ENGINEBOOT_MAX
            || boots_uint != myBoots
            || time_difference > USM_TIME_WINDOW) {
            snmp_increment_statistic(STAT_USMSTATSNOTINTIMEWINDOWS);

            DEBUGMSGTL(("usm",
                        "boot_uint %u myBoots %u time_diff %u => not in time window\n",
                        boots_uint, myBoots, time_difference));
            *error = SNMPERR_USM_NOTINTIMEWINDOW;
            return -1;
        }

        *error = SNMPERR_SUCCESS;
        return 0;
    }

    /*
     * This is a remote reference.
     */
    else {
        u_int           theirBoots, theirTime, theirLastTime;
        u_int           time_difference;

        if (get_enginetime_ex(secEngineID, secEngineIDLen,
                              &theirBoots, &theirTime,
                              &theirLastTime, TRUE)
            != SNMPERR_SUCCESS) {
            DEBUGMSGTL(("usm", "%s\n",
                        "Failed to get remote engine's times."));

            *error = SNMPERR_USM_GENERICERROR;
            return -1;
        }

        time_difference = theirTime > time_uint ?
            theirTime - time_uint : time_uint - theirTime;


        /*
         * XXX  Contrary to the pseudocode:
         *      See if boots is invalid first.
         */
        if (theirBoots == ENGINEBOOT_MAX || theirBoots > boots_uint) {
            DEBUGMSGTL(("usm", "%s\n", "Remote boot count invalid."));

            *error = SNMPERR_USM_NOTINTIMEWINDOW;
            return -1;
        }


        /*
         * Boots is ok, see if the boots is the same but the time
         * is old.
         */
        if (theirBoots == boots_uint && time_uint < theirLastTime) {
            if (time_difference > USM_TIME_WINDOW) {
                DEBUGMSGTL(("usm", "%s\n", "Message too old."));
                *error = SNMPERR_USM_NOTINTIMEWINDOW;
                return -1;
            }

            else {              /* Old, but acceptable */

                *error = SNMPERR_SUCCESS;
                return 0;
            }
        }


        /*
         * Message is ok, either boots has been advanced, or
         * time is greater than before with the same boots.
         */

        if (set_enginetime(secEngineID, secEngineIDLen,
                           boots_uint, time_uint, TRUE)
            != SNMPERR_SUCCESS) {
            DEBUGMSGTL(("usm", "%s\n",
                        "Failed updating remote boot/time."));
            *error = SNMPERR_USM_GENERICERROR;
            return -1;
        }

        *error = SNMPERR_SUCCESS;
        return 0;               /* Fresh message and time updated */

    }                           /* endif -- local or remote time reference. */


}                               /* end usm_check_and_update_timeliness() */

Project: net-snmp
File: snmpusm.c

usm_set_user_password(struct usmUser *user, const char *token, char *line)
{
    char           *cp = line;
    u_char         *engineID = user->engineID;
    size_t          engineIDLen = user->engineIDLen;

    u_char        **key;
    size_t         *keyLen;
    u_char          userKey[SNMP_MAXBUF_SMALL];
    size_t          userKeyLen = SNMP_MAXBUF_SMALL;
    u_char         *userKeyP = userKey;
    int             type, ret;

    /*
     * Retrieve the "old" key and set the key type.
     */
    if (!token) {
        return;
    } else if (strcmp(token, "userSetAuthPass") == 0) {
        key = &user->authKey;
        keyLen = &user->authKeyLen;
        type = 0;
    } else if (strcmp(token, "userSetPrivPass") == 0) {
        key = &user->privKey;
        keyLen = &user->privKeyLen;
        type = 0;
    } else if (strcmp(token, "userSetAuthKey") == 0) {
        key = &user->authKey;
        keyLen = &user->authKeyLen;
        type = 1;
    } else if (strcmp(token, "userSetPrivKey") == 0) {
        key = &user->privKey;
        keyLen = &user->privKeyLen;
        type = 1;
    } else if (strcmp(token, "userSetAuthLocalKey") == 0) {
        key = &user->authKey;
        keyLen = &user->authKeyLen;
        type = 2;
    } else if (strcmp(token, "userSetPrivLocalKey") == 0) {
        key = &user->privKey;
        keyLen = &user->privKeyLen;
        type = 2;
    } else {
        /*
         * no old key, or token was not recognized 
         */
        return;
    }

    if (*key) {
        /*
         * (destroy and) free the old key 
         */
        memset(*key, 0, *keyLen);
        SNMP_FREE(*key);
    }

    if (type == 0) {
        /*
         * convert the password into a key 
         */
        if (cp == NULL) {
            config_perror("missing user password");
            return;
        }
        ret = generate_Ku(user->authProtocol, user->authProtocolLen,
                          (u_char *) cp, strlen(cp), userKey, &userKeyLen);

        if (ret != SNMPERR_SUCCESS) {
            config_perror("setting key failed (in sc_genKu())");
            return;
        }
        /* save master key */
        if (user->flags & USMUSER_FLAG_KEEP_MASTER_KEY) {
            if (userKey == user->privKey) {
                user->privKeyKu = netsnmp_memdup(userKey, userKeyLen);
                user->privKeyKuLen = userKeyLen;
            } else if (userKey == user->authKey) {
                user->authKeyKu = netsnmp_memdup(userKey, userKeyLen);
                user->authKeyKuLen = userKeyLen;
            }
        }
    } else if (type == 1) {
        cp = read_config_read_octet_string(cp, &userKeyP, &userKeyLen);

        if (cp == NULL) {
            config_perror("invalid user key");
            return;
        }
    }

    if (type < 2) {
        *key = (u_char *) malloc(SNMP_MAXBUF_SMALL);
        *keyLen = SNMP_MAXBUF_SMALL;
        ret = generate_kul(user->authProtocol, user->authProtocolLen,
                           engineID, engineIDLen,
                           userKey, userKeyLen, *key, keyLen);
        if (ret != SNMPERR_SUCCESS) {
            config_perror("setting key failed (in generate_kul())");
            return;
        }

        /*
         * (destroy and) free the old key 
         */
        memset(userKey, 0, sizeof(userKey));

    } else {
        /*
         * the key is given, copy it in 
         */
        cp = read_config_read_octet_string(cp, key, keyLen);

        if (cp == NULL) {
            config_perror("invalid localized user key");
            return;
        }
    }

    if (key == &user->privKey) {
        ret = usm_extend_user_kul(user, *keyLen);
        if (SNMPERR_SUCCESS != ret) {
            config_perror("error extending localized user key");
            return;
        }
    }
}                               /* end usm_set_password() */

Project: net-snmp
File: snmpusm.c

asn_predict_int_length(int type, long number, size_t len)
{
    register u_long mask;


    if (len != sizeof(long))
        return -1;

    mask = ((u_long) 0x1FF) << ((8 * (sizeof(long) - 1)) - 1);
    /*
     * mask is 0xFF800000 on a big-endian machine 
     */

    while ((((number & mask) == 0) || ((number & mask) == mask))
           && len > 1) {
        len--;
        number <<= 8;
    }

    return len;

}                               /* end asn_predict_length() */

Project: net-snmp
File: snmpusm.c

init_usm(void)
{
    struct snmp_secmod_def *def;
    char *type;

    DEBUGMSGTL(("init_usm", "unit_usm: %" NETSNMP_PRIo "u %" NETSNMP_PRIo "u\n",
                usmNoPrivProtocol[0], usmNoPrivProtocol[1]));

    sc_init();                  /* initalize scapi code */

    /*
     * register ourselves as a security service
     */
    def = SNMP_MALLOC_STRUCT(snmp_secmod_def);
    if (def == NULL)
        return;
    /*
     * XXX: def->init_sess_secmod move stuff from snmp_api.c
     */
    def->encode_reverse = usm_secmod_rgenerate_out_msg;
    def->encode_forward = usm_secmod_generate_out_msg;
    def->decode = usm_secmod_process_in_msg;
    def->pdu_clone = usm_clone;
    def->pdu_free_state_ref = usm_free_usmStateReference;
    def->session_setup = usm_session_init;
    def->handle_report = usm_handle_report;
    def->probe_engineid = usm_discover_engineid;
    def->post_probe_engineid = usm_create_user_from_session_hook;
    if (register_sec_mod(USM_SEC_MODEL_NUMBER, "usm", def) != SNMPERR_SUCCESS) {
        SNMP_FREE(def);
        snmp_log(LOG_ERR, "could not register usm sec mod\n");
        return;
    }

    snmp_register_callback(SNMP_CALLBACK_LIBRARY,
                           SNMP_CALLBACK_POST_PREMIB_READ_CONFIG,
                           init_usm_post_config, NULL);

    snmp_register_callback(SNMP_CALLBACK_LIBRARY,
                           SNMP_CALLBACK_SHUTDOWN,
                           deinit_usm_post_config, NULL);

    snmp_register_callback(SNMP_CALLBACK_LIBRARY,
                           SNMP_CALLBACK_SHUTDOWN,
                           free_engineID, NULL);

    register_config_handler("snmp", "defAuthType", snmpv3_authtype_conf,
                            NULL, "MD5|SHA|SHA-512|SHA-384|SHA-256|SHA-224");
    register_config_handler("snmp", "defPrivType", snmpv3_privtype_conf,
                            NULL,
                            "DES"
#ifdef HAVE_AES
                            "|AES|AES-128"
#ifdef NETSNMP_DRAFT_BLUMENTHAL_AES_04
                            "|AES-192|AES-256"
#endif /* NETSNMP_DRAFT_BLUMENTHAL_AES_04 */
#else
                            " (AES support not available)"
#endif
                           );

    /*
     * Free stuff at shutdown time
     */
    snmp_register_callback(SNMP_CALLBACK_LIBRARY,
                           SNMP_CALLBACK_SHUTDOWN,
                           free_enginetime_on_shutdown, NULL);


    type = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_APPTYPE);

    register_config_handler(type, "userSetAuthPass", usm_set_password,
                            NULL, NULL);
    register_config_handler(type, "userSetPrivPass", usm_set_password,
                            NULL, NULL);
    register_config_handler(type, "userSetAuthKey", usm_set_password, NULL,
                            NULL);
    register_config_handler(type, "userSetPrivKey", usm_set_password, NULL,
                            NULL);
    register_config_handler(type, "userSetAuthLocalKey", usm_set_password,
                            NULL, NULL);
    register_config_handler(type, "userSetPrivLocalKey", usm_set_password,
                            NULL, NULL);
}

Project: net-snmp
File: snmp_client.c

_get_vb_num(netsnmp_variable_list *vars, int index)
{
    for (; vars && index > 0; --index)
        vars = vars->next_variable;

    if (!vars || index > 0)
        return NULL;
    
    return vars;
}

Project: net-snmp
File: snmp_client.c

snmp_set_var_typed_value(netsnmp_variable_list * newvar, u_char type,
                         const void * val_str, size_t val_len)
{
    newvar->type = type;
    return snmp_set_var_value(newvar, val_str, val_len);
}

Project: net-snmp
File: snmpusm.c

usm_set_usmStateReference_auth_protocol(struct usmStateReference *ref,
                                        oid * auth_protocol,
                                        size_t auth_protocol_len)
{
    MAKE_ENTRY(ref, oid, auth_protocol, auth_protocol_len,
               usr_auth_protocol, usr_auth_protocol_length);
}

Project: net-snmp
File: snmpusm.c

usm_secmod_process_in_msg(struct snmp_secmod_incoming_params *parms)
{
    if (!parms)
        return SNMPERR_GENERR;

    return usm_process_in_msg(parms->msgProcModel,
                              parms->maxMsgSize,
                              parms->secParams,
                              parms->secModel,
                              parms->secLevel,
                              parms->wholeMsg,
                              parms->wholeMsgLen,
                              parms->secEngineID,
                              parms->secEngineIDLen,
                              parms->secName,
                              parms->secNameLen,
                              parms->scopedPdu,
                              parms->scopedPduLen,
                              parms->maxSizeResponse,
                              parms->secStateRef,
                              parms->sess, parms->msg_flags);
}

Project: net-snmp
File: snmpusm.c

usm_set_password(const char *token, char *line)
{
    char           *cp;
    char            nameBuf[SNMP_MAXBUF];
    u_char         *engineID = NULL;
    size_t          engineIDLen = 0;
    struct usmUser *user;

    cp = copy_nword(line, nameBuf, sizeof(nameBuf));
    if (cp == NULL) {
        config_perror("invalid name specifier");
        return;
    }

    DEBUGMSGTL(("usm", "comparing: %s and %s\n", cp, WILDCARDSTRING));
    if (strncmp(cp, WILDCARDSTRING, strlen(WILDCARDSTRING)) == 0) {
        /*
         * match against all engineIDs we know about 
         */
        cp = skip_token(cp);
        for (user = userList; user != NULL; user = user->next) {
            if (user->secName && strcmp(user->secName, nameBuf) == 0) {
                usm_set_user_password(user, token, cp);
            }
        }
    } else {
        cp = read_config_read_octet_string(cp, &engineID, &engineIDLen);
        if (cp == NULL) {
            config_perror("invalid engineID specifier");
            SNMP_FREE(engineID);
            return;
        }

        user = usm_get_user(engineID, engineIDLen, nameBuf);
        if (user == NULL) {
            config_perror("not a valid user/engineID pair");
            SNMP_FREE(engineID);
            return;
        }
        usm_set_user_password(user, token, cp);
        SNMP_FREE(engineID);
    }
}

Project: net-snmp
File: snmp_client.c

snmp_clone_pdu(netsnmp_pdu *pdu)
{
    return _clone_pdu(pdu, 0);  /* copies all variables */
}

Project: net-snmp
File: snmpusm.c

usm_set_usmStateReference_priv_protocol(struct usmStateReference *ref,
                                        oid * priv_protocol,
                                        size_t priv_protocol_len)
{
    MAKE_ENTRY(ref, oid, priv_protocol, priv_protocol_len,
               usr_priv_protocol, usr_priv_protocol_length);
}

Project: net-snmp
File: snmpusm.c

usm_secmod_rgenerate_out_msg(struct snmp_secmod_outgoing_params *parms)
{
    if (!parms)
        return SNMPERR_GENERR;

    return usm_rgenerate_out_msg(parms->msgProcModel,
                                 parms->globalData, parms->globalDataLen,
                                 parms->maxMsgSize, parms->secModel,
                                 parms->secEngineID, parms->secEngineIDLen,
                                 parms->secName, parms->secNameLen,
                                 parms->secLevel,
                                 parms->scopedPdu, parms->scopedPduLen,
                                 parms->secStateRef,
                                 parms->wholeMsg, parms->wholeMsgLen,
                                 parms->wholeMsgOffset);
}

Project: net-snmp
File: snmpusm.c

usm_read_user(const char *line)
{
    struct usmUser *user;
    size_t          len, proper_length, privtype;

    user = usm_create_user();
    if (user == NULL)
        return NULL;

    user->userStatus = atoi(line);
    line = skip_token_const(line);
    user->userStorageType = atoi(line);
    line = skip_token_const(line);
    line = read_config_read_octet_string_const(line, &user->engineID,
                                               &user->engineIDLen);

    /*
     * set the lcd entry for this engineID to the minimum boots/time
     * values so that its a known engineid and won't return a report pdu.
     * This is mostly important when receiving v3 traps so that the usm
     * will at least continue processing them. 
     */
    set_enginetime(user->engineID, user->engineIDLen, 1, 0, 0);

    line = read_config_read_octet_string(line, (u_char **) & user->name,
                                         &len);
    line = read_config_read_octet_string(line, (u_char **) & user->secName,
                                         &len);
    SNMP_FREE(user->cloneFrom);
    user->cloneFromLen = 0;

    line = read_config_read_objid_const(line, &user->cloneFrom,
                                        &user->cloneFromLen);

    SNMP_FREE(user->authProtocol);
    user->authProtocolLen = 0;

    line = read_config_read_objid_const(line, &user->authProtocol,
                                        &user->authProtocolLen);
    line = read_config_read_octet_string_const(line, &user->authKey,
                                               &user->authKeyLen);
    SNMP_FREE(user->privProtocol);
    user->privProtocolLen = 0;

    line = read_config_read_objid_const(line, &user->privProtocol,
                                        &user->privProtocolLen);
    line = read_config_read_octet_string(line, &user->privKey,
                                         &user->privKeyLen);

    privtype = sc_get_privtype(user->privProtocol, user->privProtocolLen);
    proper_length = sc_get_proper_priv_length_bytype(privtype);
    if (USM_CREATE_USER_PRIV_DES == privtype)
        proper_length *= 2; /* ?? we store salt with key */
    /* For backwards compatibility */
    if (user->privKeyLen > proper_length) {
        user->privKeyLen = proper_length;
    }

    line = read_config_read_octet_string(line, &user->userPublicString,
                                         &user->userPublicStringLen);
    return user;
}

Project: net-snmp
File: snmp_client.c

static int _query(netsnmp_variable_list *list,
                  int                    request,
                  netsnmp_session       *session) {

    netsnmp_pdu *pdu;
    netsnmp_pdu *response = NULL;
    netsnmp_variable_list *vb1, *vb2, *vtmp;
    int ret, count;

    DEBUGMSGTL(("iquery", "query on session %p\n", session));

    if (NULL == list) {
        snmp_log(LOG_ERR, "empty variable list in _query\n");
        return SNMP_ERR_GENERR;
    }

    pdu = snmp_pdu_create( request );
    if (NULL == pdu) {
        snmp_log(LOG_ERR, "could not allocate pdu\n");
        return SNMP_ERR_GENERR;
    }

    /*
     * Clone the varbind list into the request PDU...
     */
    pdu->variables = snmp_clone_varbind( list );
    if (NULL == pdu->variables) {
        snmp_log(LOG_ERR, "could not clone variable list\n");
        snmp_free_pdu(pdu);
        return SNMP_ERR_GENERR;
    }

#ifndef NETSNMP_NO_WRITE_SUPPORT
retry:
#endif
    if ( session )
        ret = snmp_synch_response(            session, pdu, &response );
    else if (_def_query_session)
        ret = snmp_synch_response( _def_query_session, pdu, &response );
    else {
        /* No session specified */
        snmp_free_pdu(pdu);
        return SNMP_ERR_GENERR;
    }
    DEBUGMSGTL(("iquery", "query returned %d\n", ret));

    /*
     * ....then copy the results back into the
     * list (assuming the request succeeded!).
     * This avoids having to worry about how this
     * list was originally allocated.
     */
    if ( ret == SNMP_ERR_NOERROR ) {
        if ( response->errstat != SNMP_ERR_NOERROR ) {
            DEBUGMSGT(("iquery", "Error in packet: %s\n",
                       snmp_errstring(response->errstat)));
            /*
             * If the request failed, then remove the
             *  offending varbind and try again.
             *  (all except SET requests)
             *
             * XXX - implement a library version of
             *       NETSNMP_DS_APP_DONT_FIX_PDUS ??
             */
            ret = response->errstat;
            if (response->errindex != 0) {
                DEBUGMSGT(("iquery:result", "Failed object:\n"));
                for (count = 1, vtmp = response->variables;
                     vtmp && count != response->errindex;
                     vtmp = vtmp->next_variable, count++)
                    /*EMPTY*/;
                if (vtmp)
                    DEBUGMSGVAR(("iquery:result", vtmp));
                DEBUGMSG(("iquery:result", "\n"));
            }
#ifndef NETSNMP_NO_WRITE_SUPPORT
            if (request != SNMP_MSG_SET &&
                response->errindex != 0) {
                DEBUGMSGTL(("iquery", "retrying query (%d, %ld)\n", ret, response->errindex));
                pdu = snmp_fix_pdu( response, request );
                snmp_free_pdu( response );
                response = NULL;
                if ( pdu != NULL )
                    goto retry;
            }
#endif /* !NETSNMP_NO_WRITE_SUPPORT */
        } else {
            for (vb1 = response->variables, vb2 = list;
                 vb1;
                 vb1 = vb1->next_variable,  vb2 = vb2->next_variable) {
                DEBUGMSGVAR(("iquery:result", vb1));
                DEBUGMSG(("iquery:results", "\n"));
                if ( !vb2 ) {
                    ret = SNMP_ERR_GENERR;
                    break;
                }
                vtmp = vb2->next_variable;
                snmp_free_var_internals( vb2 );
                snmp_clone_var( vb1, vb2 ); /* xxx: check return? */
                vb2->next_variable = vtmp;
            }
        }
    } else {
        /* Distinguish snmp_send errors from SNMP errStat errors */
        ret = -ret;
    }
    snmp_free_pdu( response );
    return ret;
}

Project: net-snmp
File: snmpusm.c

usm_process_in_msg(int msgProcModel,    /* (UNUSED) */
                   size_t maxMsgSize,   /* IN     - Used to calc maxSizeResponse.  */
                   u_char * secParams,  /* IN     - BER encoded securityParameters. */
                   int secModel,        /* (UNUSED) */
                   int secLevel,        /* IN     - AuthNoPriv, authPriv etc.      */
                   u_char * wholeMsg,   /* IN     - Original v3 message.           */
                   size_t wholeMsgLen,  /* IN     - Msg length.                    */
                   u_char * secEngineID,        /* OUT    - Pointer snmpEngineID.          */
                   size_t * secEngineIDLen,     /* IN/OUT - Len available, len returned.   */
                   /*
                    * NOTE: Memory provided by caller.      
                    */
                   char *secName,       /* OUT    - Pointer to securityName.       */
                   size_t * secNameLen, /* IN/OUT - Len available, len returned.   */
                   u_char ** scopedPdu, /* OUT    - Pointer to plaintext scopedPdu. */
                   size_t * scopedPduLen,       /* IN/OUT - Len available, len returned.   */
                   size_t * maxSizeResponse,    /* OUT    - Max size of Response PDU.      */
                   void **secStateRf,   /* OUT    - Ref to security state.         */
                   netsnmp_session * sess,      /* IN     - session which got the message  */
                   u_char msg_flags)
{                               /* IN     - v3 Message flags.              */
    size_t          remaining = wholeMsgLen - (u_int)
        ((u_long) * secParams - (u_long) * wholeMsg);
    u_int           boots_uint;
    u_int           time_uint;
#ifdef HAVE_AES
    u_int           net_boots, net_time;
#endif
#ifndef NETSNMP_DISABLE_DES
    int             i;
#endif
    u_char          signature[USM_MAX_AUTHSIZE];
    size_t          signature_length = USM_MAX_AUTHSIZE;
    u_char          salt[BYTESIZE(USM_MAX_SALT_LENGTH)];
    size_t          salt_length = BYTESIZE(USM_MAX_SALT_LENGTH);
    u_char          iv[BYTESIZE(USM_MAX_SALT_LENGTH)];
    u_int           iv_length = BYTESIZE(USM_MAX_SALT_LENGTH);
    u_char         *data_ptr;
    u_char         *value_ptr;
    u_char          type_value;
    u_char         *end_of_overhead = NULL;
    int             error;
    int             rc = 0;
    struct usmStateReference **secStateRef =
        (struct usmStateReference **) secStateRf;

    struct usmUser *user;


    DEBUGMSGTL(("usm", "USM processing begun...\n"));

    netsnmp_assert(secStateRef);

    usm_free_usmStateReference(*secStateRef);
    *secStateRef = usm_malloc_usmStateReference();
    if (*secStateRef == NULL) {
        DEBUGMSGTL(("usm", "Out of memory.\n"));
        return SNMPERR_USM_GENERICERROR;
    }

    /*
     * Make sure the *secParms is an OCTET STRING.
     * Extract the user name, engine ID, and security level.
     */
    if ((rc = usm_parse_security_parameters(secParams, remaining,
                                            secEngineID, secEngineIDLen,
                                            &boots_uint, &time_uint,
                                            secName, secNameLen,
                                            signature, &signature_length,
                                            salt, &salt_length,
                                            &data_ptr)) < 0) {
        DEBUGMSGTL(("usm", "Parsing failed (rc %d).\n", rc));
        if (rc == -2) {
            /*
             * This indicates a decryptionError.  
             */
            snmp_increment_statistic(STAT_USMSTATSDECRYPTIONERRORS);
            error = SNMPERR_USM_DECRYPTIONERROR;
        } else {
            snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
            error = SNMPERR_USM_PARSEERROR;
        }
        goto err;
    }

    /*
     * RFC 2574 section 8.3.2
     * 1)  If the privParameters field is not an 8-octet OCTET STRING,
     * then an error indication (decryptionError) is returned to the
     * calling module.
     */
    if ((secLevel == SNMP_SEC_LEVEL_AUTHPRIV) && (salt_length != 8)) {
        snmp_increment_statistic(STAT_USMSTATSDECRYPTIONERRORS);
        error = SNMPERR_USM_DECRYPTIONERROR;
        goto err;
    }

    if (secLevel != SNMP_SEC_LEVEL_AUTHPRIV) {
        /*
         * pull these out now so reports can use them 
         */
        *scopedPdu = data_ptr;
        *scopedPduLen = wholeMsgLen - (data_ptr - wholeMsg);
        end_of_overhead = data_ptr;
    }

    /*
     * Cache the name, engine ID, and security level,
     * * per step 2 (section 3.2)
     */
    if (usm_set_usmStateReference_name
        (*secStateRef, secName, *secNameLen) == -1) {
        DEBUGMSGTL(("usm", "%s\n", "Couldn't cache name."));
        error = SNMPERR_USM_GENERICERROR;
        goto err;
    }

    if (usm_set_usmStateReference_engine_id
        (*secStateRef, secEngineID, *secEngineIDLen) == -1) {
        DEBUGMSGTL(("usm", "%s\n", "Couldn't cache engine id."));
        error = SNMPERR_USM_GENERICERROR;
        goto err;
    }

    if (usm_set_usmStateReference_sec_level(*secStateRef, secLevel) ==
        -1) {
        DEBUGMSGTL(("usm", "%s\n", "Couldn't cache security level."));
        error = SNMPERR_USM_GENERICERROR;
        goto err;
    }

    /*
     * Locate the engine ID record.
     * If it is unknown, then either create one or note this as an error.
     */
    if ((sess && (sess->isAuthoritative == SNMP_SESS_AUTHORITATIVE ||
                  (sess->isAuthoritative == SNMP_SESS_UNKNOWNAUTH &&
                   (msg_flags & SNMP_MSG_FLAG_RPRT_BIT)))) ||
        (!sess && (msg_flags & SNMP_MSG_FLAG_RPRT_BIT))) {
        if (ISENGINEKNOWN(secEngineID, *secEngineIDLen) == FALSE) {
            DEBUGMSGTL(("usm", "Unknown Engine ID.\n"));
            snmp_increment_statistic(STAT_USMSTATSUNKNOWNENGINEIDS);
            error = SNMPERR_USM_UNKNOWNENGINEID;
            goto err;
        }
    } else {
        if (ENSURE_ENGINE_RECORD(secEngineID, *secEngineIDLen)
            != SNMPERR_SUCCESS) {
            DEBUGMSGTL(("usm", "%s\n", "Couldn't ensure engine record."));
            error = SNMPERR_USM_GENERICERROR;
            goto err;
        }

    }


    /*
     * Locate the User record.
     * If the user/engine ID is unknown, report this as an error.
     */
    if ((user = usm_get_user_from_list(secEngineID, *secEngineIDLen,
                                       secName, userList,
                                       (((sess && sess->isAuthoritative ==
                                          SNMP_SESS_AUTHORITATIVE) ||
                                         (!sess)) ? 0 : 1)))
        == NULL) {
        DEBUGMSGTL(("usm", "Unknown User(%s)\n", secName));
        snmp_increment_statistic(STAT_USMSTATSUNKNOWNUSERNAMES);
        error = SNMPERR_USM_UNKNOWNSECURITYNAME;
        goto err;
    }

    /* ensure the user is active */
    if (user->userStatus != RS_ACTIVE) {
        DEBUGMSGTL(("usm", "Attempt to use an inactive user.\n"));
        error = SNMPERR_USM_UNKNOWNSECURITYNAME;
        goto err;
    }

    /*
     * Make sure the security level is appropriate.
     */

    rc = usm_check_secLevel(secLevel, user);
    if (1 == rc) {
        DEBUGMSGTL(("usm", "Unsupported Security Level (%d).\n",
                    secLevel));
        snmp_increment_statistic(STAT_USMSTATSUNSUPPORTEDSECLEVELS);
        error = SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL;
        goto err;
    } else if (rc != 0) {
        DEBUGMSGTL(("usm", "Unknown issue.\n"));
        error = SNMPERR_USM_GENERICERROR;
        goto err;
    }

    /*
     * Check the authentication credentials of the message.
     */
    if (secLevel == SNMP_SEC_LEVEL_AUTHNOPRIV
        || secLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
        if (sc_check_keyed_hash(user->authProtocol, user->authProtocolLen,
                                user->authKey, user->authKeyLen,
                                wholeMsg, wholeMsgLen,
                                signature, signature_length)
            != SNMP_ERR_NOERROR) {
            DEBUGMSGTL(("usm", "Verification failed.\n"));
            snmp_increment_statistic(STAT_USMSTATSWRONGDIGESTS);
	    snmp_log(LOG_WARNING, "Authentication failed for %s\n",
				user->name);
            error = SNMPERR_USM_AUTHENTICATIONFAILURE;
            goto err;
        }

        DEBUGMSGTL(("usm", "Verification succeeded.\n"));
    }


    /*
     * Steps 10-11  user is already set - relocated before timeliness 
     * check in case it fails - still save user data for response.
     *
     * Cache the keys and protocol oids, per step 11 (s3.2).
     */
    if (usm_set_usmStateReference_auth_protocol(*secStateRef,
                                                user->authProtocol,
                                                user->
                                                authProtocolLen) == -1) {
        DEBUGMSGTL(("usm", "%s\n",
                    "Couldn't cache authentication protocol."));
        error = SNMPERR_USM_GENERICERROR;
        goto err;
    }

    if (usm_set_usmStateReference_auth_key(*secStateRef,
                                           user->authKey,
                                           user->authKeyLen) == -1) {
        DEBUGMSGTL(("usm", "%s\n",
                    "Couldn't cache authentication key."));
        error = SNMPERR_USM_GENERICERROR;
        goto err;
    }

    if (usm_set_usmStateReference_priv_protocol(*secStateRef,
                                                user->privProtocol,
                                                user->
                                                privProtocolLen) == -1) {
        DEBUGMSGTL(("usm", "%s\n",
                    "Couldn't cache privacy protocol."));
        error = SNMPERR_USM_GENERICERROR;
        goto err;
    }

    if (usm_set_usmStateReference_priv_key(*secStateRef,
                                           user->privKey,
                                           user->privKeyLen) == -1) {
        DEBUGMSGTL(("usm", "%s\n", "Couldn't cache privacy key."));
        error = SNMPERR_USM_GENERICERROR;
        goto err;
    }


    /*
     * Perform the timeliness/time manager functions.
     */
    if (secLevel == SNMP_SEC_LEVEL_AUTHNOPRIV
        || secLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
        if (usm_check_and_update_timeliness(secEngineID, *secEngineIDLen,
                                            boots_uint, time_uint,
                                            &error) == -1) {
            goto err;
        }
    }
#ifdef							LCD_TIME_SYNC_OPT
    /*
     * Cache the unauthenticated time to use in case we don't have
     * anything better - this guess will be no worse than (0,0)
     * that we normally use.
     */
    else {
        set_enginetime(secEngineID, *secEngineIDLen,
                       boots_uint, time_uint, FALSE);
    }
#endif                          /* LCD_TIME_SYNC_OPT */


    /*
     * If needed, decrypt the scoped PDU.
     */
    if (secLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
        int priv_type = sc_get_privtype(user->privProtocol,
                                        user->privProtocolLen);
        remaining = wholeMsgLen - (data_ptr - wholeMsg);

        if ((value_ptr = asn_parse_sequence(data_ptr, &remaining,
                                            &type_value,
                                            (ASN_UNIVERSAL | ASN_PRIMITIVE
                                             | ASN_OCTET_STR),
                                            "encrypted sPDU")) == NULL) {
            DEBUGMSGTL(("usm", "%s\n",
                        "Failed while parsing encrypted sPDU."));
            snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
            usm_free_usmStateReference(*secStateRef);
            *secStateRef = NULL;
            error = SNMPERR_USM_PARSEERROR;
            goto err;
        }

#ifndef NETSNMP_DISABLE_DES
        if (USM_CREATE_USER_PRIV_DES == (priv_type & USM_PRIV_MASK_ALG)) {
            /*
             * From RFC2574:
             * 
             * "Before decryption, the encrypted data length is verified.
             * If the length of the OCTET STRING to be decrypted is not
             * an integral multiple of 8 octets, the decryption process
             * is halted and an appropriate exception noted."  
             */

            if (remaining % 8 != 0) {
                DEBUGMSGTL(("usm",
                            "Ciphertext is %lu bytes, not an integer multiple of 8 (rem %lu)\n",
                            (unsigned long)remaining, (unsigned long)remaining % 8));
                snmp_increment_statistic(STAT_USMSTATSDECRYPTIONERRORS);
                usm_free_usmStateReference(*secStateRef);
                *secStateRef = NULL;
                error = SNMPERR_USM_DECRYPTIONERROR;
                goto err;
            }

            end_of_overhead = value_ptr;

            if ( !user->privKey ) {
                DEBUGMSGTL(("usm", "No privacy pass phrase for %s\n", user->secName));
                snmp_increment_statistic(STAT_USMSTATSDECRYPTIONERRORS);
                usm_free_usmStateReference(*secStateRef);
                *secStateRef = NULL;
                error = SNMPERR_USM_DECRYPTIONERROR;
                goto err;
            }

            /*
             * XOR the salt with the last (iv_length) bytes
             * of the priv_key to obtain the IV.
             */
            iv_length = BYTESIZE(USM_DES_SALT_LENGTH);
            for (i = 0; i < (int) iv_length; i++)
                iv[i] = salt[i] ^ user->privKey[iv_length + i];
        }
#endif
#ifdef HAVE_AES
        if (USM_CREATE_USER_PRIV_AES == (priv_type & USM_PRIV_MASK_ALG)) {
            iv_length = BYTESIZE(USM_AES_SALT_LENGTH);
            net_boots = ntohl(boots_uint);
            net_time = ntohl(time_uint);
            memcpy(iv, &net_boots, 4);
            memcpy(iv+4, &net_time, 4);
            memcpy(iv+8, salt, salt_length);
        }
#endif

#ifdef NETSNMP_ENABLE_TESTING_CODE
        if (debug_is_token_registered("usm/dump") == SNMPERR_SUCCESS) {
            dump_chunk("usm/dump", "Cypher Text", value_ptr, remaining);
            dump_chunk("usm/dump", "salt + Encrypted form:",
                       salt, salt_length);
            dump_chunk("usm/dump", "IV + Encrypted form:", iv, iv_length);
        }
#endif
        if (sc_decrypt(user->privProtocol, user->privProtocolLen,
                       user->privKey, user->privKeyLen,
                       iv, iv_length,
                       value_ptr, remaining, *scopedPdu, scopedPduLen)
            != SNMP_ERR_NOERROR) {
            DEBUGMSGTL(("usm", "%s\n", "Failed decryption."));
            snmp_increment_statistic(STAT_USMSTATSDECRYPTIONERRORS);
            error = SNMPERR_USM_DECRYPTIONERROR;
            goto err;
        }
#ifdef NETSNMP_ENABLE_TESTING_CODE
        if (debug_is_token_registered("usm/dump") == SNMPERR_SUCCESS) {
            dump_chunk("usm/dump", "Decrypted chunk:",
                       *scopedPdu, *scopedPduLen);
        }
#endif
    }
    /*
     * sPDU is plaintext.
     */
    else {
        *scopedPdu = data_ptr;
        *scopedPduLen = wholeMsgLen - (data_ptr - wholeMsg);
        end_of_overhead = data_ptr;

    }                           /* endif -- PDU decryption */


    /*
     * Calculate the biggest sPDU for the response (i.e., whole - ovrhd).
     *
     * FIX  Correct? 
     */
    *maxSizeResponse = maxMsgSize - (end_of_overhead - wholeMsg);


    DEBUGMSGTL(("usm", "USM processing completed.\n"));

    return SNMPERR_SUCCESS;

err:
    usm_free_usmStateReference(*secStateRef);
    *secStateRef = NULL;
    netsnmp_assert(error != SNMPERR_SUCCESS);
    return error;
}                               /* end usm_process_in_msg() */

Project: net-snmp
File: snmpusm.c

usm_save_users(const char *token, const char *type)
{
    usm_save_users_from_list(userList, token, type);
}

Project: net-snmp
File: snmp_client.c

int netsnmp_query_set(netsnmp_variable_list *list,
                      netsnmp_session       *session){
    return _query( list, SNMP_MSG_SET, session );
}

Project: net-snmp
File: snmpusm.c

usm_parse_create_usmUser(const char *token, char *line)
{
    const char *error = NULL;
    usm_create_usmUser_from_string(line, &error);
    if (error)
        config_perror(error);
}

Project: net-snmp
File: snmpusm.c

snmpv3_privtype_conf(const char *word, char *cptr)
{
    int priv_type = usm_lookup_priv_type(cptr);
    if (priv_type < 0)
        config_perror("Unknown privacy type");
    defaultPrivType = sc_get_priv_oid(priv_type, &defaultPrivTypeLen);
    DEBUGMSGTL(("snmpv3", "set default privacy type: %s\n", cptr));
}

Project: net-snmp
File: snmpusm.c

usm_secmod_generate_out_msg(struct snmp_secmod_outgoing_params *parms)
{
    if (!parms)
        return SNMPERR_GENERR;

    return usm_generate_out_msg(parms->msgProcModel,
                                parms->globalData, parms->globalDataLen,
                                parms->maxMsgSize, parms->secModel,
                                parms->secEngineID, parms->secEngineIDLen,
                                parms->secName, parms->secNameLen,
                                parms->secLevel,
                                parms->scopedPdu, parms->scopedPduLen,
                                parms->secStateRef,
                                parms->secParams, parms->secParamsLen,
                                parms->wholeMsg, parms->wholeMsgLen);
}

Project: net-snmp
File: snmpusm.c

usm_get_user_from_list(u_char * engineID, size_t engineIDLen,
                       char *name, struct usmUser *puserList,
                       int use_default)
{
    struct usmUser *ptr;
    char            noName[] = "";
    if (name == NULL)
        name = noName;
    for (ptr = puserList; ptr != NULL; ptr = ptr->next) {
        if (ptr->name && !strcmp(ptr->name, name)) {
          DEBUGMSGTL(("usm", "match on user %s\n", ptr->name));
          if (ptr->engineIDLen == engineIDLen &&
            ((ptr->engineID == NULL && engineID == NULL) ||
             (ptr->engineID != NULL && engineID != NULL &&
              memcmp(ptr->engineID, engineID, engineIDLen) == 0)))
            return ptr;
          DEBUGMSGTL(("usm", "no match on engineID ("));
          if (engineID) {
              DEBUGMSGHEX(("usm", engineID, engineIDLen));
          } else {
              DEBUGMSGTL(("usm", "Empty EngineID"));
          }
          DEBUGMSG(("usm", ")\n"));
        }
    }

    /*
     * return "" user used to facilitate engineID discovery
     */
    if (use_default && !strcmp(name, ""))
        return noNameUser;
    return NULL;
}

Project: net-snmp
File: snmpusm.c

usm_build_probe_pdu(netsnmp_pdu **pdu)
{
    struct usmUser *user;

    /*
     * create the pdu 
     */
    if (!pdu)
        return -1;
    *pdu = snmp_pdu_create(SNMP_MSG_GET);
    if (!(*pdu))
        return -1;
    (*pdu)->version = SNMP_VERSION_3;
    (*pdu)->securityName = strdup("");
    (*pdu)->securityNameLen = strlen((*pdu)->securityName);
    (*pdu)->securityLevel = SNMP_SEC_LEVEL_NOAUTH;
    (*pdu)->securityModel = SNMP_SEC_MODEL_USM;

    /*
     * create the empty user 
     */
    user = usm_get_user(NULL, 0, (*pdu)->securityName);
    if (user == NULL) {
        user = (struct usmUser *) calloc(1, sizeof(struct usmUser));
        if (user == NULL) {
            snmp_free_pdu(*pdu);
            *pdu = (netsnmp_pdu *) NULL;
            return -1;
        }
        user->name = strdup((*pdu)->securityName);
        user->secName = strdup((*pdu)->securityName);
        user->authProtocolLen = sizeof(usmNoAuthProtocol) / sizeof(oid);
        user->authProtocol =
            snmp_duplicate_objid(usmNoAuthProtocol, user->authProtocolLen);
        user->privProtocolLen = sizeof(usmNoPrivProtocol) / sizeof(oid);
        user->privProtocol =
            snmp_duplicate_objid(usmNoPrivProtocol, user->privProtocolLen);
        usm_add_user(user);
    }
    return 0;
}

Project: net-snmp
File: snmpusm.c

usm_clone_usmStateReference(struct usmStateReference *from, struct usmStateReference **to)
{
    struct usmStateReference *cloned_usmStateRef;

    if (from == NULL || to == NULL)
        return -1;

    *to = usm_malloc_usmStateReference();
    cloned_usmStateRef = *to;

    if (usm_set_usmStateReference_name(cloned_usmStateRef, from->usr_name, from->usr_name_length) ||
        usm_set_usmStateReference_engine_id(cloned_usmStateRef, from->usr_engine_id, from->usr_engine_id_length) ||
        usm_set_usmStateReference_auth_protocol(cloned_usmStateRef, from->usr_auth_protocol, from->usr_auth_protocol_length) ||
        usm_set_usmStateReference_auth_key(cloned_usmStateRef, from->usr_auth_key, from->usr_auth_key_length) ||
        usm_set_usmStateReference_priv_protocol(cloned_usmStateRef, from->usr_priv_protocol, from->usr_priv_protocol_length) ||
        usm_set_usmStateReference_priv_key(cloned_usmStateRef, from->usr_priv_key, from->usr_priv_key_length) ||
        usm_set_usmStateReference_sec_level(cloned_usmStateRef, from->usr_sec_level))
    {
        usm_free_usmStateReference(*to);
        *to = NULL;
        return -1;
    }

    return 0;

}

Project: net-snmp
File: snmpusm.c

usm_parse_security_parameters(u_char * secParams,
                              size_t remaining,
                              u_char * secEngineID,
                              size_t * secEngineIDLen,
                              u_int * boots_uint,
                              u_int * time_uint,
                              char *secName,
                              size_t * secNameLen,
                              u_char * signature,
                              size_t * signature_length,
                              u_char * salt,
                              size_t * salt_length, u_char ** data_ptr)
{
    u_char         *parse_ptr = secParams;
    u_char         *value_ptr;
    u_char         *next_ptr;
    u_char          type_value;

    size_t          octet_string_length = remaining;
    size_t          sequence_length;
    size_t          remaining_bytes;

    long            boots_long;
    long            time_long;

    u_int           origNameLen;


    /*
     * Eat the first octet header.
     */
    if ((value_ptr = asn_parse_sequence(parse_ptr, &octet_string_length,
                                        &type_value,
                                        (ASN_UNIVERSAL | ASN_PRIMITIVE |
                                         ASN_OCTET_STR),
                                        "usm first octet")) == NULL) {
        /*
         * RETURN parse error 
         */ return -1;
    }


    /*
     * Eat the sequence header.
     */
    parse_ptr = value_ptr;
    sequence_length = octet_string_length;

    if ((value_ptr = asn_parse_sequence(parse_ptr, &sequence_length,
                                        &type_value,
                                        (ASN_SEQUENCE | ASN_CONSTRUCTOR),
                                        "usm sequence")) == NULL) {
        /*
         * RETURN parse error 
         */ return -1;
    }


    /*
     * Retrieve the engineID.
     */
    parse_ptr = value_ptr;
    remaining_bytes = sequence_length;

    DEBUGDUMPHEADER("recv", "msgAuthoritativeEngineID");
    if ((next_ptr
         = asn_parse_string(parse_ptr, &remaining_bytes, &type_value,
                            secEngineID, secEngineIDLen)) == NULL) {
        DEBUGINDENTLESS();
        /*
         * RETURN parse error 
         */ return -1;
    }
    DEBUGINDENTLESS();

    if (type_value !=
        (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR)) {
        /*
         * RETURN parse error 
         */ return -1;
    }


    /*
     * Retrieve the engine boots, notice switch in the way next_ptr and
     * remaining_bytes are used (to accomodate the asn code).
     */
    DEBUGDUMPHEADER("recv", "msgAuthoritativeEngineBoots");
    if ((next_ptr = asn_parse_int(next_ptr, &remaining_bytes, &type_value,
                                  &boots_long, sizeof(long))) == NULL) {
        DEBUGINDENTLESS();
        /*
         * RETURN parse error 
         */ return -1;
    }
    DEBUGINDENTLESS();

    if (type_value !=
        (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER)) {
        DEBUGINDENTLESS();
        /*
         * RETURN parse error 
         */ return -1;
    }

    *boots_uint = (u_int) boots_long;


    /*
     * Retrieve the time value.
     */
    DEBUGDUMPHEADER("recv", "msgAuthoritativeEngineTime");
    if ((next_ptr = asn_parse_int(next_ptr, &remaining_bytes, &type_value,
                                  &time_long, sizeof(long))) == NULL) {
        /*
         * RETURN parse error 
         */ return -1;
    }
    DEBUGINDENTLESS();

    if (type_value !=
        (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER)) {
        /*
         * RETURN parse error 
         */ return -1;
    }

    *time_uint = (u_int) time_long;

    if (*boots_uint > ENGINEBOOT_MAX || *time_uint > ENGINETIME_MAX) {
        return -1;
    }

    /*
     * Retrieve the secName.
     */
    origNameLen = *secNameLen;


    DEBUGDUMPHEADER("recv", "msgUserName");
    if ((next_ptr
         = asn_parse_string(next_ptr, &remaining_bytes, &type_value,
                            (u_char *) secName, secNameLen)) == NULL) {
        DEBUGINDENTLESS();
        /*
         * RETURN parse error 
         */ return -1;
    }
    DEBUGINDENTLESS();

    /*
     * FIX -- doesn't this also indicate a buffer overrun?
     */
    if (origNameLen < *secNameLen + 1) {
        /*
         * RETURN parse error, but it's really a parameter error 
         */
        return -1;
    }

    if (*secNameLen > 32) {
        /*
         * This is a USM-specific limitation over and above the above
         * limitation (which will probably default to the length of an
         * SnmpAdminString, i.e. 255).  See RFC 2574, sec. 2.4.  
         */
        return -1;
    }

    secName[*secNameLen] = '\0';

    if (type_value !=
        (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR)) {
        /*
         * RETURN parse error 
         */ return -1;
    }


    /*
     * Retrieve the signature and blank it if there.
     */
    DEBUGDUMPHEADER("recv", "msgAuthenticationParameters");
    if ((next_ptr
         = asn_parse_string(next_ptr, &remaining_bytes, &type_value,
                            signature, signature_length)) == NULL) {
        DEBUGINDENTLESS();
        /*
         * RETURN parse error 
         */ return -1;
    }
    DEBUGINDENTLESS();

    if (type_value !=
        (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR)) {
        /*
         * RETURN parse error 
         */ return -1;
    }

    if (*signature_length != 0) {       /* Blanking for authentication step later */
        memset(next_ptr - (u_long) * signature_length,
               0, *signature_length);
    }


    /*
     * Retrieve the salt.
     *
     * Note that the next ptr is where the data section starts.
     */
    DEBUGDUMPHEADER("recv", "msgPrivacyParameters");
    if ((*data_ptr
         = asn_parse_string(next_ptr, &remaining_bytes, &type_value,
                            salt, salt_length)) == NULL) {
        DEBUGINDENTLESS();
        /*
         * RETURN parse error 
         */ return -2;
    }
    DEBUGINDENTLESS();

    if (type_value !=
        (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR)) {
        /*
         * RETURN parse error 
         */ return -2;
    }

    return 0;

}                               /* end usm_parse_security_parameters() */

Project: net-snmp
File: snmpusm.c

get_default_privtype(size_t * len)
{
    if (defaultPrivType == NULL) {
        defaultPrivType = SNMP_DEFAULT_PRIV_PROTO;
        defaultPrivTypeLen = SNMP_DEFAULT_PRIV_PROTOLEN;
    }
    if (len)
        *len = defaultPrivTypeLen;
    return defaultPrivType;
}

Project: net-snmp
File: snmpusm.c

asn_predict_length(int type, u_char * ptr, size_t u_char_len)
{

    if (type & ASN_SEQUENCE)
        return 1 + 3 + u_char_len;

    if (type & ASN_INTEGER) {
        u_long          value;
        memcpy(&value, ptr, u_char_len);
        u_char_len = asn_predict_int_length(type, value, u_char_len);
    }

    if (u_char_len < 0x80)
        return 1 + 1 + u_char_len;
    else if (u_char_len < 0xFF)
        return 1 + 2 + u_char_len;
    else
        return 1 + 3 + u_char_len;

}                               /* end asn_predict_length() */

Project: net-snmp
File: snmp_client.c

_clone_pdu_header(netsnmp_pdu *pdu)
{
    netsnmp_pdu    *newpdu;
    struct snmp_secmod_def *sptr;
    int ret;

    if (!pdu)
        return NULL;

    newpdu = (netsnmp_pdu *) malloc(sizeof(netsnmp_pdu));
    if (!newpdu)
        return NULL;
    memmove(newpdu, pdu, sizeof(netsnmp_pdu));

    /*
     * reset copied pointers if copy fails 
     */
    newpdu->variables = NULL;
    newpdu->enterprise = NULL;
    newpdu->community = NULL;
    newpdu->securityEngineID = NULL;
    newpdu->securityName = NULL;
    newpdu->contextEngineID = NULL;
    newpdu->contextName = NULL;
    newpdu->transport_data = NULL;

    /*
     * copy buffers individually. If any copy fails, all are freed. 
     */
    if (snmp_clone_mem((void **) &newpdu->enterprise, pdu->enterprise,
                       sizeof(oid) * pdu->enterprise_length) ||
        snmp_clone_mem((void **) &newpdu->community, pdu->community,
                       pdu->community_len) ||
        snmp_clone_mem((void **) &newpdu->contextEngineID,
                       pdu->contextEngineID, pdu->contextEngineIDLen)
        || snmp_clone_mem((void **) &newpdu->securityEngineID,
                          pdu->securityEngineID, pdu->securityEngineIDLen)
        || snmp_clone_mem((void **) &newpdu->contextName, pdu->contextName,
                          pdu->contextNameLen)
        || snmp_clone_mem((void **) &newpdu->securityName,
                          pdu->securityName, pdu->securityNameLen)
        || snmp_clone_mem((void **) &newpdu->transport_data,
                          pdu->transport_data,
                          pdu->transport_data_length)) {
        snmp_free_pdu(newpdu);
        return NULL;
    }

    sptr = find_sec_mod(newpdu->securityModel);
    if (sptr && sptr->pdu_clone) {
        /* call security model if it needs to know about this */
        ret = sptr->pdu_clone(pdu, newpdu);
        if (ret) {
            snmp_free_pdu(newpdu);
            return NULL;
        }
    }

    return newpdu;
}

Project: net-snmp
File: snmpusm.c

usm_set_usmStateReference_sec_level(struct usmStateReference *ref,
                                    int sec_level)
{
    if (ref == NULL)
        return -1;
    ref->usr_sec_level = sec_level;
    return 0;
}

Project: net-snmp
File: snmp_client.c

int netsnmp_query_walk(netsnmp_variable_list *list,
                       netsnmp_session       *session) {
    /*
     * Create a working copy of the original (single)
     * varbind, so we can use this varbind parameter
     * to check when we've finished walking this subtree.
     */
    netsnmp_variable_list *vb = snmp_clone_varbind( list );
    netsnmp_variable_list *res_list = NULL;
    netsnmp_variable_list *res_last = NULL;
    int ret;

    /*
     * Now walk the tree as usual
     */
    ret = _query( vb, SNMP_MSG_GETNEXT, session );
    while ( ret == SNMP_ERR_NOERROR &&
        snmp_oidtree_compare( list->name, list->name_length,
                                vb->name,   vb->name_length ) == 0) {

	if (vb->type == SNMP_ENDOFMIBVIEW ||
	    vb->type == SNMP_NOSUCHOBJECT ||
	    vb->type == SNMP_NOSUCHINSTANCE)
	    break;

        /*
         * Copy each response varbind to the end of the result list
         * and then re-use this to ask for the next entry.
         */
        if ( res_last ) {
            res_last->next_variable = snmp_clone_varbind( vb );
            res_last = res_last->next_variable;
        } else {
            res_list = snmp_clone_varbind( vb );
            res_last = res_list;
        }
        ret = _query( vb, SNMP_MSG_GETNEXT, session );
    }
    /*
     * Copy the first result back into the original varbind parameter,
     * add the rest of the results (if any), and clean up.
     */
    if ( res_list ) {
        snmp_clone_var( res_list, list );
        list->next_variable = res_list->next_variable;
        res_list->next_variable = NULL;
        snmp_free_varbind( res_list );
    }
    snmp_free_varbind( vb );
    return ret;
}

Project: net-snmp
File: snmp_client.c

_clone_pdu(netsnmp_pdu *pdu, int drop_err)
{
    netsnmp_pdu    *newpdu;
    newpdu = _clone_pdu_header(pdu);
    newpdu = _copy_pdu_vars(pdu, newpdu, drop_err, 0, 10000);   /* skip none, copy all */

    return newpdu;
}

Project: net-snmp
File: snmpusm.c

usm_lookup_auth_str(int value)
{
    return usm_lookup_alg_str(value, usm_auth_type );
}

Project: net-snmp
File: snmp_client.c

_row_status_state_activate(netsnmp_state_machine_input *input,
                  netsnmp_state_machine_step *step)
{
    rowcreate_state       *ctx;
    netsnmp_variable_list *rs_var, *var = NULL;
    int32_t                rc, val = RS_ACTIVE;

    netsnmp_require_ptr_LRV( input, SNMPERR_GENERR );
    netsnmp_require_ptr_LRV( step, SNMPERR_GENERR );
    netsnmp_require_ptr_LRV( input->input_context, SNMPERR_GENERR );

    ctx = (rowcreate_state *)input->input_context;

    DEBUGMSGT(("row_create:called", "called %s\n", step->name));

    /*
     * just send the rowstatus varbind
     */
    rs_var = _get_vb_num(ctx->vars, ctx->row_status_index);
    netsnmp_require_ptr_LRV(rs_var, SNMPERR_GENERR);

    var = snmp_varlist_add_variable(&var, rs_var->name, rs_var->name_length,
                                    rs_var->type, &val, sizeof(val));
    netsnmp_require_ptr_LRV( var, SNMPERR_GENERR );

    /*
     * send set
     */
    rc = netsnmp_query_set( var, ctx->session );
    if (-2 == rc)
        rc = SNMPERR_ABORT;

    snmp_free_varbind(var);

    return rc;
}

Project: net-snmp
File: snmpusm.c

usm_create_usmUser_from_string(char *line, const char **errorMsg)
{
    char           *cp;
    const char     *dummy;
    char            buf[SNMP_MAXBUF_MEDIUM];
    struct usmUser *newuser;
    u_char          userKey[SNMP_MAXBUF_SMALL], *tmpp;
    size_t          userKeyLen = SNMP_MAXBUF_SMALL;
    size_t          privKeySize;
    size_t          ret;
    int             ret2, properLen, properPrivKeyLen;
    const oid      *def_auth_prot, *def_priv_prot;
    size_t          def_auth_prot_len, def_priv_prot_len;
    netsnmp_priv_alg_info *pai;

    def_auth_prot = get_default_authtype(&def_auth_prot_len);
    def_priv_prot = get_default_privtype(&def_priv_prot_len);

    if (NULL == line)
        return NULL;

#ifdef NETSNMP_ENABLE_TESTING_CODE
    DEBUGMSGTL(("usmUser", "new user %s\n", line)); /* logs passphrases */
#endif

    if (NULL == errorMsg)
        errorMsg = &dummy;
    *errorMsg = NULL; /* no errors yet */

    newuser = usm_create_user();
    if (newuser == NULL) {
        *errorMsg = "malloc failure creating new user";
        goto fail;
    }

    /*
     * READ: Security Name 
     */
    cp = copy_nword(line, buf, sizeof(buf));

    /*
     * check for (undocumented) 'keep master key' flag. so far, this is
     * just used for users for informs (who need non-localized keys).
     */
    if (strcmp(buf, "-M") == 0) {
        newuser->flags |= USMUSER_FLAG_KEEP_MASTER_KEY;
        cp = copy_nword(cp, buf, sizeof(buf));
    }

    /*
     * might be a -e ENGINEID argument 
     */
    if (strcmp(buf, "-e") == 0) {
        size_t          ebuf_len = 32, eout_len = 0;
        u_char         *ebuf = (u_char *) malloc(ebuf_len);

        if (ebuf == NULL) {
            *errorMsg = "malloc failure processing -e flag";
            goto fail;
        }

        /*
         * Get the specified engineid from the line.  
         */
        cp = copy_nword(cp, buf, sizeof(buf));
        if (!snmp_hex_to_binary(&ebuf, &ebuf_len, &eout_len, 1, buf)) {
            *errorMsg = "invalid EngineID argument to -e";
            SNMP_FREE(ebuf);
            goto fail;
        }

        newuser->engineID = ebuf;
        newuser->engineIDLen = eout_len;
        cp = copy_nword(cp, buf, sizeof(buf));
    } else {
        newuser->engineID = snmpv3_generate_engineID(&ret);
        if (ret == 0) {
            goto fail;
        }
        newuser->engineIDLen = ret;
    }

    newuser->secName = strdup(buf);
    newuser->name = strdup(buf);

    if (!cp) {
#ifdef NETSNMP_FORCE_SYSTEM_V3_AUTHPRIV
        /** no passwords ok iff defaults are noauth/nopriv */
        if (snmp_oid_compare(usmNoAuthProtocol, OID_LENGTH(usmNoAuthProtocol),
                             def_auth_prot, def_auth_prot_len) != 0) {
            *errorMsg = "no authentication pass phrase";
            goto fail;
        }
        if (snmp_oid_compare(usmNoPrivProtocol, OID_LENGTH(usmNoPrivProtocol),
                             def_priv_prot, def_priv_prot_len) != 0) {
            *errorMsg = "no privacy pass phrase";
            goto fail;
        }
#endif /* NETSNMP_FORCE_SYSTEM_V3_AUTHPRIV */
        goto add;               /* no authentication or privacy type */
    }

    /*
     * READ: Authentication Type 
     */
    newuser->authProtocol[0] = 0;
    cp = copy_nword(cp, buf, sizeof(buf));
    if ((strncmp(cp, "default", 7) == 0) && (NULL != def_auth_prot)) {
        SNMP_FREE(newuser->authProtocol);
        newuser->authProtocol = snmp_duplicate_objid(def_auth_prot,
                                                     def_auth_prot_len);
        if (newuser->authProtocol == NULL) {
            *errorMsg = "malloc failed";
            goto fail;
        }
        newuser->authProtocolLen = def_auth_prot_len;
    } else {
        const oid *auth_prot;
        int auth_type = usm_lookup_auth_type(buf);
        if (auth_type < 0) {
            *errorMsg = "unknown authProtocol";
            goto fail;
        }
        auth_prot = sc_get_auth_oid(auth_type, &newuser->authProtocolLen);
        if (auth_prot) {
            SNMP_FREE(newuser->authProtocol);
            newuser->authProtocol =
                snmp_duplicate_objid(auth_prot, newuser->authProtocolLen);
        }
        if (newuser->authProtocol == NULL) {
            *errorMsg = "malloc failed";
            goto fail;
        }
    }
    if (0 == newuser->authProtocol[0]) {
        *errorMsg = "Unknown authentication protocol";
        goto fail;
    }
#ifdef NETSNMP_FORCE_SYSTEM_V3_AUTHPRIV
    if (snmp_oid_compare(newuser->authProtocol, newuser->authProtocolLen,
                         def_auth_prot, def_auth_prot_len) != 0) {
        *errorMsg = "auth protocol does not match system policy";
        goto fail;
    }
#endif /* NETSNMP_FORCE_SYSTEM_V3_AUTHPRIV */

    /*
     * READ: Authentication Pass Phrase or key
     */
    cp = copy_nword(cp, buf, sizeof(buf));
    if (strcmp(buf,"-m") == 0) {
        /* a master key is specified */
        cp = copy_nword(cp, buf, sizeof(buf));
        ret = sizeof(userKey);
        tmpp = userKey;
        userKeyLen = 0;
        if (!snmp_hex_to_binary(&tmpp, &ret, &userKeyLen, 0, buf)) {
            *errorMsg = "invalid key value argument to -m";
            goto fail;
        }
        /* save master key */
        if (newuser->flags & USMUSER_FLAG_KEEP_MASTER_KEY) {
            newuser->authKeyKu = netsnmp_memdup(userKey, userKeyLen);
            newuser->authKeyKuLen = userKeyLen;
        }
    } else if (strcmp(buf,"-l") != 0) {
        /* a password is specified */
        userKeyLen = sizeof(userKey);
        ret2 = generate_Ku(newuser->authProtocol, newuser->authProtocolLen,
                          (u_char *) buf, strlen(buf), userKey, &userKeyLen);
        if (ret2 != SNMPERR_SUCCESS) {
            *errorMsg = "could not generate the authentication key from the supplied pass phrase.";
            goto fail;
        }
        /* save master key */
        if (newuser->flags & USMUSER_FLAG_KEEP_MASTER_KEY) {
            newuser->authKeyKu = netsnmp_memdup(userKey, userKeyLen);
            newuser->authKeyKuLen = userKeyLen;
        }
    }        
        
    /*
     * And turn it into a localized key 
     */
    properLen = sc_get_proper_auth_length_bytype(
        sc_get_authtype(newuser->authProtocol, newuser->authProtocolLen));
    if (properLen <= 0) {
        *errorMsg = "Could not get proper authentication protocol key length";
        goto fail;
    }
    newuser->authKey = (u_char *) malloc(properLen);
    newuser->authKeyLen = properLen;

    if (strcmp(buf,"-l") == 0) {
        /* a local key is directly specified */
        cp = copy_nword(cp, buf, sizeof(buf));
        ret = newuser->authKeyLen;
        newuser->authKeyLen = 0;
        if (!snmp_hex_to_binary(&newuser->authKey, &ret,
                                &newuser->authKeyLen, 0, buf)) {
            *errorMsg = "invalid key value argument to -l";
            goto fail;
        }
        if (properLen != newuser->authKeyLen) {
            *errorMsg = "improper key length to -l";
            goto fail;
        }
    } else {
        ret2 = generate_kul(newuser->authProtocol, newuser->authProtocolLen,
                           newuser->engineID, newuser->engineIDLen,
                           userKey, userKeyLen,
                           newuser->authKey, &newuser->authKeyLen);
        if (ret2 != SNMPERR_SUCCESS) {
            *errorMsg = "could not generate localized authentication key (Kul) from the master key (Ku).";
            goto fail;
        }
    }

    if (!cp) {
#ifndef NETSNMP_FORCE_SYSTEM_V3_AUTHPRIV
        goto add;               /* no privacy type (which is legal) */
#else
        if (snmp_oid_compare(usmNoPrivProtocol, OID_LENGTH(usmNoPrivProtocol),
                             def_priv_prot, def_priv_prot_len) == 0)
            goto add;
        else {
            *errorMsg = "priv protocol does not match system policy";
            goto fail;
        }
#endif /* NETSNMP_FORCE_SYSTEM_V3_AUTHPRIV */
    }

    /*
     * READ: Privacy Type 
     */
    newuser->privProtocol[0] = 0;
    cp = copy_nword(cp, buf, sizeof(buf));
    if ((strncmp(buf, "default", 7) == 0) && (NULL != def_priv_prot)) {
        SNMP_FREE(newuser->privProtocol);
        newuser->privProtocol =
            snmp_duplicate_objid(def_priv_prot, def_priv_prot_len);
        if (newuser->privProtocol == NULL) {
            *errorMsg = "malloc failed";
            goto fail;
        }
        newuser->privProtocolLen = def_priv_prot_len;
        pai = sc_get_priv_alg_byoid(newuser->privProtocol,
                                    newuser->privProtocolLen);
    } else {
        int priv_type = usm_lookup_priv_type(buf);
        if (priv_type < 0) {
            *errorMsg = "unknown privProtocol";
            DEBUGMSGTL(("usmUser", "%s %s\n", *errorMsg, buf));
            goto fail;
        }
        DEBUGMSGTL(("9:usmUser", "privProtocol %s\n", buf));
        pai = sc_get_priv_alg_bytype(priv_type);
        if (pai) {
            SNMP_FREE(newuser->privProtocol);
            newuser->privProtocolLen = pai->oid_len;
            newuser->privProtocol =
                snmp_duplicate_objid(pai->alg_oid, newuser->privProtocolLen);
            DEBUGMSGTL(("9:usmUser", "pai %s\n", pai->name));
            if (newuser->privProtocol == NULL) {
                *errorMsg = "malloc failed";
                goto fail;
            }
        }
    }
    if (NULL == pai) {
        *errorMsg = "priv protocol lookup failed";
        goto fail;
    }

    if (0 == newuser->privProtocol[0] && NULL == *errorMsg)
        *errorMsg = "Unknown privacy protocol";
    if (NULL != *errorMsg)
        goto fail;
#ifdef NETSNMP_FORCE_SYSTEM_V3_AUTHPRIV
    if (snmp_oid_compare(newuser->privProtocol, newuser->privProtocolLen,
                         def_priv_prot, def_priv_prot_len) != 0) {
        *errorMsg = "priv protocol does not match system policy";
        goto fail;
    }
#endif /* NETSNMP_FORCE_SYSTEM_V3_AUTHPRIV */

    properPrivKeyLen = pai->proper_length;
    if (USM_CREATE_USER_PRIV_DES == pai->type)
        properPrivKeyLen *= 2; /* ?? we store salt with key */

    /*
     * READ: Encryption Pass Phrase or key
     */
    if (!cp) {
        /*
         * assume the same as the authentication key 
         */
        newuser->privKey = netsnmp_memdup(newuser->authKey,
                                          newuser->authKeyLen);
        privKeySize = newuser->privKeyLen = newuser->authKeyLen;
        if (newuser->flags & USMUSER_FLAG_KEEP_MASTER_KEY) {
            newuser->privKeyKu = netsnmp_memdup(newuser->authKeyKu,
                                                newuser->authKeyKuLen);
            newuser->privKeyKuLen = newuser->authKeyKuLen;
        }
    } else {
        cp = copy_nword(cp, buf, sizeof(buf));
        
        if (strcmp(buf,"-m") == 0) {
            /* a master key is specified */
            cp = copy_nword(cp, buf, sizeof(buf));
            ret = sizeof(userKey);
            tmpp = userKey;
            userKeyLen = 0;
            if (!snmp_hex_to_binary(&tmpp, &ret, &userKeyLen, 0, buf)) {
                *errorMsg = "invalid key value argument to -m";
                goto fail;
            }
            /* save master key */
            if (newuser->flags & USMUSER_FLAG_KEEP_MASTER_KEY) {
                newuser->privKeyKu = netsnmp_memdup(userKey, userKeyLen);
                newuser->privKeyKuLen = userKeyLen;
            }
        } else if (strcmp(buf,"-l") != 0) {
            /* a password is specified */
            userKeyLen = sizeof(userKey);
            ret2 = generate_Ku(newuser->authProtocol, newuser->authProtocolLen,
                              (u_char*)buf, strlen(buf), userKey, &userKeyLen);
            if (ret2 != SNMPERR_SUCCESS) {
                *errorMsg = "could not generate the privacy key from the supplied pass phrase.";
                goto fail;
            }
            /* save master key */
            if (newuser->flags & USMUSER_FLAG_KEEP_MASTER_KEY) {
                newuser->privKeyKu = netsnmp_memdup(userKey, userKeyLen);
                newuser->privKeyKuLen = userKeyLen;
            }
        }

        /*
         * And turn it into a localized key
         * Allocate enough space for greater of auth mac and privKey len.
         */
        privKeySize = SNMP_MAX(properPrivKeyLen, properLen);
        newuser->privKey = (u_char *) malloc(privKeySize);
        newuser->privKeyLen = privKeySize;

        if (strcmp(buf,"-l") == 0) {
            /* a local key is directly specified */
            cp = copy_nword(cp, buf, sizeof(buf));
            ret = newuser->privKeyLen;
            newuser->privKeyLen = 0;
            if (!snmp_hex_to_binary(&newuser->privKey, &ret,
                                    &newuser->privKeyLen, 0, buf)) {
                *errorMsg = "invalid key value argument to -l";
                goto fail;
            }
        } else {
            ret2 = generate_kul(newuser->authProtocol, newuser->authProtocolLen,
                               newuser->engineID, newuser->engineIDLen,
                               userKey, userKeyLen,
                               newuser->privKey, &newuser->privKeyLen);
            if (ret2 != SNMPERR_SUCCESS) {
                *errorMsg = "could not generate localized privacy key (Kul) from the master key (Ku).";
                goto fail;
            }
        }

        if (newuser->privKeyLen < properPrivKeyLen) {
            ret = usm_extend_user_kul(newuser, properPrivKeyLen);
            if (ret != SNMPERR_SUCCESS) {
                *errorMsg = "could not extend localized privacy key to required length.";
                goto fail;
            }
        }
    }

    if ((newuser->privKeyLen >= properPrivKeyLen) || (properPrivKeyLen == 0)){
        DEBUGMSGTL(("9:usmUser", "truncating privKeyLen from %" NETSNMP_PRIz "d to %d\n",
                    newuser->privKeyLen, properPrivKeyLen));
        newuser->privKeyLen = properPrivKeyLen;
    }
    else {
        DEBUGMSGTL(("usmUser",
                    "privKey length %" NETSNMP_PRIz "d < %d required by privProtocol\n",
                    newuser->privKeyLen, properPrivKeyLen));
      *errorMsg = "privKey length is less than required by privProtocol";
      goto fail;
    }

  add:
    usm_add_user(newuser);
    DEBUGMSGTL(("usmUser", "created a new user %s at ", newuser->secName));
    DEBUGMSGHEX(("usmUser", newuser->engineID, newuser->engineIDLen));
    DEBUGMSG(("usmUser", "\n"));

    return newuser;

  fail:
    usm_free_user(newuser);
    return NULL;
}

Project: net-snmp
File: snmpusm.c

usm_set_usmStateReference_name(struct usmStateReference *ref,
                               char *name, size_t name_len)
{
    MAKE_ENTRY(ref, char, name, name_len, usr_name, usr_name_length);
}

Project: net-snmp
File: snmpusm.c

usm_clone(netsnmp_pdu *pdu, netsnmp_pdu *new_pdu)
{
    struct usmStateReference *ref = pdu->securityStateRef;
    struct usmStateReference **new_ref =
        (struct usmStateReference **)&new_pdu->securityStateRef;
    int ret = 0;

    if (!ref)
        return ret;

    if (pdu->command == SNMP_MSG_TRAP2) {
        netsnmp_assert(pdu->securityModel == SNMP_DEFAULT_SECMODEL);
        ret = usm_clone_usmStateReference(ref, new_ref);
    } else {
        netsnmp_assert(ref == *new_ref);
        ref->refcnt++;
    }

    return ret;
}

Project: net-snmp
File: snmp_client.c

snmp_set_var_value(netsnmp_variable_list * vars,
                   const void * value, size_t len)
{
    int             largeval = 1;

    /*
     * xxx-rks: why the unconditional free? why not use existing
     * memory, if len < vars->val_len ?
     */
    if (vars->val.string && vars->val.string != vars->buf) {
        free(vars->val.string);
    }
    vars->val.string = NULL;
    vars->val_len = 0;

    if (value == NULL && len > 0) {
        snmp_log(LOG_ERR, "bad size for NULL value\n");
        return 1;
    }

    /*
     * use built-in storage for smaller values 
     */
    if (len <= sizeof(vars->buf)) {
        vars->val.string = (u_char *) vars->buf;
        largeval = 0;
    }

    if ((0 == len) || (NULL == value)) {
        vars->val.string[0] = 0;
        return 0;
    }

    vars->val_len = len;
    switch (vars->type) {
    case ASN_INTEGER:
    case ASN_UNSIGNED:
    case ASN_TIMETICKS:
    case ASN_COUNTER:
    case ASN_UINTEGER:
        if (vars->val_len == sizeof(int)) {
            if (ASN_INTEGER == vars->type) {
                const int      *val_int 
                    = (const int *) value;
                *(vars->val.integer) = (long) *val_int;
            } else {
                const u_int    *val_uint
                    = (const u_int *) value;
                *(vars->val.integer) = (unsigned long) *val_uint;
            }
        }
#if SIZEOF_LONG != SIZEOF_INT
        else if (vars->val_len == sizeof(long)){
            const u_long   *val_ulong
                = (const u_long *) value;
            *(vars->val.integer) = *val_ulong;
            if (*(vars->val.integer) > 0xffffffff) {
                snmp_log(LOG_ERR,"truncating integer value > 32 bits\n");
                *(vars->val.integer) &= 0xffffffff;
            }
        }
#endif
#if defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG != SIZEOF_LONG_LONG)
#if !defined(SIZEOF_INTMAX_T) || (SIZEOF_LONG_LONG != SIZEOF_INTMAX_T)
        else if (vars->val_len == sizeof(long long)){
            const unsigned long long   *val_ullong
                = (const unsigned long long *) value;
            *(vars->val.integer) = (long) *val_ullong;
            if (*(vars->val.integer) > 0xffffffff) {
                snmp_log(LOG_ERR,"truncating integer value > 32 bits\n");
                *(vars->val.integer) &= 0xffffffff;
            }
        }
#endif
#endif
#if defined(SIZEOF_INTMAX_T) && (SIZEOF_LONG != SIZEOF_INTMAX_T)
        else if (vars->val_len == sizeof(intmax_t)){
            const uintmax_t *val_uintmax_t
                = (const uintmax_t *) value;
            *(vars->val.integer) = (long) *val_uintmax_t;
            if (*(vars->val.integer) > 0xffffffff) {
                snmp_log(LOG_ERR,"truncating integer value > 32 bits\n");
                *(vars->val.integer) &= 0xffffffff;
            }
        }
#endif
#if SIZEOF_SHORT != SIZEOF_INT
        else if (vars->val_len == sizeof(short)) {
            if (ASN_INTEGER == vars->type) {
                const short      *val_short 
                    = (const short *) value;
                *(vars->val.integer) = (long) *val_short;
            } else {
                const u_short    *val_ushort
                    = (const u_short *) value;
                *(vars->val.integer) = (unsigned long) *val_ushort;
            }
        }
#endif
        else if (vars->val_len == sizeof(char)) {
            if (ASN_INTEGER == vars->type) {
                const char      *val_char 
                    = (const char *) value;
                *(vars->val.integer) = (long) *val_char;
            } else {
                    const u_char    *val_uchar
                    = (const u_char *) value;
                *(vars->val.integer) = (unsigned long) *val_uchar;
            }
        }
        else {
            snmp_log(LOG_ERR,"bad size for integer-like type (%d)\n",
                     (int)vars->val_len);
            return (1);
        }
        vars->val_len = sizeof(long);
        break;

    case ASN_OBJECT_ID:
    case ASN_PRIV_IMPLIED_OBJECT_ID:
    case ASN_PRIV_INCL_RANGE:
    case ASN_PRIV_EXCL_RANGE:
        if (largeval) {
            vars->val.objid = (oid *) malloc(vars->val_len);
        }
        if (vars->val.objid == NULL) {
            snmp_log(LOG_ERR,"no storage for OID\n");
            return 1;
        }
        memmove(vars->val.objid, value, vars->val_len);
        break;

    case ASN_IPADDRESS: /* snmp_build_var_op treats IPADDR like a string */
        if (4 != vars->val_len) {
            netsnmp_assert("ipaddress length == 4");
        }
        /* FALL THROUGH */
    case ASN_PRIV_IMPLIED_OCTET_STR:
    case ASN_OCTET_STR:
    case ASN_BIT_STR:
    case ASN_OPAQUE:
    case ASN_NSAP:
        if (vars->val_len >= sizeof(vars->buf)) {
            vars->val.string = (u_char *) malloc(vars->val_len + 1);
        }
        if (vars->val.string == NULL) {
            snmp_log(LOG_ERR,"no storage for string\n");
            return 1;
        }
        memmove(vars->val.string, value, vars->val_len);
        /*
         * Make sure the string is zero-terminated; some bits of code make
         * this assumption.  Easier to do this here than fix all these wrong
         * assumptions.  
         */
        vars->val.string[vars->val_len] = '\0';
        break;

    case SNMP_NOSUCHOBJECT:
    case SNMP_NOSUCHINSTANCE:
    case SNMP_ENDOFMIBVIEW:
    case ASN_NULL:
        vars->val_len = 0;
        vars->val.string = NULL;
        break;

#ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
    case ASN_OPAQUE_U64:
    case ASN_OPAQUE_I64:
#endif                          /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */
    case ASN_COUNTER64:
        if (largeval) {
            snmp_log(LOG_ERR,"bad size for counter 64 (%d)\n",
                     (int)vars->val_len);
            return (1);
        }
        vars->val_len = sizeof(struct counter64);
        memmove(vars->val.counter64, value, vars->val_len);
        break;

#ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
    case ASN_OPAQUE_FLOAT:
        if (largeval) {
            snmp_log(LOG_ERR,"bad size for opaque float (%d)\n",
                     (int)vars->val_len);
            return (1);
        }
        vars->val_len = sizeof(float);
        memmove(vars->val.floatVal, value, vars->val_len);
        break;

    case ASN_OPAQUE_DOUBLE:
        if (largeval) {
            snmp_log(LOG_ERR,"bad size for opaque double (%d)\n",
                     (int)vars->val_len);
            return (1);
        }
        vars->val_len = sizeof(double);
        memmove(vars->val.doubleVal, value, vars->val_len);
        break;

#endif                          /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */

    default:
        snmp_log(LOG_ERR,"Internal error in type switching\n");
        snmp_set_detail("Internal error in type switching\n");
        return (1);
    }

    return 0;
}

Project: net-snmp
File: snmp_client.c

find_varbind_in_list( netsnmp_variable_list *vblist,
                      const oid *name, size_t len)
{
    for (; vblist != NULL; vblist = vblist->next_variable)
        if (!snmp_oid_compare(vblist->name, vblist->name_length, name, len))
            return vblist;

    return NULL;
}

Project: net-snmp
File: snmp_client.c

_row_status_state_single_value_cols(netsnmp_state_machine_input *input,
                                    netsnmp_state_machine_step *step)
{
    rowcreate_state       *ctx;
    netsnmp_variable_list *var, *tmp_next, *row_status;
    int                    rc = SNMPERR_GENERR;

    netsnmp_require_ptr_LRV( input, SNMPERR_GENERR );
    netsnmp_require_ptr_LRV( step, SNMPERR_GENERR );
    netsnmp_require_ptr_LRV( input->input_context, SNMPERR_GENERR );

    ctx = (rowcreate_state *)input->input_context;

    DEBUGMSGT(("row_create:called", "called %s\n", step->name));

    row_status = _get_vb_num(ctx->vars, ctx->row_status_index);
    netsnmp_require_ptr_LRV(row_status, SNMPERR_GENERR);

    /*
     * try one varbind at a time
     */
    for (var = ctx->vars; var; var = var->next_variable) {
        if (var == row_status)
            continue;

        tmp_next = var->next_variable;
        var->next_variable = NULL;

        /*
         * send set
         */
        rc = netsnmp_query_set( var, ctx->session );
        var->next_variable = tmp_next;
        if (-2 == rc)
            rc = SNMPERR_ABORT;
        if (rc != SNMPERR_SUCCESS)
            break;
    }

    return rc;
}

Project: net-snmp
File: snmpusm.c

usm_get_userList(void)
{
    return userList;
}

Project: net-snmp
File: snmpusm.c

usm_set_usmStateReference_auth_key(struct usmStateReference *ref,
                                   u_char * auth_key, size_t auth_key_len)
{
    MAKE_ENTRY(ref, u_char, auth_key, auth_key_len,
               usr_auth_key, usr_auth_key_length);
}

Project: net-snmp
File: snmpusm.c

usm_save_user(struct usmUser *user, const char *token, const char *type)
{
    char            line[4096];
    char           *cptr;

    memset(line, 0, sizeof(line));

    sprintf(line, "%s %d %d ", token, user->userStatus,
            user->userStorageType);
    cptr = &line[strlen(line)]; /* the NULL */
    cptr =
        read_config_save_octet_string(cptr, user->engineID,
                                      user->engineIDLen);
    *cptr++ = ' ';
    cptr = read_config_save_octet_string(cptr, (u_char *) user->name,
                                         (user->name == NULL) ? 0 :
                                         strlen(user->name));
    *cptr++ = ' ';
    cptr = read_config_save_octet_string(cptr, (u_char *) user->secName,
                                         (user->secName == NULL) ? 0 :
                                         strlen(user->secName));
    *cptr++ = ' ';
    cptr =
        read_config_save_objid(cptr, user->cloneFrom, user->cloneFromLen);
    *cptr++ = ' ';
    cptr = read_config_save_objid(cptr, user->authProtocol,
                                  user->authProtocolLen);
    *cptr++ = ' ';
    cptr =
        read_config_save_octet_string(cptr, user->authKey,
                                      user->authKeyLen);
    *cptr++ = ' ';
    cptr = read_config_save_objid(cptr, user->privProtocol,
                                  user->privProtocolLen);
    *cptr++ = ' ';
    cptr =
        read_config_save_octet_string(cptr, user->privKey,
                                      user->privKeyLen);
    *cptr++ = ' ';
    cptr = read_config_save_octet_string(cptr, user->userPublicString,
                                         user->userPublicStringLen);

    read_config_store(type, line);
}

Project: net-snmp
File: snmpusm.c

usm_lookup_alg_type(const char *str, usm_alg_type_t *types)
{
    int i, l;
    l = strlen(str);
    for (i = 0; types[i].label; ++i) {
        if (0 == strncasecmp(types[i].label, str, l))
            return types[i].value;
    }

    return -1;
}

Project: net-snmp
File: snmp_client.c

netsnmp_query_set_default_session( netsnmp_session *sess) {
    DEBUGMSGTL(("iquery", "set default session %p\n", sess));
    _def_query_session = sess;
}