restemplate/indy/Protocols/IdASN1Util.pas

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.