{ $Project$ $Workfile$ $Revision$ $DateUTC$ $Id$ This file is part of the Indy (Internet Direct) project, and is offered under the dual-licensing agreement described on the Indy website. (http://www.indyproject.org/) Copyright: (c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved. } { $Log$ } { Rev 1.2 3/3/2005 9:13:36 AM JPMugaas Should work in DotNET. Rev 1.1 02/03/2005 00:09:14 CCostelloe Bug fix (high bit treated as sign instead of MSB) Rev 1.0 11/14/2002 02:12:30 PM JPMugaas } unit IdASN1Util; // REVIEW: Licensing problem // 1) Is this only used by SNMP? If so it should be merged there. // 2) MPL conflicts with Indy's BSD. We need permission to distribute under BSD as well. // 3) A comment needs to be added that Indy has permission to use this { |==============================================================================| | Project : Delphree - Synapse | 001.003.004 | |==============================================================================| | Content: support for ASN.1 coding and decoding | |==============================================================================| | The contents of this file are subject to the Mozilla Public License Ver. 1.1 | | (the "License"); you may not use this file except in compliance with the | | License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ | | | | Software distributed under the License is distributed on an "AS IS" basis, | | WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for | | the specific language governing rights and limitations under the License. | |==============================================================================| | The Original Code is Synapse Delphi Library. | |==============================================================================| | The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).| | Portions created by Lukas Gebauer are Copyright (c) 1999,2000,2001. | | Portions created by Hernan Sanchez are Copyright (c) 2000. | | All Rights Reserved. | |==============================================================================| | Contributor(s): | | Hernan Sanchez (hernan.sanchez@iname.com) | |==============================================================================| | History: see HISTORY.HTM from distribution package | | (Found at URL: http://www.ararat.cz/synapse/) | |==============================================================================| } {$Q-} {$WEAKPACKAGEUNIT ON} interface {$i IdCompilerDefines.inc} uses SysUtils; const ASN1_INT = $02; ASN1_OCTSTR = $04; ASN1_NULL = $05; ASN1_OBJID = $06; ASN1_SEQ = $30; ASN1_IPADDR = $40; ASN1_COUNTER = $41; ASN1_GAUGE = $42; ASN1_TIMETICKS = $43; ASN1_OPAQUE = $44; function ASNEncOIDItem(Value: Integer): string; function ASNDecOIDItem(var Start: Integer; const Buffer: string): Integer; function ASNEncLen(Len: Integer): string; function ASNDecLen(var Start: Integer; const Buffer: string): Integer; function ASNEncInt(Value: Integer): string; function ASNEncUInt(Value: Integer): string; function ASNObject(const Data: string; ASNType: Integer): string; function ASNItem(var Start: Integer; const Buffer: string; var ValueType: Integer): string; function MibToId(Mib: string): string; function IdToMib(const Id: string): string; function IntMibToStr(const Value: string): string; implementation uses IdGlobal; {==============================================================================} function ASNEncOIDItem(Value: Integer): string; var x, xm: Integer; b: Boolean; begin x := Value; b := False; Result := ''; {Do not Localize} repeat xm := x mod 128; x := x div 128; if b then xm := xm or $80; if x > 0 then b := True; Result := Char(xm) + Result; until x = 0; end; {==============================================================================} function ASNDecOIDItem(var Start: Integer; const Buffer: string): Integer; var x: Integer; b: Boolean; begin Result := 0; repeat Result := Result * 128; x := Ord(Buffer[Start]); Inc(Start); b := x > $7F; x := x and $7F; Result := Result + x; until not b; end; {==============================================================================} function ASNEncLen(Len: Integer): string; var x, y: Integer; begin if Len < $80 then Result := Char(Len) else begin x := Len; Result := ''; {Do not Localize} repeat y := x mod 256; x := x div 256; Result := Char(y) + Result; until x = 0; y := Length(Result); y := y or $80; Result := Char(y) + Result; end; end; {==============================================================================} function ASNDecLen(var Start: Integer; const Buffer: string): Integer; var x, n: Integer; begin x := Ord(Buffer[Start]); Inc(Start); if x < $80 then Result := x else begin Result := 0; x := x and $7F; for n := 1 to x do begin Result := Result * 256; x := Ord(Buffer[Start]); Inc(Start); Result := Result + x; end; end; end; {==============================================================================} function ASNEncInt(Value: Integer): string; var x, y: UInt32; neg: Boolean; {$IFDEF STRING_IS_IMMUTABLE} LSB: TIdStringBuilder; {$ENDIF} begin neg := Value < 0; x := Abs(Value); if neg then begin x := not (x - 1); end; Result := ''; {Do not Localize} {$IFDEF STRING_IS_IMMUTABLE} LSB := TIdStringBuilder.Create; {$ENDIF} repeat y := x mod 256; x := x div 256; {$IFDEF STRING_IS_IMMUTABLE} LSB.Insert(0, Char(y)); {$ELSE} Result := Char(y) + Result; {$ENDIF} until x = 0; if (not neg) then begin {$IFDEF STRING_IS_IMMUTABLE} if (LSB[0] > #$7F) then begin LSB.Insert(0, #0); end; {$ELSE} if (Result[1] > #$7F) then begin Result := #0 + Result; end; {$ENDIF} end; {$IFDEF STRING_IS_IMMUTABLE} Result := LSB.ToString; {$ENDIF} end; {==============================================================================} function ASNEncUInt(Value: Integer): string; var x, y: Integer; neg: Boolean; {$IFDEF STRING_IS_IMMUTABLE} LSB: TIdStringBuilder; {$ENDIF} begin neg := Value < 0; x := Value; if neg then begin x := x and $7FFFFFFF; end; Result := ''; {Do not Localize} {$IFDEF STRING_IS_IMMUTABLE} LSB := TIdStringBuilder.Create; {$ENDIF} repeat y := x mod 256; x := x div 256; {$IFDEF STRING_IS_IMMUTABLE} LSB.Insert(0, Char(y)); {$ELSE} Result := Char(y) + Result; {$ENDIF} until x = 0; if neg then begin {$IFDEF STRING_IS_IMMUTABLE} LSB[0] := Char(Ord(LSB[0]) or $80); {$ELSE} Result[1] := Char(Ord(Result[1]) or $80); {$ENDIF} end; {$IFDEF STRING_IS_IMMUTABLE} Result := LSB.ToString; {$ENDIF} end; {==============================================================================} function ASNObject(const Data: string; ASNType: Integer): string; begin Result := Char(ASNType) + ASNEncLen(Length(Data)) + Data; end; {==============================================================================} function ASNItem(var Start: Integer; const Buffer: string; var ValueType: Integer): string; var ASNType: Integer; ASNSize: Integer; y, n: Integer; x: byte; {$IFDEF STRING_IS_IMMUTABLE} LSB: TIdStringBuilder; {$ELSE} s: string; {$ENDIF} neg: Boolean; l: Integer; z: Int64; begin Result := ''; {Do not Localize} ValueType := ASN1_NULL; l := Length(Buffer); if l < (Start + 1) then begin Exit; end; ASNType := Ord(Buffer[Start]); ValueType := ASNType; Inc(Start); ASNSize := ASNDecLen(Start, Buffer); if (Start + ASNSize - 1) > l then begin Exit; end; if (ASNType and $20) > 0 then begin Result := '$' + IntToHex(ASNType, 2) {Do not Localize} end else begin case ASNType of ASN1_INT: begin y := 0; neg := False; for n := 1 to ASNSize do begin x := Ord(Buffer[Start]); if (n = 1) and (x > $7F) then begin neg := True; end; if neg then begin x := not x; end; y := y * 256 + x; Inc(Start); end; if neg then begin y := -(y + 1); end; Result := IntToStr(y); end; ASN1_COUNTER, ASN1_GAUGE, ASN1_TIMETICKS: //Typically a 32-bit _unsigned_ number begin z := 0; for n := 1 to ASNSize do begin x := Ord(Buffer[Start]); //get the byte y := x; //promote to an integer z := (z * 256) + y; //now accumulate value Inc(Start); end; Result := IntToStr(z); end; ASN1_OCTSTR, ASN1_OPAQUE: begin {$IFDEF STRING_IS_IMMUTABLE} LSB := TIdStringBuilder.Create(ASNSize); {$ELSE} SetLength(s, ASNSize); {$ENDIF} for n := 1 to ASNSize do begin {$IFDEF STRING_IS_IMMUTABLE} LSB.Append(Char(Buffer[Start])); {$ELSE} s[n] := Char(Buffer[Start]); {$ENDIF} Inc(Start); end; {$IFDEF STRING_IS_IMMUTABLE} Result := LSB.ToString; {$ELSE} Result := s; {$ENDIF} end; ASN1_OBJID: begin {$IFDEF STRING_IS_IMMUTABLE} LSB := TIdStringBuilder.Create(ASNSize); {$ELSE} SetLength(s, ASNSize); {$ENDIF} for n := 1 to ASNSize do begin {$IFDEF STRING_IS_IMMUTABLE} LSB.Append(Char(Buffer[Start])); {$ELSE} s[n] := Char(Buffer[Start]); {$ENDIF} Inc(Start); end; Result := IdToMib( {$IFDEF STRING_IS_IMMUTABLE} LSB.ToString {$ELSE} s {$ENDIF} ); end; ASN1_IPADDR: begin {$IFDEF STRING_IS_IMMUTABLE} LSB := TIdStringBuilder.Create(15); {$ELSE} s := ''; {Do not Localize} {$ENDIF} for n := 1 to ASNSize do begin if (n <> 1) then begin {$IFDEF STRING_IS_IMMUTABLE} LSB.Append('.'); {Do not Localize} {$ELSE} s := s + '.'; {Do not Localize} {$ENDIF} end; y := Ord(Buffer[Start]); Inc(Start); {$IFDEF STRING_IS_IMMUTABLE} LSB.Append(y); {$ELSE} s := s + IntToStr(y); {$ENDIF} end; {$IFDEF STRING_IS_IMMUTABLE} Result := LSB.ToString; {$ELSE} Result := s; {$ENDIF} end; ASN1_NULL: begin Result := ''; Inc(Start, ASNSize); end; else // unknown begin {$IFDEF STRING_IS_IMMUTABLE} LSB := TIdStringBuilder.Create(ASNSize); {$ELSE} SetLength(s, ASNSize); {$ENDIF} for n := 1 to ASNSize do begin {$IFDEF STRING_IS_IMMUTABLE} LSB.Append(Char(Buffer[Start])); {$ELSE} s[n] := Char(Buffer[Start]); {$ENDIF} Inc(Start); end; {$IFDEF STRING_IS_IMMUTABLE} Result := LSB.ToString; {$ELSE} Result := s; {$ENDIF} end; end; end; end; {==============================================================================} function MibToId(Mib: string): string; var x: Integer; function WalkInt(var s: string): Integer; var lx: Integer; t: string; begin lx := Pos('.', s); {Do not Localize} if lx < 1 then begin t := s; s := ''; {Do not Localize} end else begin t := Copy(s, 1, lx - 1); s := Copy(s, lx + 1, MaxInt); end; Result := IndyStrToInt(t, 0); end; begin Result := ''; {Do not Localize} x := WalkInt(Mib); x := x * 40 + WalkInt(Mib); Result := ASNEncOIDItem(x); while Mib <> '' do {Do not Localize} begin x := WalkInt(Mib); Result := Result + ASNEncOIDItem(x); end; end; {==============================================================================} function IdToMib(const Id: string): string; var x, y, n: Integer; begin Result := ''; {Do not Localize} n := 1; while Length(Id) + 1 > n do begin x := ASNDecOIDItem(n, Id); if (n - 1) = 1 then begin y := x div 40; x := x mod 40; Result := IntToStr(y); end; Result := Result + '.' + IntToStr(x); {Do not Localize} end; end; {==============================================================================} function IntMibToStr(const Value: string): string; var n, y: Integer; begin y := 0; for n := 1 to Length(Value) - 1 do begin y := y * 256 + Ord(Value[n]); end; Result := IntToStr(y); end; {==============================================================================} end.