520 lines
14 KiB
Plaintext
520 lines
14 KiB
Plaintext
{
|
|
$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.
|