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; }
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; }
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; }
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; }