Blame apps/snmpusm.c

Packit fcad23
/*
Packit fcad23
 * snmpusm.c - send snmp SET requests to a network entity to change the
Packit fcad23
 *             usm user database
Packit fcad23
 *
Packit fcad23
 * XXX get engineID dynamically.
Packit fcad23
 * XXX read passwords from prompts
Packit fcad23
 * XXX customize responses with user names, etc.
Packit fcad23
 */
Packit fcad23
/* Portions of this file are subject to the following copyright(s).  See
Packit fcad23
 * the Net-SNMP's COPYING file for more details and other copyrights
Packit fcad23
 * that may apply:
Packit fcad23
 */
Packit fcad23
/*
Packit fcad23
 * Portions of this file are copyrighted by:
Packit fcad23
 * Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
Packit fcad23
 * Use is subject to license terms specified in the COPYING file
Packit fcad23
 * distributed with the Net-SNMP package.
Packit fcad23
 */
Packit fcad23
#include <net-snmp/net-snmp-config.h>
Packit fcad23
Packit fcad23
#if HAVE_STDLIB_H
Packit fcad23
#include <stdlib.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_UNISTD_H
Packit fcad23
#include <unistd.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_STRING_H
Packit fcad23
#include <string.h>
Packit fcad23
#else
Packit fcad23
#include <strings.h>
Packit fcad23
#endif
Packit fcad23
#include <sys/types.h>
Packit fcad23
#if HAVE_NETINET_IN_H
Packit fcad23
#include <netinet/in.h>
Packit fcad23
#endif
Packit fcad23
#include <stdio.h>
Packit fcad23
#include <ctype.h>
Packit fcad23
#if TIME_WITH_SYS_TIME
Packit fcad23
# include <sys/time.h>
Packit fcad23
# include <time.h>
Packit fcad23
#else
Packit fcad23
# if HAVE_SYS_TIME_H
Packit fcad23
#  include <sys/time.h>
Packit fcad23
# else
Packit fcad23
#  include <time.h>
Packit fcad23
# endif
Packit fcad23
#endif
Packit fcad23
#if HAVE_SYS_SELECT_H
Packit fcad23
#include <sys/select.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_NETDB_H
Packit fcad23
#include <netdb.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_ARPA_INET_H
Packit fcad23
#include <arpa/inet.h>
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#if defined(HAVE_OPENSSL_DH_H) && defined(HAVE_LIBCRYPTO)
Packit fcad23
#include <openssl/dh.h>
Packit fcad23
#endif /* HAVE_OPENSSL_DH_H && HAVE_LIBCRYPTO */
Packit fcad23
Packit fcad23
#include <net-snmp/net-snmp-includes.h>
Packit fcad23
#include <net-snmp/library/snmp_openssl.h>
Packit fcad23
Packit fcad23
#define CMD_PASSWD_NAME    "passwd"
Packit fcad23
#define CMD_PASSWD         1
Packit fcad23
#define CMD_CREATE_NAME    "create"
Packit fcad23
#define CMD_CREATE         2
Packit fcad23
#define CMD_DELETE_NAME    "delete"
Packit fcad23
#define CMD_DELETE         3
Packit fcad23
#define CMD_CLONEFROM_NAME "cloneFrom"
Packit fcad23
#define CMD_CLONEFROM      4
Packit fcad23
#define CMD_ACTIVATE_NAME  "activate"
Packit fcad23
#define CMD_ACTIVATE       5
Packit fcad23
#define CMD_DEACTIVATE_NAME "deactivate"
Packit fcad23
#define CMD_DEACTIVATE     6
Packit fcad23
#define CMD_CHANGEKEY_NAME  "changekey"
Packit fcad23
#define CMD_CHANGEKEY      7
Packit fcad23
Packit fcad23
#define CMD_NUM    7
Packit fcad23
Packit fcad23
static const char *successNotes[CMD_NUM] = {
Packit fcad23
    "SNMPv3 Key(s) successfully changed.",
Packit fcad23
    "User successfully created.",
Packit fcad23
    "User successfully deleted.",
Packit fcad23
    "User successfully cloned.",
Packit fcad23
    "User successfully activated.",
Packit fcad23
    "User successfully deactivated.",
Packit fcad23
    "SNMPv3 Key(s) successfully changed."
Packit fcad23
};
Packit fcad23
Packit fcad23
#define                   USM_OID_LEN    12
Packit fcad23
#define                DH_USM_OID_LEN    11
Packit fcad23
Packit fcad23
static oid
Packit fcad23
Packit fcad23
authKeyOid[MAX_OID_LEN] = { 1, 3, 6, 1, 6, 3, 15, 1, 2, 2, 1, 6 },
Packit fcad23
ownAuthKeyOid[MAX_OID_LEN] = {1, 3, 6, 1, 6, 3, 15, 1, 2, 2, 1, 7},
Packit fcad23
privKeyOid[MAX_OID_LEN] = {1, 3, 6, 1, 6, 3, 15, 1, 2, 2, 1, 9},
Packit fcad23
ownPrivKeyOid[MAX_OID_LEN] = {1, 3, 6, 1, 6, 3, 15, 1, 2, 2, 1, 10},
Packit fcad23
usmUserCloneFrom[MAX_OID_LEN] = {1, 3, 6, 1, 6, 3, 15, 1, 2, 2, 1, 4},
Packit fcad23
usmUserSecurityName[MAX_OID_LEN] = {1, 3, 6, 1, 6, 3, 15, 1, 2, 2, 1, 3},
Packit fcad23
usmUserPublic[MAX_OID_LEN] = {1, 3, 6, 1, 6, 3, 15, 1, 2, 2, 1, 11},
Packit fcad23
usmUserStatus[MAX_OID_LEN] = {1, 3, 6, 1, 6, 3, 15, 1, 2, 2, 1, 13},
Packit fcad23
/* diffie helman change key objects */
Packit fcad23
usmDHUserAuthKeyChange[MAX_OID_LEN] = {1, 3, 6, 1, 3, 101, 1, 1, 2, 1, 1 },
Packit fcad23
usmDHUserPrivKeyChange[MAX_OID_LEN] = {1, 3, 6, 1, 3, 101, 1, 1, 2, 1, 3 },
Packit fcad23
#if defined(HAVE_OPENSSL_DH_H) && defined(HAVE_LIBCRYPTO)
Packit fcad23
usmDHUserOwnAuthKeyChange[MAX_OID_LEN] = {1, 3, 6, 1, 3, 101, 1, 1, 2, 1, 2 },
Packit fcad23
usmDHUserOwnPrivKeyChange[MAX_OID_LEN] = {1, 3, 6, 1, 3, 101, 1, 1, 2, 1, 4 },
Packit fcad23
#endif /* HAVE_OPENSSL_DH_H && HAVE_LIBCRYPTO */
Packit fcad23
usmDHParameters[] = { 1,3,6,1,3,101,1,1,1,0 }
Packit fcad23
;
Packit fcad23
size_t usmDHParameters_len = OID_LENGTH(usmDHParameters);
Packit fcad23
Packit fcad23
static
Packit fcad23
oid            *authKeyChange = authKeyOid, *privKeyChange = privKeyOid;
Packit fcad23
oid            *dhauthKeyChange = usmDHUserAuthKeyChange,
Packit fcad23
               *dhprivKeyChange = usmDHUserPrivKeyChange;
