Beispiel #1
0
static u_char*
EncodeUsmSecParams(TnmSnmp *session, TnmSnmpPdu *pdu, int *lengthPtr)
{
    u_char *seqToken;
    char *user, *engineID;
    int userLength, engineIDLength;
    static u_char buffer[TNM_SNMP_MAXSIZE];
    TnmBer *ber;

    /*
     * Start building the UsmSecurityParameters field.
     */

    ber = TnmBerCreate(buffer, sizeof(buffer));
    ber = TnmBerEncSequenceStart(ber, ASN1_SEQUENCE, &seqToken);

    engineID = TnmGetOctetStringFromObj(NULL, session->engineID,
					&engineIDLength);
    ber = TnmBerEncOctetString(ber, ASN1_OCTET_STRING,
			       engineID, engineIDLength);

    if (pdu->type == ASN1_SNMP_RESPONSE
	|| session->securityLevel & TNM_SNMP_AUTH_MASK) {
	ber = TnmBerEncInt(ber, ASN1_INTEGER, session->engineBoots);
	ber = TnmBerEncInt(ber, ASN1_INTEGER, session->engineTime);
    } else {
	ber = TnmBerEncInt(ber, ASN1_INTEGER, 0);
	ber = TnmBerEncInt(ber, ASN1_INTEGER, 0);
    }
        
    user = Tcl_GetStringFromObj(session->user, &userLength);
    ber = TnmBerEncOctetString(ber, ASN1_OCTET_STRING,
			       user, userLength);
    
    if (session->securityLevel & TNM_SNMP_AUTH_MASK) {
	char zeros[12];
	memset(zeros, 0, 12);
	ber = TnmBerEncOctetString(ber, ASN1_OCTET_STRING, zeros, 12);
    } else {
	ber = TnmBerEncOctetString(ber, ASN1_OCTET_STRING, "", 0);
    }
    ber = TnmBerEncOctetString(ber, ASN1_OCTET_STRING, "", 0);
    ber = TnmBerEncSequenceEnd(ber, seqToken);

    if (! ber) {
	*lengthPtr = 0;
	/* TnmBerDelete(ber); xxx */
	return NULL;
    }

    *lengthPtr = (ber->current - ber->start);
    TnmBerDelete(ber);
    return buffer;
}
Beispiel #2
0
static TnmBer*
EncodeScopedPDU(Tcl_Interp *interp, TnmSnmp *session, TnmSnmpPdu *pdu, TnmBer *ber)
{
    u_char *seqToken;
    char *context, *engineID;
    int contextLength, engineIDLength;

    ber = TnmBerEncSequenceStart(ber, ASN1_SEQUENCE, &seqToken);

    engineID = TnmGetOctetStringFromObj(NULL, session->engineID,
					&engineIDLength);
    ber = TnmBerEncOctetString(ber, ASN1_OCTET_STRING,
			       engineID, engineIDLength);
    context = Tcl_GetStringFromObj(session->context, &contextLength);
    ber = TnmBerEncOctetString(ber, ASN1_OCTET_STRING,
			       context, contextLength);
    ber = EncodePDU(interp, session, pdu, ber);

    ber = TnmBerEncSequenceEnd(ber, seqToken);
    return ber;
}
Beispiel #3
0
static void
ComputeKey(Tcl_Obj **objPtrPtr, Tcl_Obj *password, Tcl_Obj *engineID, int algorithm)
{
    unsigned char *pwBytes, *engineBytes, *bytes;
    int pwLength, engineLength, length;
    KeyCache *elemPtr;
    static KeyCache *keyList = NULL;
    unsigned char buffer[256];	/* must be large enough to hold keys */

    if (*objPtrPtr) {
	Tcl_DecrRefCount(*objPtrPtr);
	*objPtrPtr = NULL;
    }

    pwBytes = (unsigned char *) Tcl_GetStringFromObj(password, &pwLength);
    engineBytes = (unsigned char *) TnmGetOctetStringFromObj(NULL, engineID, &engineLength);

    if (! pwBytes || ! engineBytes || engineLength == 0 || pwLength == 0) {
	return;
    }
    
    /*
     * Check whether the key is already in our cache. We have
     * to check that the password and the engineID  matches as
     * well as the algorithm.
     */

    for (elemPtr = keyList; elemPtr; elemPtr = elemPtr->nextPtr) {
	if (elemPtr->algorithm != algorithm) continue;

	bytes = (unsigned char *) Tcl_GetStringFromObj(elemPtr->password, &length);
	if (length != pwLength) continue;
	if (memcmp(pwBytes, bytes, (size_t) length) != 0) continue;
	
	bytes = (unsigned char *) Tcl_GetStringFromObj(elemPtr->engineID, &length);
	if (length != engineLength) continue;
	if (memcmp(engineBytes, bytes, (size_t) length) != 0) continue;

	*objPtrPtr = elemPtr->key;
	Tcl_IncrRefCount(*objPtrPtr);
    }

    /*
     * Compute a new key as described in the appendix of RFC 2274.
     */

    switch (algorithm) {
    case TNM_SNMP_AUTH_MD5:
        MD5PassWord2Key(pwBytes, pwLength, engineBytes, engineLength, buffer);
	*objPtrPtr = TnmNewOctetStringObj((char *)buffer, 16);
	Tcl_IncrRefCount(*objPtrPtr);
	break;
    case TNM_SNMP_AUTH_SHA:
	SHAPassWord2Key(pwBytes, pwLength, engineBytes, engineLength, buffer);
	*objPtrPtr = TnmNewOctetStringObj((char *)buffer, 20);
	Tcl_IncrRefCount(*objPtrPtr);
	break;
    default:
	Tcl_Panic("unknown algorithm for password to key conversion");
    }

    /*
     * Finally, create a new cache entry to save the result for the
     * future.
     */

    elemPtr = (KeyCache *) ckalloc(sizeof(KeyCache));
    elemPtr->algorithm = algorithm;
    elemPtr->password = password;
    Tcl_IncrRefCount(elemPtr->password);
    elemPtr->engineID = engineID;
    Tcl_IncrRefCount(elemPtr->engineID);
    elemPtr->key = *objPtrPtr;
    Tcl_IncrRefCount(elemPtr->key);
    elemPtr->nextPtr = keyList;
    keyList = elemPtr;
}
Beispiel #4
0
Tcl_Obj*
TnmSnmpNorm(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags)
{
    int i, code, objc;
    Tcl_Obj **objv;
    Tcl_Obj *vbListPtr = NULL;

    /*
     * The following Tcl_Objs are allocated once and reused whenever
     * we need to expand a varbind list containing object identifiers
     * without any value or type elements.
     */

    static Tcl_Obj *nullType = NULL;
    static Tcl_Obj *zeroValue = NULL;
    static Tcl_Obj *nullValue = NULL;

    if (! nullType) {
	nullType = Tcl_NewStringObj("NULL", 4);
	Tcl_IncrRefCount(nullType);
    }
    if (! zeroValue) {
	zeroValue = Tcl_NewIntObj(0);
	Tcl_IncrRefCount(zeroValue);
    }
    if (! nullValue) {
	nullValue = Tcl_NewStringObj(NULL, 0);
	Tcl_IncrRefCount(nullValue);
    }

    /*
     * Split the varbind list into a list of varbinds. Create a
     * new Tcl list to hold the expanded varbind list.
     */

    code = Tcl_ListObjGetElements(interp, objPtr, &objc, &objv);
    if (code != TCL_OK) {
	goto errorExit;
    }

    vbListPtr = Tcl_NewListObj(0, NULL);

    for (i = 0; i < objc; i++) {
	int vbc, type;
	Tcl_Obj **vbv, *vbPtr;
	TnmOid* oidPtr;
	Tcl_Obj *oidObjPtr, *typeObjPtr, *valueObjPtr;
	TnmMibNode *nodePtr = NULL;

	/*
	 * Create a new varbind element in the expanded result list
	 * for each varbind.
	 */

	vbPtr = Tcl_NewListObj(0, NULL);
	Tcl_ListObjAppendElement(interp, vbListPtr, vbPtr);

	code = Tcl_ListObjGetElements(interp, objv[i], &vbc, &vbv);
	if (code != TCL_OK) {
	    goto errorExit;
	}

	/*
	 * Get the object identifier value from the first list
	 * element. Check the number of list elements and assign
	 * them to the oid, type and value variables.
	 */

	switch (vbc) {
	case 1:
	    oidObjPtr = vbv[0];
	    typeObjPtr = nullType;
	    valueObjPtr = nullValue;
	    break;
	case 2:
	    oidObjPtr = vbv[0];
	    typeObjPtr = NULL;
	    valueObjPtr = vbv[1];
	    break;
	case 3:
	    oidObjPtr = vbv[0];
	    typeObjPtr = vbv[1];
	    valueObjPtr = vbv[2];
	    break;
	default: {
		char msg[80];
		sprintf(msg, "illegal number of elements in varbind %d", i);
		Tcl_ResetResult(interp);
		Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), 
				       msg, (char *) NULL);
		goto errorExit;
	    }
	}

	/*
	 * Check/resolve the object identifier and assign it to the
	 * result list. Make sure to make a deep copy if the object
	 * identifier value is shared since the string representation
	 * must be invalidated to ensure that hexadecimal
	 * sub-identifier are converted into decimal sub-identifier.
	 */

	oidPtr = TnmGetOidFromObj(interp, oidObjPtr);
	if (! oidPtr) {
	    goto errorExit;
	}
	if (Tcl_IsShared(oidObjPtr)) {
	    oidObjPtr = Tcl_DuplicateObj(oidObjPtr);
	}
	TnmOidObjSetRep(oidObjPtr, TNM_OID_AS_OID);
	Tcl_InvalidateStringRep(oidObjPtr);
	Tcl_ListObjAppendElement(interp, vbPtr, oidObjPtr);

	/* 
	 * Lookup the type in the MIB if there is no type given in the
	 * varbind element.
	 */

	if (! typeObjPtr) {
	    int syntax;
	    nodePtr = TnmMibNodeFromOid(oidPtr, NULL);
	    if (! nodePtr) {
		char msg[80];
		sprintf(msg, "failed to lookup the type for varbind %d", i);
		Tcl_ResetResult(interp);
		Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), 
				       msg, (char *) NULL);
		goto errorExit;
	    }
	    syntax = (nodePtr->typePtr && nodePtr->typePtr->name)
		? nodePtr->typePtr->syntax : nodePtr->syntax;

	    typeObjPtr = Tcl_NewStringObj(
		TnmGetTableValue(tnmSnmpTypeTable, (unsigned) syntax), -1);
	}

	type = TnmGetTableKeyFromObj(NULL, tnmSnmpTypeTable, 
				     typeObjPtr, NULL);
	if (type == -1) {
	    type = TnmGetTableKeyFromObj(NULL, tnmSnmpExceptionTable,
					 typeObjPtr, NULL);
	    if (type == -1) {
		char msg[80];
	    invalidType:
		sprintf(msg, "illegal type in varbind %d", i);
		Tcl_ResetResult(interp);
		Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), 
				       msg, (char *) NULL);
		goto errorExit;
	    }
	}

	Tcl_ListObjAppendElement(interp, vbPtr, typeObjPtr);

	/*
	 * Check the value and perform any conversions needed to
	 * convert the value into the base type representation.
	 */

	switch (type) {
	case ASN1_INTEGER: {
	    long longValue;
	    code = Tcl_GetLongFromObj(interp, valueObjPtr, &longValue);
	    if (code != TCL_OK) {
		if (! nodePtr) {
		    nodePtr = TnmMibNodeFromOid(oidPtr, NULL);
		}
		if (nodePtr) {
		    Tcl_Obj *value;
		    value = TnmMibScanValue(nodePtr->typePtr, nodePtr->syntax, 
					    valueObjPtr);
		    if (! value) {
			goto errorExit;
		    }
		    Tcl_ResetResult(interp);
		    code = Tcl_GetLongFromObj(interp, value, &longValue);
		}
		if (code != TCL_OK) {
		    goto errorExit;
		}
		valueObjPtr = Tcl_NewLongObj(longValue);
	    }
	    if (flags & TNM_SNMP_NORM_INT) {
		if (! nodePtr) {
		    nodePtr = TnmMibNodeFromOid(oidPtr, NULL);
		}
		if (nodePtr && nodePtr->typePtr) {
		    Tcl_Obj *newPtr;
		    newPtr = TnmMibFormatValue(nodePtr->typePtr,
					       nodePtr->syntax,
					       valueObjPtr);
		    if (newPtr) {
			valueObjPtr = newPtr;
		    }
		}
	    }
	    break;
	}
	case ASN1_COUNTER32:
	case ASN1_GAUGE32:
	case ASN1_TIMETICKS: {
	    TnmUnsigned32 u;
	    code = TnmGetUnsigned32FromObj(interp, valueObjPtr, &u);
	    if (code != TCL_OK) {
		goto errorExit;
	    }
	    break;
	}
	case ASN1_COUNTER64: {
	    TnmUnsigned64 u;
	    code = TnmGetUnsigned64FromObj(interp, valueObjPtr, &u);
	    if (code != TCL_OK) {
		goto errorExit;
	    }
	    break;
	}
	case ASN1_IPADDRESS: {
            if (TnmGetIpAddressFromObj(interp, valueObjPtr) == NULL) {
		goto errorExit;
	    }
	    Tcl_InvalidateStringRep(valueObjPtr);
	    break;
	}
	case ASN1_OBJECT_IDENTIFIER:
	    if (! TnmGetOidFromObj(interp, valueObjPtr)) {
		goto errorExit;
	    }
	    if (Tcl_IsShared(valueObjPtr)) {
		valueObjPtr = Tcl_DuplicateObj(valueObjPtr);
	    }
	    if (flags & TNM_SNMP_NORM_OID) {
		TnmOidObjSetRep(valueObjPtr, TNM_OID_AS_NAME);
	    } else {
		TnmOidObjSetRep(valueObjPtr, TNM_OID_AS_OID);
	    }
	    Tcl_InvalidateStringRep(valueObjPtr);
	    break;
	case ASN1_OCTET_STRING: {
	    int len;
	    if (! nodePtr) {
		nodePtr = TnmMibNodeFromOid(oidPtr, NULL);
	    }
	    if (nodePtr) {
		Tcl_Obj *scan;
		scan = TnmMibScanValue(nodePtr->typePtr, nodePtr->syntax, 
				      valueObjPtr);
		if (scan) {
		    valueObjPtr = scan;
		}
	    }
	    if (TnmGetOctetStringFromObj(interp, valueObjPtr, &len) == NULL) {
		goto errorExit;
	    }
	    Tcl_InvalidateStringRep(valueObjPtr);
	    break;
	}
	case ASN1_NULL:
	    valueObjPtr = nullValue;
	    break;
	default:
	    goto invalidType;
	}
	
	Tcl_ListObjAppendElement(interp, vbPtr, valueObjPtr);
    }

    return vbListPtr;

 errorExit:
    if (vbListPtr) {
	Tcl_DecrRefCount(vbListPtr);
    }
    return NULL;
}