diff --git a/snmpsend.pas b/snmpsend.pas index 431f5e4..6ddd9a0 100644 --- a/snmpsend.pas +++ b/snmpsend.pas @@ -1,9 +1,9 @@ {==============================================================================| -| Project : Ararat Synapse | 003.000.010 | +| Project : Ararat Synapse | 004.000.000 | |==============================================================================| | Content: SNMP client | |==============================================================================| -| Copyright (c)1999-2010, Lukas Gebauer | +| Copyright (c)1999-2011, Lukas Gebauer | | All rights reserved. | | | | Redistribution and use in source and binary forms, with or without | @@ -33,7 +33,7 @@ | DAMAGE. | |==============================================================================| | The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).| -| Portions created by Lukas Gebauer are Copyright (c)2000-2010. | +| Portions created by Lukas Gebauer are Copyright (c)2000-2011. | | All Rights Reserved. | |==============================================================================| | Contributor(s): | @@ -45,9 +45,12 @@ {:@abstract(SNMP client) Supports SNMPv1 include traps, SNMPv2c and SNMPv3 include authorization - (encryption not yet supported!) +and privacy encryption. -Used RFC: RFC-1157, RFC-1901, RFC-3412, RFC-3414, RFC-3416 +Used RFC: RFC-1157, RFC-1901, RFC-3412, RFC-3414, RFC-3416, RFC-3826 + +Supported Authorization hashes: MD5, SHA1 +Supported Privacy encryptions: DES, 3DES, AES } {$IFDEF FPC} @@ -67,7 +70,7 @@ interface uses Classes, SysUtils, - blcksock, synautil, asn1util, synaip, synacode; + blcksock, synautil, asn1util, synaip, synacode, synacrypt; const cSnmpProtocol = '161'; @@ -125,6 +128,12 @@ type AuthMD5, AuthSHA1); + {:@abstract(Type of SNMPv3 privacy)} + TV3Priv = ( + PrivDES, + Priv3DES, + PrivAES); + {:@abstract(Data object with one record of MIB OID and corresponding values.)} TSNMPMib = class(TObject) protected @@ -175,19 +184,25 @@ type FUserName: AnsiString; FPassword: AnsiString; FAuthKey: AnsiString; + FPrivMode: TV3Priv; + FPrivPassword: AnsiString; FPrivKey: AnsiString; + FPrivSalt: AnsiString; + FPrivSaltCounter: integer; FOldTrapEnterprise: AnsiString; FOldTrapHost: AnsiString; FOldTrapGen: Integer; FOldTrapSpec: Integer; FOldTrapTimeTicks: Integer; function Pass2Key(const Value: AnsiString): AnsiString; + function EncryptPDU(const value: AnsiString): AnsiString; + function DecryptPDU(const value: AnsiString): AnsiString; public constructor Create; destructor Destroy; override; {:Decode SNMP packet in buffer to object properties.} - function DecodeBuf(const Buffer: AnsiString): Boolean; + function DecodeBuf(Buffer: AnsiString): Boolean; {:Encode obeject properties to SNMP packet.} function EncodeBuf: AnsiString; @@ -246,8 +261,7 @@ type {:Maximum message size in bytes for SNMPv3. For sending is default 1472 bytes.} property MaxSize: Integer read FMaxSize write FMaxSize; - {:Specify if message is authorised or encrypted. Used only in SNMPv3, and - encryption is not yet supported!} + {:Specify if message is authorised or encrypted. Used only in SNMPv3.} property Flags: TV3Flags read FFlags write FFlags; {:For SNMPv3.... If is @true, SNMP agent must send reply (at least with some @@ -264,6 +278,9 @@ type authorization)} property AuthMode: TV3Auth read FAuthMode write FAuthMode; + {:For SNMPv3. Specify Privacy mode.} + property PrivMode: TV3Priv read FPrivMode write FPrivMode; + {:value used by SNMPv3 authorisation for synchronization with SNMP agent.} property AuthEngineID: AnsiString read FAuthEngineID write FAuthEngineID; @@ -285,7 +302,10 @@ type {:For SNMPv3. Computed Athorization key from @link(password).} property AuthKey: AnsiString read FAuthKey write FAuthKey; - {:For SNMPv3. Encryption key for message encryption. Not yet used!} + {:SNMPv3 privacy password} + property PrivPassword: AnsiString read FPrivPassword write FPrivPassword; + + {:For SNMPv3. Computed Privacy key from @link(PrivPassword).} property PrivKey: AnsiString read FPrivKey write FPrivKey; {:MIB value to identify the object that sent the TRAPv1.} @@ -417,6 +437,10 @@ begin inherited Create; FSNMPMibList := TList.Create; Clear; + FAuthMode := AuthMD5; + FPassword := ''; + FPrivMode := PrivDES; + FPrivPassword := ''; FID := 1; FMaxSize := 1472; end; @@ -452,8 +476,66 @@ begin end; end; +function TSNMPRec.DecryptPDU(const value: AnsiString): AnsiString; +var + des: TSynaDes; + des3: TSyna3Des; + aes: TSynaAes; + s: string; +begin + FPrivKey := ''; + if FFlags <> AuthPriv then + Result := value + else + begin + case FPrivMode of + Priv3DES: + begin + FPrivKey := Pass2Key(FPrivPassword); + FPrivKey := FPrivKey + Pass2Key(FPrivKey); + des3 := TSyna3Des.Create(PadString(FPrivKey, 24, #0)); + try + s := PadString(FPrivKey, 32, #0); + delete(s, 1, 24); + des3.SetIV(xorstring(s, FPrivSalt)); + s := des3.DecryptCBC(value); + Result := s; + finally + des3.free; + end; + end; + PrivAES: + begin + FPrivKey := Pass2Key(FPrivPassword); + aes := TSynaAes.Create(PadString(FPrivKey, 16, #0)); + try + s := CodeLongInt(FAuthEngineBoots) + CodeLongInt(FAuthEngineTime) + FPrivSalt; + aes.SetIV(s); + s := aes.DecryptCFBblock(value); + Result := s; + finally + aes.free; + end; + end; + else //PrivDES as default + begin + FPrivKey := Pass2Key(FPrivPassword); + des := TSynaDes.Create(PadString(FPrivKey, 8, #0)); + try + s := PadString(FPrivKey, 16, #0); + delete(s, 1, 8); + des.SetIV(xorstring(s, FPrivSalt)); + s := des.DecryptCBC(value); + Result := s; + finally + des.free; + end; + end; + end; + end; +end; -function TSNMPRec.DecodeBuf(const Buffer: AnsiString): Boolean; +function TSNMPRec.DecodeBuf(Buffer: AnsiString): Boolean; var Pos: Integer; EndPos: Integer; @@ -508,14 +590,24 @@ begin FAuthEngineTimeStamp := GetTick; FUserName := ASNItem(SPos, s, Svt); FAuthKey := ASNItem(SPos, s, Svt); - FPrivKey := ASNItem(SPos, s, Svt); + FPrivSalt := ASNItem(SPos, s, Svt); end; //scopedPDU - s := ASNItem(Pos, Buffer, Svt); - if Svt = ASN1_OCTSTR then + if FFlags = AuthPriv then begin - //decrypt! + x := Pos; + s := ASNItem(Pos, Buffer, Svt); + if Svt <> ASN1_OCTSTR then + exit; + s := DecryptPDU(s); + //replace encoded content by decoded version and continue + Buffer := copy(Buffer, 1, x - 1); + Buffer := Buffer + s; + Pos := x; + if length(Buffer) < EndPos then + EndPos := length(buffer); end; + ASNItem(Pos, Buffer, Svt); //skip sequence mark FContextEngineID := ASNItem(Pos, Buffer, Svt); FContextName := ASNItem(Pos, Buffer, Svt); end @@ -547,11 +639,88 @@ begin ASNItem(Pos, Buffer, Svt); Sm := ASNItem(Pos, Buffer, Svt); Sv := ASNItem(Pos, Buffer, Svt); - Self.MIBAdd(sm, sv, Svt); + if sm <> '' then + Self.MIBAdd(sm, sv, Svt); end; Result := True; end; +function TSNMPRec.EncryptPDU(const value: AnsiString): AnsiString; +var + des: TSynaDes; + des3: TSyna3Des; + aes: TSynaAes; + s: string; + x: integer; +begin + FPrivKey := ''; + if FFlags <> AuthPriv then + Result := Value + else + begin + case FPrivMode of + Priv3DES: + begin + FPrivKey := Pass2Key(FPrivPassword); + FPrivKey := FPrivKey + Pass2Key(FPrivKey); + des3 := TSyna3Des.Create(PadString(FPrivKey, 24, #0)); + try + s := PadString(FPrivKey, 32, #0); + delete(s, 1, 24); + FPrivSalt := CodeLongInt(FAuthEngineBoots) + CodeLongInt(FPrivSaltCounter); + inc(FPrivSaltCounter); + s := xorstring(s, FPrivSalt); + des3.SetIV(s); + x := length(value) mod 8; + x := 8 - x; + if x = 8 then + x := 0; + s := des3.EncryptCBC(value + Stringofchar(#0, x)); + Result := ASNObject(s, ASN1_OCTSTR); + finally + des3.free; + end; + end; + PrivAES: + begin + FPrivKey := Pass2Key(FPrivPassword); + aes := TSynaAes.Create(PadString(FPrivKey, 16, #0)); + try + FPrivSalt := CodeLongInt(0) + CodeLongInt(FPrivSaltCounter); + inc(FPrivSaltCounter); + s := CodeLongInt(FAuthEngineBoots) + CodeLongInt(FAuthEngineTime) + FPrivSalt; + aes.SetIV(s); + s := aes.EncryptCFBblock(value); + Result := ASNObject(s, ASN1_OCTSTR); + finally + aes.free; + end; + end; + else //PrivDES as default + begin + FPrivKey := Pass2Key(FPrivPassword); + des := TSynaDes.Create(PadString(FPrivKey, 8, #0)); + try + s := PadString(FPrivKey, 16, #0); + delete(s, 1, 8); + FPrivSalt := CodeLongInt(FAuthEngineBoots) + CodeLongInt(FPrivSaltCounter); + inc(FPrivSaltCounter); + s := xorstring(s, FPrivSalt); + des.SetIV(s); + x := length(value) mod 8; + x := 8 - x; + if x = 8 then + x := 0; + s := des.EncryptCBC(value + Stringofchar(#0, x)); + Result := ASNObject(s, ASN1_OCTSTR); + finally + des.free; + end; + end; + end; + end; +end; + function TSNMPRec.EncodeBuf: AnsiString; var s: AnsiString; @@ -610,8 +779,9 @@ begin pdu := ASNObject(FContextEngineID, ASN1_OCTSTR) + ASNObject(FContextName, ASN1_OCTSTR) + pdu; - //maybe encrypt pdu... in future pdu := ASNObject(pdu, ASN1_SEQ); + //encrypt PDU if Priv mode is enabled + pdu := EncryptPDU(pdu); //prepare flags case FFlags of @@ -646,7 +816,7 @@ begin AuthPriv: begin s := authbeg + ASNObject(StringOfChar(#0, 12), ASN1_OCTSTR) - + ASNObject(FPrivKey, ASN1_OCTSTR); + + ASNObject(FPrivSalt, ASN1_OCTSTR); s := ASNObject(s, ASN1_SEQ); s := head + ASNObject(s, ASN1_OCTSTR); s := ASNObject(s + pdu, ASN1_SEQ); @@ -672,7 +842,7 @@ begin end; auth := authbeg + ASNObject(FAuthKey, ASN1_OCTSTR) - + ASNObject(FPrivKey, ASN1_OCTSTR); + + ASNObject(FPrivSalt, ASN1_OCTSTR); auth := ASNObject(auth, ASN1_SEQ); head := head + ASNObject(auth, ASN1_OCTSTR); @@ -694,7 +864,6 @@ begin FVersion := SNMP_V1; FCommunity := 'public'; FUserName := ''; - FPassword := ''; FPDUType := 0; FErrorStatus := 0; FErrorIndex := 0; @@ -710,13 +879,14 @@ begin FFlagReportable := false; FContextEngineID := ''; FContextName := ''; - FAuthMode := AuthMD5; FAuthEngineID := ''; FAuthEngineBoots := 0; FAuthEngineTime := 0; FAuthEngineTimeStamp := 0; FAuthKey := ''; FPrivKey := ''; + FPrivSalt := ''; + FPrivSaltCounter := random(maxint); end; procedure TSNMPRec.MIBAdd(const MIB, Value: AnsiString; ValueType: Integer); @@ -813,6 +983,10 @@ end; function TSNMPSend.InternalSendRequest(const QValue, RValue: TSNMPRec): Boolean; begin Result := False; + RValue.AuthMode := QValue.AuthMode; + RValue.Password := QValue.Password; + RValue.PrivMode := QValue.PrivMode; + RValue.PrivPassword := QValue.PrivPassword; FSock.Bind(FIPInterface, cAnyPort); FSock.Connect(FTargetHost, FTargetPort); if InternalSendSnmp(QValue) then @@ -832,10 +1006,7 @@ begin FQuery.AuthEngineTimeStamp := Sync.EngineStamp; FQuery.AuthEngineID := Sync.EngineID; end; - FSock.Bind(FIPInterface, cAnyPort); - FSock.Connect(FTargetHost, FTargetPort); - if InternalSendSnmp(FQuery) then - Result := InternalRecvSnmp(FReply); + Result := InternalSendRequest(FQuery, FReply); end; function TSNMPSend.SendTrap: Boolean; @@ -892,6 +1063,9 @@ begin SyncQuery.Password := FQuery.Password; SyncQuery.FlagReportable := True; SyncQuery.Flags := FQuery.Flags; + SyncQuery.AuthMode := FQuery.AuthMode; + SyncQuery.PrivMode := FQuery.PrivMode; + SyncQuery.PrivPassword := FQuery.PrivPassword; SyncQuery.PDUType := PDUGetRequest; SyncQuery.AuthEngineID := FReply.FAuthEngineID; if InternalSendRequest(SyncQuery, FReply) then diff --git a/synacrypt.pas b/synacrypt.pas index 25e552e..f19d256 100644 --- a/synacrypt.pas +++ b/synacrypt.pas @@ -498,7 +498,7 @@ const 96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219, 224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121, 231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8, - 186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, + 186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, 112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158, 225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223, 140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22); @@ -564,7 +564,7 @@ const ($2d,$9b,$9b,$b6), ($3c,$1e,$1e,$22), ($15,$87,$87,$92), ($c9,$e9,$e9,$20), ($87,$ce,$ce,$49), ($aa,$55,$55,$ff), ($50,$28,$28,$78), ($a5,$df,$df,$7a), ($03,$8c,$8c,$8f), ($59,$a1,$a1,$f8), ($09,$89,$89,$80), ($1a,$0d,$0d,$17), - ($65,$bf,$bf,$da), ($d7,$e6,$e6,$31), ($84,$42,$42,$c6), ($d0,$68,$68,$b8), + ($65,$bf,$bf,$da), ($d7,$e6,$e6,$31), ($84,$42,$42,$c6), ($d0,$68,$68,$b8), ($82,$41,$41,$c3), ($29,$99,$99,$b0), ($5a,$2d,$2d,$77), ($1e,$0f,$0f,$11), ($7b,$b0,$b0,$cb), ($a8,$54,$54,$fc), ($6d,$bb,$bb,$d6), ($2c,$16,$16,$3a)); T2: array[0..255,0..3] of byte= ( @@ -597,7 +597,7 @@ const ($cf,$8a,$45,$45), ($10,$e9,$f9,$f9), ($06,$04,$02,$02), ($81,$fe,$7f,$7f), ($f0,$a0,$50,$50), ($44,$78,$3c,$3c), ($ba,$25,$9f,$9f), ($e3,$4b,$a8,$a8), ($f3,$a2,$51,$51), ($fe,$5d,$a3,$a3), ($c0,$80,$40,$40), ($8a,$05,$8f,$8f), - ($ad,$3f,$92,$92), ($bc,$21,$9d,$9d), ($48,$70,$38,$38), ($04,$f1,$f5,$f5), + ($ad,$3f,$92,$92), ($bc,$21,$9d,$9d), ($48,$70,$38,$38), ($04,$f1,$f5,$f5), ($df,$63,$bc,$bc), ($c1,$77,$b6,$b6), ($75,$af,$da,$da), ($63,$42,$21,$21), ($30,$20,$10,$10), ($1a,$e5,$ff,$ff), ($0e,$fd,$f3,$f3), ($6d,$bf,$d2,$d2), ($4c,$81,$cd,$cd), ($14,$18,$0c,$0c), ($35,$26,$13,$13), ($2f,$c3,$ec,$ec), @@ -663,7 +663,7 @@ const ($50,$f0,$a0,$50), ($3c,$44,$78,$3c), ($9f,$ba,$25,$9f), ($a8,$e3,$4b,$a8), ($51,$f3,$a2,$51), ($a3,$fe,$5d,$a3), ($40,$c0,$80,$40), ($8f,$8a,$05,$8f), ($92,$ad,$3f,$92), ($9d,$bc,$21,$9d), ($38,$48,$70,$38), ($f5,$04,$f1,$f5), - ($bc,$df,$63,$bc), ($b6,$c1,$77,$b6), ($da,$75,$af,$da), ($21,$63,$42,$21), + ($bc,$df,$63,$bc), ($b6,$c1,$77,$b6), ($da,$75,$af,$da), ($21,$63,$42,$21), ($10,$30,$20,$10), ($ff,$1a,$e5,$ff), ($f3,$0e,$fd,$f3), ($d2,$6d,$bf,$d2), ($cd,$4c,$81,$cd), ($0c,$14,$18,$0c), ($13,$35,$26,$13), ($ec,$2f,$c3,$ec), ($5f,$e1,$be,$5f), ($97,$a2,$35,$97), ($44,$cc,$88,$44), ($17,$39,$2e,$17), @@ -795,7 +795,7 @@ const ($80,$c0,$c5,$4f), ($61,$dc,$20,$a2), ($5a,$77,$4b,$69), ($1c,$12,$1a,$16), ($e2,$93,$ba,$0a), ($c0,$a0,$2a,$e5), ($3c,$22,$e0,$43), ($12,$1b,$17,$1d), ($0e,$09,$0d,$0b), ($f2,$8b,$c7,$ad), ($2d,$b6,$a8,$b9), ($14,$1e,$a9,$c8), - ($57,$f1,$19,$85), ($af,$75,$07,$4c), ($ee,$99,$dd,$bb), ($a3,$7f,$60,$fd), + ($57,$f1,$19,$85), ($af,$75,$07,$4c), ($ee,$99,$dd,$bb), ($a3,$7f,$60,$fd), ($f7,$01,$26,$9f), ($5c,$72,$f5,$bc), ($44,$66,$3b,$c5), ($5b,$fb,$7e,$34), ($8b,$43,$29,$76), ($cb,$23,$c6,$dc), ($b6,$ed,$fc,$68), ($b8,$e4,$f1,$63), ($d7,$31,$dc,$ca), ($42,$63,$85,$10), ($13,$97,$22,$40), ($84,$c6,$11,$20), @@ -861,7 +861,7 @@ const ($0a,$e2,$93,$ba), ($e5,$c0,$a0,$2a), ($43,$3c,$22,$e0), ($1d,$12,$1b,$17), ($0b,$0e,$09,$0d), ($ad,$f2,$8b,$c7), ($b9,$2d,$b6,$a8), ($c8,$14,$1e,$a9), ($85,$57,$f1,$19), ($4c,$af,$75,$07), ($bb,$ee,$99,$dd), ($fd,$a3,$7f,$60), - ($9f,$f7,$01,$26), ($bc,$5c,$72,$f5), ($c5,$44,$66,$3b), ($34,$5b,$fb,$7e), + ($9f,$f7,$01,$26), ($bc,$5c,$72,$f5), ($c5,$44,$66,$3b), ($34,$5b,$fb,$7e), ($76,$8b,$43,$29), ($dc,$cb,$23,$c6), ($68,$b6,$ed,$fc), ($63,$b8,$e4,$f1), ($ca,$d7,$31,$dc), ($10,$42,$63,$85), ($40,$13,$97,$22), ($20,$84,$c6,$11), ($7d,$85,$4a,$24), ($f8,$d2,$bb,$3d), ($11,$ae,$f9,$32), ($6d,$c7,$29,$a1), @@ -927,7 +927,7 @@ const ($0d,$0b,$0e,$09), ($c7,$ad,$f2,$8b), ($a8,$b9,$2d,$b6), ($a9,$c8,$14,$1e), ($19,$85,$57,$f1), ($07,$4c,$af,$75), ($dd,$bb,$ee,$99), ($60,$fd,$a3,$7f), ($26,$9f,$f7,$01), ($f5,$bc,$5c,$72), ($3b,$c5,$44,$66), ($7e,$34,$5b,$fb), - ($29,$76,$8b,$43), ($c6,$dc,$cb,$23), ($fc,$68,$b6,$ed), ($f1,$63,$b8,$e4), + ($29,$76,$8b,$43), ($c6,$dc,$cb,$23), ($fc,$68,$b6,$ed), ($f1,$63,$b8,$e4), ($dc,$ca,$d7,$31), ($85,$10,$42,$63), ($22,$40,$13,$97), ($11,$20,$84,$c6), ($24,$7d,$85,$4a), ($3d,$f8,$d2,$bb), ($32,$11,$ae,$f9), ($a1,$6d,$c7,$29), ($2f,$4b,$1d,$9e), ($30,$f3,$dc,$b2), ($52,$ec,$0d,$86), ($e3,$d0,$77,$c1), @@ -1092,7 +1092,7 @@ const ($38,$24,$34,$2c), ($36,$2d,$39,$27), ($24,$36,$2e,$3a), ($2a,$3f,$23,$31), ($70,$48,$68,$58), ($7e,$41,$65,$53), ($6c,$5a,$72,$4e), ($62,$53,$7f,$45), ($48,$6c,$5c,$74), ($46,$65,$51,$7f), ($54,$7e,$46,$62), ($5a,$77,$4b,$69), - ($e0,$90,$d0,$b0), ($ee,$99,$dd,$bb), ($fc,$82,$ca,$a6), ($f2,$8b,$c7,$ad), + ($e0,$90,$d0,$b0), ($ee,$99,$dd,$bb), ($fc,$82,$ca,$a6), ($f2,$8b,$c7,$ad), ($d8,$b4,$e4,$9c), ($d6,$bd,$e9,$97), ($c4,$a6,$fe,$8a), ($ca,$af,$f3,$81), ($90,$d8,$b8,$e8), ($9e,$d1,$b5,$e3), ($8c,$ca,$a2,$fe), ($82,$c3,$af,$f5), ($a8,$fc,$8c,$c4), ($a6,$f5,$81,$cf), ($b4,$ee,$96,$d2), ($ba,$e7,$9b,$d9), @@ -1125,7 +1125,7 @@ const ($31,$a4,$b2,$af), ($3f,$ad,$bf,$a4), ($2d,$b6,$a8,$b9), ($23,$bf,$a5,$b2), ($09,$80,$86,$83), ($07,$89,$8b,$88), ($15,$92,$9c,$95), ($1b,$9b,$91,$9e), ($a1,$7c,$0a,$47), ($af,$75,$07,$4c), ($bd,$6e,$10,$51), ($b3,$67,$1d,$5a), - ($99,$58,$3e,$6b), ($97,$51,$33,$60), ($85,$4a,$24,$7d), ($8b,$43,$29,$76), + ($99,$58,$3e,$6b), ($97,$51,$33,$60), ($85,$4a,$24,$7d), ($8b,$43,$29,$76), ($d1,$34,$62,$1f), ($df,$3d,$6f,$14), ($cd,$26,$78,$09), ($c3,$2f,$75,$02), ($e9,$10,$56,$33), ($e7,$19,$5b,$38), ($f5,$02,$4c,$25), ($fb,$0b,$41,$2e), ($9a,$d7,$61,$8c), ($94,$de,$6c,$87), ($86,$c5,$7b,$9a), ($88,$cc,$76,$91), @@ -1158,7 +1158,7 @@ const ($58,$70,$48,$68), ($53,$7e,$41,$65), ($4e,$6c,$5a,$72), ($45,$62,$53,$7f), ($74,$48,$6c,$5c), ($7f,$46,$65,$51), ($62,$54,$7e,$46), ($69,$5a,$77,$4b), ($b0,$e0,$90,$d0), ($bb,$ee,$99,$dd), ($a6,$fc,$82,$ca), ($ad,$f2,$8b,$c7), - ($9c,$d8,$b4,$e4), ($97,$d6,$bd,$e9), ($8a,$c4,$a6,$fe), ($81,$ca,$af,$f3), + ($9c,$d8,$b4,$e4), ($97,$d6,$bd,$e9), ($8a,$c4,$a6,$fe), ($81,$ca,$af,$f3), ($e8,$90,$d8,$b8), ($e3,$9e,$d1,$b5), ($fe,$8c,$ca,$a2), ($f5,$82,$c3,$af), ($c4,$a8,$fc,$8c), ($cf,$a6,$f5,$81), ($d2,$b4,$ee,$96), ($d9,$ba,$e7,$9b), ($7b,$db,$3b,$bb), ($70,$d5,$32,$b6), ($6d,$c7,$29,$a1), ($66,$c9,$20,$ac), @@ -1191,7 +1191,7 @@ const ($83,$09,$80,$86), ($88,$07,$89,$8b), ($95,$15,$92,$9c), ($9e,$1b,$9b,$91), ($47,$a1,$7c,$0a), ($4c,$af,$75,$07), ($51,$bd,$6e,$10), ($5a,$b3,$67,$1d), ($6b,$99,$58,$3e), ($60,$97,$51,$33), ($7d,$85,$4a,$24), ($76,$8b,$43,$29), - ($1f,$d1,$34,$62), ($14,$df,$3d,$6f), ($09,$cd,$26,$78), ($02,$c3,$2f,$75), + ($1f,$d1,$34,$62), ($14,$df,$3d,$6f), ($09,$cd,$26,$78), ($02,$c3,$2f,$75), ($33,$e9,$10,$56), ($38,$e7,$19,$5b), ($25,$f5,$02,$4c), ($2e,$fb,$0b,$41), ($8c,$9a,$d7,$61), ($87,$94,$de,$6c), ($9a,$86,$c5,$7b), ($91,$88,$cc,$76), ($a0,$a2,$f3,$55), ($ab,$ac,$fa,$58), ($b6,$be,$e1,$4f), ($bd,$b0,$e8,$42), @@ -1290,7 +1290,7 @@ const ($90,$d0,$b0,$e0), ($99,$dd,$bb,$ee), ($82,$ca,$a6,$fc), ($8b,$c7,$ad,$f2), ($b4,$e4,$9c,$d8), ($bd,$e9,$97,$d6), ($a6,$fe,$8a,$c4), ($af,$f3,$81,$ca), ($d8,$b8,$e8,$90), ($d1,$b5,$e3,$9e), ($ca,$a2,$fe,$8c), ($c3,$af,$f5,$82), - ($fc,$8c,$c4,$a8), ($f5,$81,$cf,$a6), ($ee,$96,$d2,$b4), ($e7,$9b,$d9,$ba), + ($fc,$8c,$c4,$a8), ($f5,$81,$cf,$a6), ($ee,$96,$d2,$b4), ($e7,$9b,$d9,$ba), ($3b,$bb,$7b,$db), ($32,$b6,$70,$d5), ($29,$a1,$6d,$c7), ($20,$ac,$66,$c9), ($1f,$8f,$57,$e3), ($16,$82,$5c,$ed), ($0d,$95,$41,$ff), ($04,$98,$4a,$f1), ($73,$d3,$23,$ab), ($7a,$de,$28,$a5), ($61,$c9,$35,$b7), ($68,$c4,$3e,$b9), @@ -1356,16 +1356,6 @@ const type PDWord = ^LongWord; -function XorString(Indata1, Indata2: AnsiString): AnsiString; -var - i: integer; -begin - Indata2 := PadString(Indata2, length(Indata1), #0); - Result := ''; - for i := 1 to length(Indata1) do - Result := Result + AnsiChar(ord(Indata1[i]) xor ord(Indata2[i])); -end; - procedure hperm_op(var a, t: integer; n, m: integer); begin t:= ((a shl (16 - n)) xor a) and m; diff --git a/synautil.pas b/synautil.pas index db7f483..7181193 100644 --- a/synautil.pas +++ b/synautil.pas @@ -1,5 +1,5 @@ {==============================================================================| -| Project : Ararat Synapse | 004.014.000 | +| Project : Ararat Synapse | 004.014.001 | |==============================================================================| | Content: support procedures and functions | |==============================================================================| @@ -324,6 +324,9 @@ function GetTempFile(const Dir, prefix: AnsiString): AnsiString; smaller, string is padded by Pad character.} function PadString(const Value: AnsiString; len: integer; Pad: AnsiChar): AnsiString; +{:XOR each byte in the strings} +function XorString(Indata1, Indata2: AnsiString): AnsiString; + {:Read header from "Value" stringlist beginning at "Index" position. If header is Splitted into multiple lines, then this procedure de-split it into one line.} function NormalizeHeader(Value: TStrings; var Index: Integer): string; @@ -1781,6 +1784,18 @@ end; {==============================================================================} +function XorString(Indata1, Indata2: AnsiString): AnsiString; +var + i: integer; +begin + Indata2 := PadString(Indata2, length(Indata1), #0); + Result := ''; + for i := 1 to length(Indata1) do + Result := Result + AnsiChar(ord(Indata1[i]) xor ord(Indata2[i])); +end; + +{==============================================================================} + function NormalizeHeader(Value: TStrings; var Index: Integer): string; var s, t: string;