Packit fcad23
int             doauthkey = 0, doprivkey = 0, uselocalizedkey = 0;
Packit fcad23
size_t          usmUserEngineIDLen = 0;
Packit fcad23
u_char         *usmUserEngineID = NULL;
Packit fcad23
char           *usmUserPublic_val = NULL;
Packit fcad23
int             docreateandwait = 0;
Packit fcad23
Packit fcad23
Packit fcad23
void
Packit fcad23
usage(void)
Packit fcad23
{
Packit fcad23
    fprintf(stderr, "Usage: snmpusm ");
Packit fcad23
    snmp_parse_args_usage(stderr);
Packit fcad23
    fprintf(stderr, " COMMAND\n\n");
Packit fcad23
    snmp_parse_args_descriptions(stderr);
Packit fcad23
    fprintf(stderr, "\nsnmpusm commands:\n");
Packit fcad23
    fprintf(stderr, "  [options]               create     USER [CLONEFROM-USER]\n");
Packit fcad23
    fprintf(stderr, "  [options]               delete     USER\n");
Packit fcad23
    fprintf(stderr, "  [options]               activate   USER\n");
Packit fcad23
    fprintf(stderr, "  [options]               deactivate USER\n");
Packit fcad23
    fprintf(stderr, "  [options] [-Cw]         cloneFrom  USER CLONEFROM-USER\n");
Packit fcad23
    fprintf(stderr, "  [options] [-Ca] [-Cx]   changekey  [USER]\n");
Packit fcad23
    fprintf(stderr,
Packit fcad23
            "  [options] [-Ca] [-Cx]   passwd     OLD-PASSPHRASE NEW-PASSPHRASE [USER]\n");
Packit fcad23
    fprintf(stderr,
Packit fcad23
            "  [options] (-Ca|-Cx) -Ck passwd     OLD-KEY-OR-PASS NEW-KEY-OR-PASS [USER]\n");
Packit fcad23
    fprintf(stderr, "\nsnmpusm options:\n");
Packit fcad23
    fprintf(stderr, "\t-CE ENGINE-ID\tSet usmUserEngineID (e.g. 800000020109840301).\n");
Packit fcad23
    fprintf(stderr, "\t-Cp STRING\tSet usmUserPublic value to STRING.\n");
Packit fcad23
    fprintf(stderr, "\t-Cw\t\tCreate the user with createAndWait.\n");
Packit fcad23
    fprintf(stderr, "\t\t\t(it won't be active until you active it)\n");
Packit fcad23
    fprintf(stderr, "\t-Cx\t\tChange the privacy key.\n");
Packit fcad23
    fprintf(stderr, "\t-Ca\t\tChange the authentication key.\n");
Packit fcad23
    fprintf(stderr, "\t-Ck\t\tAllows one to use localized key (must start with 0x)\n");
Packit fcad23
    fprintf(stderr, "\t\t\tinstead of passphrase.\n");
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * setup_oid appends to the oid the index for the engineid/user 
Packit fcad23
 */
Packit fcad23
void
Packit fcad23
setup_oid(oid * it, size_t * len, u_char * id, size_t idlen,
Packit fcad23
          const char *user)
Packit fcad23
{
Packit fcad23
    int             i, itIndex = *len;
Packit fcad23
Packit fcad23
    *len = itIndex + 1 + idlen + 1 + strlen(user);
Packit fcad23
Packit fcad23
    it[itIndex++] = idlen;
Packit fcad23
    for (i = 0; i < (int) idlen; i++) {
Packit fcad23
        it[itIndex++] = id[i];
Packit fcad23
    }
Packit fcad23
Packit fcad23
    it[itIndex++] = strlen(user);
Packit fcad23
    for (i = 0; i < (int) strlen(user); i++) {
Packit fcad23
        it[itIndex++] = user[i];
Packit fcad23
    }
Packit fcad23
Packit fcad23
#ifdef NETSNMP_ENABLE_TESTING_CODE
Packit fcad23
    fprintf(stdout, "setup_oid: ");  
Packit fcad23
    fprint_objid(stdout, it, *len);  
Packit fcad23
    fprintf(stdout, "\n");  
Packit fcad23
#endif
Packit fcad23
}
Packit fcad23
Packit fcad23
#if defined(HAVE_OPENSSL_DH_H) && defined(HAVE_LIBCRYPTO)
Packit fcad23
int
Packit fcad23
get_USM_DH_key(netsnmp_variable_list *vars, netsnmp_variable_list *dhvar,
Packit fcad23
               size_t outkey_len,
Packit fcad23
               netsnmp_pdu *pdu, const char *keyname,
Packit fcad23
               oid *keyoid, size_t keyoid_len) {
Packit fcad23
    u_char *dhkeychange;
Packit fcad23
    DH *dh;
Packit fcad23
    const BIGNUM *p, *g, *pub_key;
Packit fcad23
    BIGNUM *other_pub;
Packit fcad23
    u_char *key;
Packit fcad23
    size_t key_len;
Packit fcad23
            
Packit fcad23
    dhkeychange = (u_char *) malloc(2 * vars->val_len * sizeof(char));
Packit fcad23
    if (!dhkeychange)
Packit fcad23
        return SNMPERR_GENERR;
Packit fcad23
    
Packit fcad23
    memcpy(dhkeychange, vars->val.string, vars->val_len);
Packit fcad23
Packit fcad23
    {
Packit fcad23
        const unsigned char *cp = dhvar->val.string;
Packit fcad23
        dh = d2i_DHparams(NULL, &cp, dhvar->val_len);
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (dh)
Packit fcad23
        DH_get0_pqg(dh, &p, NULL, &g);
Packit fcad23
Packit fcad23
    if (!dh || !g || !p) {
Packit fcad23
        SNMP_FREE(dhkeychange);
Packit fcad23
        return SNMPERR_GENERR;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (!DH_generate_key(dh)) {
Packit fcad23
        SNMP_FREE(dhkeychange);
Packit fcad23
        return SNMPERR_GENERR;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    DH_get0_key(dh, &pub_key, NULL);
Packit fcad23
    if (vars->val_len != (unsigned int)BN_num_bytes(pub_key)) {
Packit fcad23
        SNMP_FREE(dhkeychange);
Packit fcad23
        fprintf(stderr,"incorrect diffie-helman lengths (%lu != %d)\n",
Packit fcad23
                (unsigned long)vars->val_len, BN_num_bytes(pub_key));
Packit fcad23
        return SNMPERR_GENERR;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    BN_bn2bin(pub_key, dhkeychange + vars->val_len);
Packit fcad23
Packit fcad23
    key_len = DH_size(dh);
Packit fcad23
    if (!key_len) {
Packit fcad23
        SNMP_FREE(dhkeychange);
Packit fcad23
        return SNMPERR_GENERR;
Packit fcad23
    }
Packit fcad23
    key = (u_char *) malloc(key_len * sizeof(u_char));
Packit fcad23
Packit fcad23
    if (!key) {
Packit fcad23
        SNMP_FREE(dhkeychange);
Packit fcad23
        return SNMPERR_GENERR;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    other_pub = BN_bin2bn(vars->val.string, vars->val_len, NULL);
Packit fcad23
    if (!other_pub) {
Packit fcad23
        SNMP_FREE(dhkeychange);
Packit fcad23
        SNMP_FREE(key);
Packit fcad23
        return SNMPERR_GENERR;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (DH_compute_key(key, other_pub, dh)) {
Packit fcad23
        u_char *kp;
Packit fcad23
Packit fcad23
        printf("new %s key: 0x", keyname);
Packit fcad23
        for(kp = key + key_len - outkey_len;
Packit fcad23
            kp - key < (int)key_len;  kp++) {
Packit fcad23
            printf("%02x", (unsigned char) *kp);
Packit fcad23
        }
Packit fcad23
        printf("\n");
Packit fcad23
    }
Packit fcad23
Packit fcad23
    snmp_pdu_add_variable(pdu, keyoid, keyoid_len,
Packit fcad23
                          ASN_OCTET_STR, dhkeychange,
Packit fcad23
                          2 * vars->val_len);
Packit fcad23
Packit fcad23
    SNMP_FREE(dhkeychange);
Packit fcad23
    SNMP_FREE(other_pub);
Packit fcad23
    SNMP_FREE(key);
Packit fcad23
Packit fcad23
    return SNMPERR_SUCCESS;
Packit fcad23
}
Packit fcad23
#endif /* HAVE_OPENSSL_DH_H */
Packit fcad23
Packit fcad23
static void
Packit fcad23
optProc(int argc, char *const *argv, int opt)
Packit fcad23
{
Packit fcad23
    switch (opt) {
Packit fcad23
    case 'C':
Packit fcad23
        while (*optarg) {
Packit fcad23
            switch (*optarg++) {
Packit fcad23
            case 'a':
Packit fcad23
                doauthkey = 1;
Packit fcad23
                break;
Packit fcad23
Packit fcad23
            case 'x':
Packit fcad23
                doprivkey = 1;
Packit fcad23
                break;
Packit fcad23
Packit fcad23
	    case 'k':
Packit fcad23
	        uselocalizedkey = 1;
Packit fcad23
		break;
Packit fcad23
Packit fcad23
	    case 'p':
Packit fcad23
                if (optind < argc) {
Packit fcad23
		    usmUserPublic_val =  argv[optind];
Packit fcad23
                } else {
Packit fcad23
                    fprintf(stderr, "Bad -Cp option: no argument given\n");
Packit fcad23
                    exit(1);
Packit fcad23
                }
Packit fcad23
                optind++;
Packit fcad23
                break;
Packit fcad23
Packit fcad23
            case 'w':
Packit fcad23
                docreateandwait = 1;
Packit fcad23
                break;
Packit fcad23
Packit fcad23
	    case 'E': {
Packit fcad23
	        size_t ebuf_len = MAX_ENGINEID_LENGTH;
Packit fcad23
                u_char *ebuf;
Packit fcad23
                if (optind < argc) {
Packit fcad23
                    if (argv[optind]) {
Packit fcad23
                        ebuf = (u_char *)malloc(ebuf_len);
Packit fcad23
                        if (ebuf == NULL) {
Packit fcad23
                            fprintf(stderr, 
Packit fcad23
                                    "malloc failure processing -CE option.\n");
Packit fcad23
                            exit(1);
Packit fcad23
                        }
Packit fcad23
		        if (!snmp_hex_to_binary(&ebuf, &ebuf_len,
Packit fcad23
                                                &usmUserEngineIDLen, 1, argv[optind])) {
Packit fcad23
                            fprintf(stderr, 
Packit fcad23
                                    "Bad usmUserEngineID value after -CE option.\n");
Packit fcad23
		            free(ebuf);
Packit fcad23
		            exit(1);
Packit fcad23
		        }
Packit fcad23
		        usmUserEngineID = ebuf;
Packit fcad23
		        DEBUGMSGTL(("snmpusm", "usmUserEngineID set to: "));
Packit fcad23
		        DEBUGMSGHEX(("snmpusm", usmUserEngineID, usmUserEngineIDLen));
Packit fcad23
		        DEBUGMSG(("snmpusm", "\n"));
Packit fcad23
Packit fcad23
                    }
Packit fcad23
                } else {
Packit fcad23
                    fprintf(stderr, "Bad -CE option: no argument given\n");
Packit fcad23
                    exit(1);
Packit fcad23
                }
Packit fcad23
                optind++;
Packit fcad23
                break;
Packit fcad23
            }
Packit fcad23
Packit fcad23
            default:
Packit fcad23
                fprintf(stderr, "Unknown flag passed to -C: %c\n",
Packit fcad23
                        optarg[-1]);
Packit fcad23
                exit(1);
Packit fcad23
            }
Packit fcad23
        }
Packit fcad23
        break;
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
int
Packit fcad23
main(int argc, char *argv[])
Packit fcad23
{
Packit fcad23
    netsnmp_session session, *ss;
Packit fcad23
    netsnmp_pdu    *pdu = NULL, *response = NULL;
Packit fcad23
Packit fcad23
    int             arg;
Packit fcad23
    size_t          name_length = USM_OID_LEN;
Packit fcad23
    size_t          name_length2 = USM_OID_LEN;
Packit fcad23
    int             status;
Packit fcad23
    int             exitval = 1;
Packit fcad23
    int             rval;
Packit fcad23
    int             command = 0;
Packit fcad23
    long            longvar;
Packit fcad23
Packit fcad23
    size_t          oldKu_len = SNMP_MAXBUF_SMALL,
Packit fcad23
        newKu_len = SNMP_MAXBUF_SMALL,
Packit fcad23
        oldkul_len = SNMP_MAXBUF_SMALL,
Packit fcad23
        oldkulpriv_len = SNMP_MAXBUF_SMALL,
Packit fcad23
        newkulpriv_len = SNMP_MAXBUF_SMALL,
Packit fcad23
        newkul_len = SNMP_MAXBUF_SMALL,
Packit fcad23
        keychange_len = SNMP_MAXBUF_SMALL,
Packit fcad23
        keychangepriv_len = SNMP_MAXBUF_SMALL;
Packit fcad23
Packit fcad23
    char           *newpass = NULL, *oldpass = NULL;
Packit fcad23
    u_char          oldKu[SNMP_MAXBUF_SMALL],
Packit fcad23
        newKu[SNMP_MAXBUF_SMALL],
Packit fcad23
        oldkul[SNMP_MAXBUF_SMALL],
Packit fcad23
        oldkulpriv[SNMP_MAXBUF_SMALL],
Packit fcad23
        newkulpriv[SNMP_MAXBUF_SMALL],
Packit fcad23
        newkul[SNMP_MAXBUF_SMALL], keychange[SNMP_MAXBUF_SMALL],
Packit fcad23
        keychangepriv[SNMP_MAXBUF_SMALL];
Packit fcad23
Packit fcad23
    SOCK_STARTUP;
Packit fcad23
Packit fcad23
    authKeyChange = authKeyOid;
Packit fcad23
    privKeyChange = privKeyOid;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * get the common command line arguments 
Packit fcad23
     */
Packit fcad23
    switch (arg = snmp_parse_args(argc, argv, &session, "C:", optProc)) {
Packit fcad23
    case NETSNMP_PARSE_ARGS_ERROR:
Packit fcad23
        goto out;
Packit fcad23
    case NETSNMP_PARSE_ARGS_SUCCESS_EXIT:
Packit fcad23
        exitval = 0;
Packit fcad23
        goto out;
Packit fcad23
    case NETSNMP_PARSE_ARGS_ERROR_USAGE:
Packit fcad23
        usage();
Packit fcad23
        goto out;
Packit fcad23
    default:
Packit fcad23
        break;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (arg >= argc) {
Packit fcad23
        fprintf(stderr, "Please specify an operation to perform.\n");
Packit fcad23
        usage();
Packit fcad23
        goto out;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * open an SNMP session 
Packit fcad23
     */
Packit fcad23
    /*
Packit fcad23
     * Note:  this needs to obtain the engineID used below 
Packit fcad23
     */
Packit fcad23
    session.flags &= ~SNMP_FLAGS_DONT_PROBE;
Packit fcad23
    ss = snmp_open(&session);
Packit fcad23
    if (ss == NULL) {
Packit fcad23
        /*
Packit fcad23
         * diagnose snmp_open errors with the input netsnmp_session pointer 
Packit fcad23
         */
Packit fcad23
        snmp_sess_perror("snmpusm", &session);
Packit fcad23
        goto out;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * set usmUserEngineID from ss->contextEngineID
Packit fcad23
     *   if not already set (via -CE)
Packit fcad23
     */
Packit fcad23
    if (usmUserEngineID == NULL) {
Packit fcad23
      usmUserEngineID    = ss->contextEngineID;
Packit fcad23
      usmUserEngineIDLen = ss->contextEngineIDLen;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * create PDU for SET request and add object names and values to request 
Packit fcad23
     */
Packit fcad23
    pdu = snmp_pdu_create(SNMP_MSG_SET);
Packit fcad23
    if (!pdu) {
Packit fcad23
        fprintf(stderr, "Failed to create request\n");
Packit fcad23
        goto close_session;
Packit fcad23
    }
Packit fcad23
Packit fcad23
Packit fcad23
    if (strcmp(argv[arg], CMD_PASSWD_NAME) == 0) {
Packit fcad23
Packit fcad23
        /*
Packit fcad23
         * passwd: change a users password.
Packit fcad23
         *
Packit fcad23
         * XXX:  Uses the auth type of the calling user, a MD5 user can't
Packit fcad23
         *       change a SHA user's key.
Packit fcad23
         */
Packit fcad23
        char *passwd_user;
Packit fcad23
Packit fcad23
        command = CMD_PASSWD;
Packit fcad23
        oldpass = argv[++arg];
Packit fcad23
        newpass = argv[++arg];
Packit fcad23
        passwd_user = argv[++arg];
Packit fcad23
Packit fcad23
        if (doprivkey == 0 && doauthkey == 0)
Packit fcad23
            doprivkey = doauthkey = 1;
Packit fcad23
Packit fcad23
        if (newpass == NULL || strlen(newpass) < USM_LENGTH_P_MIN) {
Packit fcad23
            fprintf(stderr,
Packit fcad23
                    "New passphrase must be greater than %d characters in length.\n",
Packit fcad23
                    USM_LENGTH_P_MIN);
Packit fcad23
            goto close_session;
Packit fcad23
        }
Packit fcad23
Packit fcad23
        if (oldpass == NULL || strlen(oldpass) < USM_LENGTH_P_MIN) {
Packit fcad23
            fprintf(stderr,
Packit fcad23
                    "Old passphrase must be greater than %d characters in length.\n",
Packit fcad23
                    USM_LENGTH_P_MIN);
Packit fcad23
            goto close_session;
Packit fcad23
        }
Packit fcad23
Packit fcad23
        DEBUGMSGTL(("9:usm:passwd", "oldpass len %" NETSNMP_PRIz "d, newpass len %" NETSNMP_PRIz "d\n",
Packit fcad23
                    strlen(oldpass), strlen(newpass)));
Packit fcad23
Packit fcad23
        /* 
Packit fcad23
         * Change the user supplied on command line.
Packit fcad23
         */
Packit fcad23
        if ((passwd_user != NULL) && (strlen(passwd_user) > 0)) {
Packit fcad23
            session.securityName = passwd_user;
Packit fcad23
        } else {
Packit fcad23
            /*
Packit fcad23
             * Use own key object if no user was supplied.
Packit fcad23
             */
Packit fcad23
            authKeyChange = ownAuthKeyOid;
Packit fcad23
            privKeyChange = ownPrivKeyOid;
Packit fcad23
        }
Packit fcad23
Packit fcad23
        /*
Packit fcad23
         * do we have a securityName?  If not, copy the default 
Packit fcad23
         */
Packit fcad23
        if (session.securityName == NULL) {
Packit fcad23
            session.securityName = 
Packit fcad23
	      strdup(netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 
Packit fcad23
					   NETSNMP_DS_LIB_SECNAME));
Packit fcad23
        }
Packit fcad23
Packit fcad23
        /*
Packit fcad23
         * the old Ku is in the session, but we need the new one 
Packit fcad23
         */
Packit fcad23
        if (session.securityAuthProto == NULL) {
Packit fcad23
            /*
Packit fcad23
             * get .conf set default 
Packit fcad23
             */
Packit fcad23
            const oid      *def =
Packit fcad23
                get_default_authtype(&session.securityAuthProtoLen);
Packit fcad23
            session.securityAuthProto =
Packit fcad23
                snmp_duplicate_objid(def, session.securityAuthProtoLen);
Packit fcad23
        }
Packit fcad23
        if (session.securityAuthProto == NULL) {
Packit fcad23
            /*
Packit fcad23
             * assume MD5 
Packit fcad23
             */
Packit fcad23
#ifndef NETSNMP_DISABLE_MD5
Packit fcad23
            session.securityAuthProtoLen =
Packit fcad23
                sizeof(usmHMACMD5AuthProtocol) / sizeof(oid);
Packit fcad23
            session.securityAuthProto =
Packit fcad23
                snmp_duplicate_objid(usmHMACMD5AuthProtocol,
Packit fcad23
                                     session.securityAuthProtoLen);
Packit fcad23
#else
Packit fcad23
            session.securityAuthProtoLen =
Packit fcad23
                sizeof(usmHMACSHA1AuthProtocol) / sizeof(oid);
Packit fcad23
            session.securityAuthProto =
Packit fcad23
                snmp_duplicate_objid(usmHMACSHA1AuthProtocol,
Packit fcad23
                                     session.securityAuthProtoLen);
Packit fcad23
#endif
Packit fcad23
Packit fcad23
        }
Packit fcad23
Packit fcad23
	if (uselocalizedkey && (strncmp(oldpass, "0x", 2) == 0)) {
Packit fcad23
	    /*
Packit fcad23
	     * use the localized key from the command line
Packit fcad23
	     */
Packit fcad23
	    u_char *buf;
Packit fcad23
	    size_t buf_len = SNMP_MAXBUF_SMALL;
Packit fcad23
	    buf = (u_char *) malloc (buf_len * sizeof(u_char));
Packit fcad23
Packit fcad23
	    oldkul_len = 0; /* initialize the offset */
Packit fcad23
	    if (!snmp_hex_to_binary((u_char **) (&buf), &buf_len, &oldkul_len, 0, oldpass)) {
Packit fcad23
	      snmp_perror(argv[0]);
Packit fcad23
	      fprintf(stderr, "generating the old Kul from localized key failed\n");
Packit fcad23
	      goto close_session;
Packit fcad23
	    }
Packit fcad23
	    
Packit fcad23
	    memcpy(oldkul, buf, oldkul_len);
Packit fcad23
	    SNMP_FREE(buf);
Packit fcad23
	}
Packit fcad23
	else {
Packit fcad23
	    /*
Packit fcad23
	     * the old Ku is in the session, but we need the new one 
Packit fcad23
	     */
Packit fcad23
	    rval = generate_Ku(session.securityAuthProto,
Packit fcad23
			       session.securityAuthProtoLen,
Packit fcad23
			       (u_char *) oldpass, strlen(oldpass),
Packit fcad23
			       oldKu, &oldKu_len);
Packit fcad23
	    
Packit fcad23
	    if (rval != SNMPERR_SUCCESS) {
Packit fcad23
	        snmp_perror(argv[0]);
Packit fcad23
	        fprintf(stderr, "generating the old Ku failed\n");
Packit fcad23
	        goto close_session;
Packit fcad23
	    }
Packit fcad23
Packit fcad23
	    /*
Packit fcad23
	     * generate the two Kul's 
Packit fcad23
	     */
Packit fcad23
	    rval = generate_kul(session.securityAuthProto,
Packit fcad23
				session.securityAuthProtoLen,
Packit fcad23
				usmUserEngineID, usmUserEngineIDLen,
Packit fcad23
				oldKu, oldKu_len, oldkul, &oldkul_len);
Packit fcad23
	    
Packit fcad23
	    if (rval != SNMPERR_SUCCESS) {
Packit fcad23
	        snmp_perror(argv[0]);
Packit fcad23
		fprintf(stderr, "generating the old Kul failed\n");
Packit fcad23
		goto close_session;
Packit fcad23
	    }
Packit fcad23
            DEBUGMSGTL(("9:usm:passwd", "oldkul len %" NETSNMP_PRIz "d\n", oldkul_len));
Packit fcad23
	}
Packit fcad23
	if (uselocalizedkey && (strncmp(newpass, "0x", 2) == 0)) {
Packit fcad23
	    /*
Packit fcad23
	     * use the localized key from the command line
Packit fcad23
	     */
Packit fcad23
	    u_char *buf;
Packit fcad23
	    size_t buf_len = SNMP_MAXBUF_SMALL;
Packit fcad23
	    buf = (u_char *) malloc (buf_len * sizeof(u_char));
Packit fcad23
Packit fcad23
	    newkul_len = 0; /* initialize the offset */
Packit fcad23
	    if (!snmp_hex_to_binary((u_char **) (&buf), &buf_len, &newkul_len, 0, newpass)) {
Packit fcad23
	      snmp_perror(argv[0]);
Packit fcad23
	      fprintf(stderr, "generating the new Kul from localized key failed\n");
Packit fcad23
	      goto close_session;
Packit fcad23
	    }
Packit fcad23
	    
Packit fcad23
	    memcpy(newkul, buf, newkul_len);
Packit fcad23
	    SNMP_FREE(buf);
Packit fcad23
	} else {
Packit fcad23
            rval = generate_Ku(session.securityAuthProto,
Packit fcad23
                               session.securityAuthProtoLen,
Packit fcad23
                               (u_char *) newpass, strlen(newpass),
Packit fcad23
                               newKu, &newKu_len);
Packit fcad23
Packit fcad23
            if (rval != SNMPERR_SUCCESS) {
Packit fcad23
                snmp_perror(argv[0]);
Packit fcad23
                fprintf(stderr, "generating the new Ku failed\n");
Packit fcad23
                goto close_session;
Packit fcad23
            }
Packit fcad23
Packit fcad23
	    rval = generate_kul(session.securityAuthProto,
Packit fcad23
				session.securityAuthProtoLen,
Packit fcad23
				usmUserEngineID, usmUserEngineIDLen,
Packit fcad23
				newKu, newKu_len, newkul, &newkul_len);
Packit fcad23
Packit fcad23
	    if (rval != SNMPERR_SUCCESS) {
Packit fcad23
	        snmp_perror(argv[0]);
Packit fcad23
		fprintf(stderr, "generating the new Kul failed\n");
Packit fcad23
		goto close_session;
Packit fcad23
	    }
Packit fcad23
            DEBUGMSGTL(("9:usm:passwd", "newkul len %" NETSNMP_PRIz "d\n", newkul_len));
Packit fcad23
	}
Packit fcad23
Packit fcad23
        /*
Packit fcad23
         * for encryption, we may need to truncate the key to the proper length
Packit fcad23
         * so we need two copies.  For simplicity, we always just copy even if
Packit fcad23
         * they're the same lengths.
Packit fcad23
         */
Packit fcad23
        if (doprivkey) {
Packit fcad23
            int privtype, properlength;
Packit fcad23
            u_char *okp = oldkulpriv, *nkp = newkulpriv;
Packit fcad23
            if (!session.securityPrivProto) {
Packit fcad23
                snmp_log(LOG_ERR, "no encryption type specified, which I need in order to know to change the key\n");
Packit fcad23
                goto close_session;
Packit fcad23
            }
Packit fcad23
Packit fcad23
            privtype = sc_get_privtype(session.securityPrivProto,
Packit fcad23
                                       session.securityPrivProtoLen);
Packit fcad23
            properlength = sc_get_proper_priv_length_bytype(privtype);
Packit fcad23
            if (USM_CREATE_USER_PRIV_DES == privtype)
Packit fcad23
                properlength *= 2; /* ?? we store salt with key */
Packit fcad23
            DEBUGMSGTL(("9:usm:passwd", "proper len %d\n", properlength));
Packit fcad23
            oldkulpriv_len = oldkul_len;
Packit fcad23
            newkulpriv_len = newkul_len;
Packit fcad23
            memcpy(oldkulpriv, oldkul, oldkulpriv_len);
Packit fcad23
            memcpy(newkulpriv, newkul, newkulpriv_len);
Packit fcad23
Packit fcad23
            if (oldkulpriv_len > properlength) {
Packit fcad23
                oldkulpriv_len = newkulpriv_len = properlength;
Packit fcad23
            }
Packit fcad23
            else if (oldkulpriv_len < properlength) {
Packit fcad23
                rval = netsnmp_extend_kul(properlength,
Packit fcad23
                                          session.securityAuthProto,
Packit fcad23
                                          session.securityAuthProtoLen,
Packit fcad23
                                          privtype,
Packit fcad23
                                          usmUserEngineID, usmUserEngineIDLen,
Packit fcad23
                                          &okp, &oldkulpriv_len,
Packit fcad23
                                          sizeof(oldkulpriv));
Packit fcad23
                rval = netsnmp_extend_kul(properlength,
Packit fcad23
                                          session.securityAuthProto,
Packit fcad23
                                          session.securityAuthProtoLen,
Packit fcad23
                                          privtype,
Packit fcad23
                                          usmUserEngineID, usmUserEngineIDLen,
Packit fcad23
                                          &nkp, &newkulpriv_len,
Packit fcad23
                                          sizeof(newkulpriv));
Packit fcad23
            }
Packit fcad23
        }
Packit fcad23
Packit fcad23
        /*
Packit fcad23
         * create the keychange string 
Packit fcad23
         */
Packit fcad23
	if (doauthkey) {
Packit fcad23
	  rval = encode_keychange(session.securityAuthProto,
Packit fcad23
				  session.securityAuthProtoLen,
Packit fcad23
				  oldkul, oldkul_len,
Packit fcad23
				  newkul, newkul_len,
Packit fcad23
				  keychange, &keychange_len);
Packit fcad23
Packit fcad23
	  if (rval != SNMPERR_SUCCESS) {
Packit fcad23
	    snmp_perror(argv[0]);
Packit fcad23
            fprintf(stderr, "encoding the keychange failed\n");
Packit fcad23
            usage();
Packit fcad23
            goto close_session;
Packit fcad23
	  }
Packit fcad23
	}
Packit fcad23
Packit fcad23
        /* which is slightly different for encryption if lengths are
Packit fcad23
           different */
Packit fcad23
	if (doprivkey) {
Packit fcad23
            DEBUGMSGTL(("9:usm:passwd:encode", "proper len %" NETSNMP_PRIz "d, old_len %" NETSNMP_PRIz "d, new_len %" NETSNMP_PRIz "d\n",
Packit fcad23
                        oldkulpriv_len, oldkulpriv_len, newkulpriv_len));
Packit fcad23
	  rval = encode_keychange(session.securityAuthProto,
Packit fcad23
                                session.securityAuthProtoLen,
Packit fcad23
                                oldkulpriv, oldkulpriv_len,
Packit fcad23
                                newkulpriv, newkulpriv_len,
Packit fcad23
                                keychangepriv, &keychangepriv_len);
Packit fcad23
Packit fcad23
          DEBUGMSGTL(("9:usm:passwd:encode", "keychange len %" NETSNMP_PRIz "d\n",
Packit fcad23
                      keychangepriv_len));
Packit fcad23
	  if (rval != SNMPERR_SUCCESS) {
Packit fcad23
            snmp_perror(argv[0]);
Packit fcad23
            fprintf(stderr, "encoding the keychange failed\n");
Packit fcad23
            usage();
Packit fcad23
            goto close_session;
Packit fcad23
	  }
Packit fcad23
	}
Packit fcad23
Packit fcad23
        /*
Packit fcad23
         * add the keychange string to the outgoing packet 
Packit fcad23
         */
Packit fcad23
        if (doauthkey) {
Packit fcad23
            setup_oid(authKeyChange, &name_length,
Packit fcad23
                      usmUserEngineID, usmUserEngineIDLen,
Packit fcad23
                      session.securityName);
Packit fcad23
            snmp_pdu_add_variable(pdu, authKeyChange, name_length,
Packit fcad23
                                  ASN_OCTET_STR, keychange, keychange_len);
Packit fcad23
        }
Packit fcad23
        if (doprivkey) {
Packit fcad23
            setup_oid(privKeyChange, &name_length2,
Packit fcad23
                      usmUserEngineID, usmUserEngineIDLen,
Packit fcad23
                      session.securityName);
Packit fcad23
            snmp_pdu_add_variable(pdu, privKeyChange, name_length2,
Packit fcad23
                                  ASN_OCTET_STR,
Packit fcad23
                                  keychangepriv, keychangepriv_len);
Packit fcad23
        }
Packit fcad23
Packit fcad23
    } else if (strcmp(argv[arg], CMD_CREATE_NAME) == 0) {
Packit fcad23
        /*
Packit fcad23
         * create:  create a user
Packit fcad23
         *
Packit fcad23
         * create USER [CLONEFROM]
Packit fcad23
         */
Packit fcad23
        if (++arg >= argc) {
Packit fcad23
            fprintf(stderr, "You must specify the user name to create\n");
Packit fcad23
            usage();
Packit fcad23
            goto close_session;
Packit fcad23
        }
Packit fcad23
Packit fcad23
        command = CMD_CREATE;
Packit fcad23
Packit fcad23
        if (++arg < argc) {
Packit fcad23
            /*
Packit fcad23
             * clone the new user from an existing user
Packit fcad23
             *   (and make them active immediately)
Packit fcad23
             */
Packit fcad23
            setup_oid(usmUserStatus, &name_length,
Packit fcad23
                      usmUserEngineID, usmUserEngineIDLen, argv[arg-1]);
Packit fcad23
            if (docreateandwait) {
Packit fcad23
                longvar = RS_CREATEANDWAIT;
Packit fcad23
            } else {
Packit fcad23
                longvar = RS_CREATEANDGO;
Packit fcad23
            }
Packit fcad23
            snmp_pdu_add_variable(pdu, usmUserStatus, name_length,
Packit fcad23
                                  ASN_INTEGER, (u_char *) & longvar,
Packit fcad23
                                  sizeof(longvar));
Packit fcad23
Packit fcad23
            name_length = USM_OID_LEN;
Packit fcad23
            setup_oid(usmUserCloneFrom, &name_length,
Packit fcad23
                      usmUserEngineID, usmUserEngineIDLen,
Packit fcad23
                      argv[arg - 1]);
Packit fcad23
            setup_oid(usmUserSecurityName, &name_length2,
Packit fcad23
                      usmUserEngineID, usmUserEngineIDLen,
Packit fcad23
                      argv[arg]);
Packit fcad23
            snmp_pdu_add_variable(pdu, usmUserCloneFrom, name_length,
Packit fcad23
                                  ASN_OBJECT_ID,
Packit fcad23
                                  (u_char *) usmUserSecurityName,
Packit fcad23
                                  sizeof(oid) * name_length2);
Packit fcad23
        } else {
Packit fcad23
            /*
Packit fcad23
             * create a new (unauthenticated) user from scratch
Packit fcad23
             * The Net-SNMP agent won't allow such a user to be made active.
Packit fcad23
             */
Packit fcad23
            setup_oid(usmUserStatus, &name_length,
Packit fcad23
                      usmUserEngineID, usmUserEngineIDLen, argv[arg-1]);
Packit fcad23
            longvar = RS_CREATEANDWAIT;
Packit fcad23
            snmp_pdu_add_variable(pdu, usmUserStatus, name_length,
Packit fcad23
                                  ASN_INTEGER, (u_char *) & longvar,
Packit fcad23
                                  sizeof(longvar));
Packit fcad23
        }
Packit fcad23
Packit fcad23
    } else if (strcmp(argv[arg], CMD_CLONEFROM_NAME) == 0) {
Packit fcad23
        /*
Packit fcad23
         * create:  clone a user from another
Packit fcad23
         *
Packit fcad23
         * cloneFrom USER FROM
Packit fcad23
         */
Packit fcad23
        if (++arg >= argc) {
Packit fcad23
            fprintf(stderr,
Packit fcad23
                    "You must specify the user name to operate on\n");
Packit fcad23
            usage();
Packit fcad23
            goto close_session;
Packit fcad23
        }
Packit fcad23
Packit fcad23
        command = CMD_CLONEFROM;
Packit fcad23
        setup_oid(usmUserStatus, &name_length,
Packit fcad23
                  usmUserEngineID, usmUserEngineIDLen, argv[arg]);
Packit fcad23
        longvar = RS_ACTIVE;
Packit fcad23
        snmp_pdu_add_variable(pdu, usmUserStatus, name_length,
Packit fcad23
                              ASN_INTEGER, (u_char *) & longvar,
Packit fcad23
                              sizeof(longvar));
Packit fcad23
        name_length = USM_OID_LEN;
Packit fcad23
        setup_oid(usmUserCloneFrom, &name_length,
Packit fcad23
                  usmUserEngineID, usmUserEngineIDLen, argv[arg]);
Packit fcad23
Packit fcad23
        if (++arg >= argc) {
Packit fcad23
            fprintf(stderr,
Packit fcad23
                    "You must specify the user name to clone from\n");
Packit fcad23
            usage();
Packit fcad23
            goto close_session;
Packit fcad23
        }
Packit fcad23
Packit fcad23
        setup_oid(usmUserSecurityName, &name_length2,
Packit fcad23
                  usmUserEngineID, usmUserEngineIDLen, argv[arg]);
Packit fcad23
        snmp_pdu_add_variable(pdu, usmUserCloneFrom, name_length,
Packit fcad23
                              ASN_OBJECT_ID,
Packit fcad23
                              (u_char *) usmUserSecurityName,
Packit fcad23
                              sizeof(oid) * name_length2);
Packit fcad23
Packit fcad23
    } else if (strcmp(argv[arg], CMD_DELETE_NAME) == 0) {
Packit fcad23
        /*
Packit fcad23
         * delete:  delete a user
Packit fcad23
         *
Packit fcad23
         * delete USER
Packit fcad23
         */
Packit fcad23
        if (++arg >= argc) {
Packit fcad23
            fprintf(stderr, "You must specify the user name to delete\n");
Packit fcad23
            goto close_session;
Packit fcad23
        }
Packit fcad23
Packit fcad23
        command = CMD_DELETE;
Packit fcad23
        setup_oid(usmUserStatus, &name_length,
Packit fcad23
                  usmUserEngineID, usmUserEngineIDLen, argv[arg]);
Packit fcad23
        longvar = RS_DESTROY;
Packit fcad23
        snmp_pdu_add_variable(pdu, usmUserStatus, name_length,
Packit fcad23
                              ASN_INTEGER, (u_char *) & longvar,
Packit fcad23
                              sizeof(longvar));
Packit fcad23
    } else if (strcmp(argv[arg], CMD_ACTIVATE_NAME) == 0) {
Packit fcad23
        /*
Packit fcad23
         * activate:  activate a user
Packit fcad23
         *
Packit fcad23
         * activate USER
Packit fcad23
         */
Packit fcad23
        if (++arg >= argc) {
Packit fcad23
            fprintf(stderr, "You must specify the user name to activate\n");
Packit fcad23
            goto close_session;
Packit fcad23
        }
Packit fcad23
Packit fcad23
        command = CMD_ACTIVATE;
Packit fcad23
        setup_oid(usmUserStatus, &name_length,
Packit fcad23
                  usmUserEngineID, usmUserEngineIDLen, argv[arg]);
Packit fcad23
        longvar = RS_ACTIVE;
Packit fcad23
        snmp_pdu_add_variable(pdu, usmUserStatus, name_length,
Packit fcad23
                              ASN_INTEGER, (u_char *) & longvar,
Packit fcad23
                              sizeof(longvar));
Packit fcad23
    } else if (strcmp(argv[arg], CMD_DEACTIVATE_NAME) == 0) {
Packit fcad23
        /*
Packit fcad23
         * deactivate:  deactivate a user
Packit fcad23
         *
Packit fcad23
         * deactivate USER
Packit fcad23
         */
Packit fcad23
        if (++arg >= argc) {
Packit fcad23
            fprintf(stderr, "You must specify the user name to deactivate\n");
Packit fcad23
            goto close_session;
Packit fcad23
        }
Packit fcad23
Packit fcad23
        command = CMD_DEACTIVATE;
Packit fcad23
        setup_oid(usmUserStatus, &name_length,
Packit fcad23
                  usmUserEngineID, usmUserEngineIDLen, argv[arg]);
Packit fcad23
        longvar = RS_NOTINSERVICE;
Packit fcad23
        snmp_pdu_add_variable(pdu, usmUserStatus, name_length,
Packit fcad23
                              ASN_INTEGER, (u_char *) & longvar,
Packit fcad23
                              sizeof(longvar));
Packit fcad23
#if defined(HAVE_OPENSSL_DH_H) && defined(HAVE_LIBCRYPTO)
Packit fcad23
    } else if (strcmp(argv[arg], CMD_CHANGEKEY_NAME) == 0) {
Packit fcad23
        /*
Packit fcad23
         * change the key of a user if DH is available
Packit fcad23
         */
Packit fcad23
Packit fcad23
        char *passwd_user;
Packit fcad23
        netsnmp_pdu *dhpdu, *dhresponse = NULL;
Packit fcad23
        netsnmp_variable_list *vars, *dhvar;
Packit fcad23
        
Packit fcad23
        command = CMD_CHANGEKEY;
Packit fcad23
        name_length = DH_USM_OID_LEN;
Packit fcad23
        name_length2 = DH_USM_OID_LEN;
Packit fcad23
Packit fcad23
        passwd_user = argv[++arg];
Packit fcad23
Packit fcad23
        if (doprivkey == 0 && doauthkey == 0)
Packit fcad23
            doprivkey = doauthkey = 1;
Packit fcad23
Packit fcad23
        /* 
Packit fcad23
         * Change the user supplied on command line.
Packit fcad23
         */
Packit fcad23
        if ((passwd_user != NULL) && (strlen(passwd_user) > 0)) {
Packit fcad23
            session.securityName = passwd_user;
Packit fcad23
        } else {
Packit fcad23
            /*
Packit fcad23
             * Use own key object if no user was supplied.
Packit fcad23
             */
Packit fcad23
            dhauthKeyChange = usmDHUserOwnAuthKeyChange;
Packit fcad23
            dhprivKeyChange = usmDHUserOwnPrivKeyChange;
Packit fcad23
        }
Packit fcad23
Packit fcad23
        /*
Packit fcad23
         * do we have a securityName?  If not, copy the default 
Packit fcad23
         */
Packit fcad23
        if (session.securityName == NULL) {
Packit fcad23
            session.securityName = 
Packit fcad23
	      strdup(netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 
Packit fcad23
					   NETSNMP_DS_LIB_SECNAME));
Packit fcad23
        }
Packit fcad23
Packit fcad23
        /* fetch the needed diffie helman parameters */
Packit fcad23
        dhpdu = snmp_pdu_create(SNMP_MSG_GET);
Packit fcad23
        if (!dhpdu) {
Packit fcad23
            fprintf(stderr, "Failed to create DH request\n");
Packit fcad23
            goto close_session;
Packit fcad23
        }
Packit fcad23
Packit fcad23
        /* get the current DH parameters */
Packit fcad23
        snmp_add_null_var(dhpdu, usmDHParameters, usmDHParameters_len);
Packit fcad23
        
Packit fcad23
        /* maybe the auth key public value */
Packit fcad23
        if (doauthkey) {
Packit fcad23
            setup_oid(dhauthKeyChange, &name_length,
Packit fcad23
                      usmUserEngineID, usmUserEngineIDLen,
Packit fcad23
                      session.securityName);
Packit fcad23
            snmp_add_null_var(dhpdu, dhauthKeyChange, name_length);
Packit fcad23
        }
Packit fcad23
            
Packit fcad23
        /* maybe the priv key public value */
Packit fcad23
        if (doprivkey) {
Packit fcad23
            setup_oid(dhprivKeyChange, &name_length2,
Packit fcad23
                      usmUserEngineID, usmUserEngineIDLen,
Packit fcad23
                      session.securityName);
Packit fcad23
            snmp_add_null_var(dhpdu, dhprivKeyChange, name_length2);
Packit fcad23
        }
Packit fcad23
Packit fcad23
        /* fetch the values */
Packit fcad23
        status = snmp_synch_response(ss, dhpdu, &dhresponse);
Packit fcad23
Packit fcad23
        if (status != SNMPERR_SUCCESS || dhresponse == NULL ||
Packit fcad23
            dhresponse->errstat != SNMP_ERR_NOERROR ||
Packit fcad23
            dhresponse->variables->type != ASN_OCTET_STR) {
Packit fcad23
            snmp_sess_perror("snmpusm", ss);
Packit fcad23
            if (dhresponse && dhresponse->variables &&
Packit fcad23
                dhresponse->variables->type != ASN_OCTET_STR) {
Packit fcad23
                fprintf(stderr,
Packit fcad23
                        "Can't get diffie-helman exchange from the agent\n");
Packit fcad23
                fprintf(stderr,
Packit fcad23
                        "  (maybe it doesn't support the SNMP-USM-DH-OBJECTS-MIB MIB)\n");
Packit fcad23
            }
Packit fcad23
            exitval = 1;
Packit fcad23
            goto begone;
Packit fcad23
        }
Packit fcad23
        
Packit fcad23
        dhvar = dhresponse->variables;
Packit fcad23
        vars = dhvar->next_variable;
Packit fcad23
        /* complete the DH equation & print resulting keys */
Packit fcad23
        if (doauthkey) {
Packit fcad23
            if (get_USM_DH_key(vars, dhvar,
Packit fcad23
                               sc_get_properlength(ss->securityAuthProto,
Packit fcad23
                                                   ss->securityAuthProtoLen),
Packit fcad23
                               pdu, "auth",
Packit fcad23
                               dhauthKeyChange, name_length) != SNMPERR_SUCCESS)
Packit fcad23
                goto begone;
Packit fcad23
            vars = vars->next_variable;
Packit fcad23
        }
Packit fcad23
        if (doprivkey) {
Packit fcad23
            size_t dhprivKeyLen = 0;
Packit fcad23
            int privtype = sc_get_privtype(ss->securityPrivProto,
Packit fcad23
                                           ss->securityPrivProtoLen);
Packit fcad23
            dhprivKeyLen = sc_get_proper_priv_length_bytype(privtype);
Packit fcad23
            if (USM_CREATE_USER_PRIV_DES == privtype)
Packit fcad23
                dhprivKeyLen *= 2; /* ?? we store salt with key */
Packit fcad23
            if (get_USM_DH_key(vars, dhvar,
Packit fcad23
                               dhprivKeyLen,
Packit fcad23
                               pdu, "priv",
Packit fcad23
                               dhprivKeyChange, name_length2)
Packit fcad23
                != SNMPERR_SUCCESS)
Packit fcad23
                goto begone;
Packit fcad23
            vars = vars->next_variable;
Packit fcad23
        }
Packit fcad23
        /* snmp_free_pdu(dhresponse); */ /* parts still in use somewhere */
Packit fcad23
#endif /* HAVE_OPENSSL_DH_H && HAVE_LIBCRYPTO */
Packit fcad23
    } else {
Packit fcad23
        fprintf(stderr, "Unknown command\n");
Packit fcad23
        usage();
Packit fcad23
        goto close_session;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * add usmUserPublic if specified (via -Cp)
Packit fcad23
     */
Packit fcad23
    if (usmUserPublic_val) {
Packit fcad23
        name_length = USM_OID_LEN;
Packit fcad23
	setup_oid(usmUserPublic, &name_length,
Packit fcad23
		  usmUserEngineID, usmUserEngineIDLen,
Packit fcad23
		  session.securityName);
Packit fcad23
	snmp_pdu_add_variable(pdu, usmUserPublic, name_length,
Packit fcad23
			      ASN_OCTET_STR, usmUserPublic_val, 
Packit fcad23
			      strlen(usmUserPublic_val));	  
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * do the request 
Packit fcad23
     */
Packit fcad23
    status = snmp_synch_response(ss, pdu, &response);
Packit fcad23
    if (status == STAT_SUCCESS) {
Packit fcad23
        if (response) {
Packit fcad23
            if (response->errstat == SNMP_ERR_NOERROR) {
Packit fcad23
                fprintf(stdout, "%s\n", successNotes[command - 1]);
Packit fcad23
            } else {
Packit fcad23
                fprintf(stderr, "Error in packet.\nReason: %s\n",
Packit fcad23
                        snmp_errstring(response->errstat));
Packit fcad23
                if (response->errindex != 0) {
Packit fcad23
                    int             count;
Packit fcad23
                    netsnmp_variable_list *vars;
Packit fcad23
                    fprintf(stderr, "Failed object: ");
Packit fcad23
                    for (count = 1, vars = response->variables;
Packit fcad23
                         vars && count != response->errindex;
Packit fcad23
                         vars = vars->next_variable, count++)
Packit fcad23
                        /*EMPTY*/;
Packit fcad23
                    if (vars)
Packit fcad23
                        fprint_objid(stderr, vars->name,
Packit fcad23
                                     vars->name_length);
Packit fcad23
                    fprintf(stderr, "\n");
Packit fcad23
                }
Packit fcad23
                exitval = 2;
Packit fcad23
            }
Packit fcad23
        }
Packit fcad23
    } else if (status == STAT_TIMEOUT) {
Packit fcad23
        fprintf(stderr, "Timeout: No Response from %s\n",
Packit fcad23
                session.peername);
Packit fcad23
        exitval = 1;
Packit fcad23
    } else {                    /* status == STAT_ERROR */
Packit fcad23
        snmp_sess_perror("snmpset", ss);
Packit fcad23
        exitval = 1;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    exitval = 0;
Packit fcad23
#if defined(HAVE_OPENSSL_DH_H) && defined(HAVE_LIBCRYPTO)
Packit fcad23
  begone:
Packit fcad23
#endif /* HAVE_OPENSSL_DH_H && HAVE_LIBCRYPTO */
Packit fcad23
    if (response)
Packit fcad23
        snmp_free_pdu(response);
Packit fcad23
Packit fcad23
close_session:
Packit fcad23
    snmp_close(ss);
Packit fcad23
Packit fcad23
out:
Packit fcad23
    SOCK_CLEANUP;
Packit fcad23
    return exitval;
Packit fcad23
}