47b69e0a35
git-svn-id: https://svn.code.sf.net/p/synalist/code/trunk@55 7c85be65-684b-0410-a082-b2ed4fbef004
361 lines
9.6 KiB
ObjectPascal
361 lines
9.6 KiB
ObjectPascal
{==============================================================================|
|
|
| Project : Delphree - Synapse | 001.003.004 |
|
|
|==============================================================================|
|
|
| Content: support for ASN.1 BER 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}
|
|
|
|
unit ASN1Util;
|
|
|
|
interface
|
|
|
|
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
|
|
|
|
{==============================================================================}
|
|
function ASNEncOIDItem(Value: Integer): string;
|
|
var
|
|
x, xm: Integer;
|
|
b: Boolean;
|
|
begin
|
|
x := Value;
|
|
b := False;
|
|
Result := '';
|
|
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 := '';
|
|
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: Cardinal;
|
|
neg: Boolean;
|
|
begin
|
|
neg := Value < 0;
|
|
x := Abs(Value);
|
|
if neg then
|
|
x := not (x - 1);
|
|
Result := '';
|
|
repeat
|
|
y := x mod 256;
|
|
x := x div 256;
|
|
Result := Char(y) + Result;
|
|
until x = 0;
|
|
if (not neg) and (Result[1] > #$7F) then
|
|
Result := #0 + Result;
|
|
end;
|
|
|
|
{==============================================================================}
|
|
function ASNEncUInt(Value: Integer): string;
|
|
var
|
|
x, y: Integer;
|
|
neg: Boolean;
|
|
begin
|
|
neg := Value < 0;
|
|
x := Value;
|
|
if neg then
|
|
x := x and $7FFFFFFF;
|
|
Result := '';
|
|
repeat
|
|
y := x mod 256;
|
|
x := x div 256;
|
|
Result := Char(y) + Result;
|
|
until x = 0;
|
|
if neg then
|
|
Result[1] := Char(Ord(Result[1]) or $80);
|
|
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;
|
|
s: string;
|
|
c: char;
|
|
neg: Boolean;
|
|
l: Integer;
|
|
begin
|
|
Result := '';
|
|
ValueType := ASN1_NULL;
|
|
l := Length(Buffer);
|
|
if l < (Start + 1) then
|
|
Exit;
|
|
ASNType := Ord(Buffer[Start]);
|
|
ValueType := ASNType;
|
|
Inc(Start);
|
|
ASNSize := ASNDecLen(Start, Buffer);
|
|
if (Start + ASNSize - 1) > l then
|
|
Exit;
|
|
if (ASNType and $20) > 0 then
|
|
Result := '$' + IntToHex(ASNType, 2)
|
|
else
|
|
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
|
|
neg := True;
|
|
if neg then
|
|
x := not x;
|
|
y := y * 256 + x;
|
|
Inc(Start);
|
|
end;
|
|
if neg then
|
|
y := -(y + 1);
|
|
Result := IntToStr(y);
|
|
end;
|
|
ASN1_COUNTER, ASN1_GAUGE, ASN1_TIMETICKS:
|
|
begin
|
|
y := 0;
|
|
for n := 1 to ASNSize do
|
|
begin
|
|
y := y * 256 + Ord(Buffer[Start]);
|
|
Inc(Start);
|
|
end;
|
|
Result := IntToStr(y);
|
|
end;
|
|
ASN1_OCTSTR, ASN1_OPAQUE:
|
|
begin
|
|
for n := 1 to ASNSize do
|
|
begin
|
|
c := Char(Buffer[Start]);
|
|
Inc(Start);
|
|
s := s + c;
|
|
end;
|
|
Result := s;
|
|
end;
|
|
ASN1_OBJID:
|
|
begin
|
|
for n := 1 to ASNSize do
|
|
begin
|
|
c := Char(Buffer[Start]);
|
|
Inc(Start);
|
|
s := s + c;
|
|
end;
|
|
Result := IdToMib(s);
|
|
end;
|
|
ASN1_IPADDR:
|
|
begin
|
|
s := '';
|
|
for n := 1 to ASNSize do
|
|
begin
|
|
if (n <> 1) then
|
|
s := s + '.';
|
|
y := Ord(Buffer[Start]);
|
|
Inc(Start);
|
|
s := s + IntToStr(y);
|
|
end;
|
|
Result := s;
|
|
end;
|
|
else // NULL
|
|
begin
|
|
Result := '';
|
|
Inc(Start);
|
|
Start := Start + ASNSize;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{==============================================================================}
|
|
function MibToId(Mib: string): string;
|
|
var
|
|
x: Integer;
|
|
|
|
function WalkInt(var s: string): Integer;
|
|
var
|
|
x: Integer;
|
|
t: string;
|
|
begin
|
|
x := Pos('.', s);
|
|
if x < 1 then
|
|
begin
|
|
t := s;
|
|
s := '';
|
|
end
|
|
else
|
|
begin
|
|
t := Copy(s, 1, x - 1);
|
|
s := Copy(s, x + 1, Length(s) - x);
|
|
end;
|
|
Result := StrToIntDef(t, 0);
|
|
end;
|
|
|
|
begin
|
|
Result := '';
|
|
x := WalkInt(Mib);
|
|
x := x * 40 + WalkInt(Mib);
|
|
Result := ASNEncOIDItem(x);
|
|
while Mib <> '' do
|
|
begin
|
|
x := WalkInt(Mib);
|
|
Result := Result + ASNEncOIDItem(x);
|
|
end;
|
|
end;
|
|
|
|
{==============================================================================}
|
|
function IdToMib(const Id: string): string;
|
|
var
|
|
x, y, n: Integer;
|
|
begin
|
|
Result := '';
|
|
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);
|
|
end;
|
|
end;
|
|
|
|
{==============================================================================}
|
|
function IntMibToStr(const Value: string): string;
|
|
var
|
|
n, y: Integer;
|
|
begin
|
|
y := 0;
|
|
for n := 1 to Length(Value) - 1 do
|
|
y := y * 256 + Ord(Value[n]);
|
|
Result := IntToStr(y);
|
|
end;
|
|
|
|
{==============================================================================}
|
|
|
|
end.
|