@@ -4,24 +4,36 @@ import arrays
4
4
import os
5
5
import io
6
6
import math.big
7
- import crypto.cipher
7
+ // import crypto.cipher
8
8
import x.crypto.chacha20
9
9
import crypto.sha256
10
10
import net
11
11
12
- const plugin_list = 'Srp256,Srp' // LegacyAuth not supported
12
+ const plugin_list = 'Srp256,Srp'
13
13
const buffer_len = 1024
14
14
const max_char_length = 32767
15
15
const blob_segment_size = 32000
16
16
17
+ const low_priority_todo = 'https://github.com/Coachonko/firebird/blob/pending/TODO.md#low-priority'
18
+ const legacy_auth_error = 'LegacyAuth is not supported: ${low_priority_todo} '
19
+ const arc4_error = 'Arc4 wire encryption plugin is not supported: ${low_priority_todo} '
20
+
17
21
struct WireChannel {
18
22
mut :
19
23
conn net.TcpConn
20
24
reader & io.BufferedReader
25
+ // The firebird protocol expects that we are in control of when the writing is flushed.
26
+ // In some situations it is required that flushing is deferred.
27
+ // io.BufferedWriter doesn't exist
28
+ // https://github.com/vlang/v/issues/21975
21
29
// writer &io.BufferedWriter
22
- plugin string
23
- crypto_reader & cipher.Stream
24
- crypto_writer & cipher.Stream
30
+ plugin string
31
+ // crypto_reader and crypto_writer should implement cipher.Stream
32
+ // This allows to use any supported stream cipher
33
+ // chacha20.Cipher and rc4.Cipher implement the cipher.Stream interface wrong.
34
+ // https://github.com/vlang/v/issues/21973
35
+ crypto_reader & chacha20 .Cipher // &cipher.Stream
36
+ crypto_writer & chacha20 .Cipher // &cipher.Stream
25
37
}
26
38
27
39
fn new_wire_channel (conn net.TcpConn) & WireChannel {
@@ -39,18 +51,105 @@ fn new_wire_channel(conn net.TcpConn) &WireChannel {
39
51
40
52
fn (mut c WireChannel) set_crypt_key (plugin string , session_key []u8 , nonce []u8 ) ! {
41
53
c.plugin = plugin
54
+ if plugin == 'Arc4' {
55
+ return error (firebird.arc4_ error)
56
+ }
57
+
42
58
if plugin == 'ChaCha' {
43
59
mut digest := sha256 .new ()
44
60
digest.write (session_key)!
45
61
key := digest.sum ([]u8 {})
46
- c.crypto_reader = chacha20 .new_cipher (key, nonce)! // https://github.com/vlang/v/issues/21973
62
+ c.crypto_reader = chacha20 .new_cipher (key, nonce)!
47
63
c.crypto_writer = chacha20 .new_cipher (key, nonce)!
48
- } else if plugin == 'Arc4' {
49
- return error ('Arc4 wire encryption plugin is not supported: https://github.com/Coachonko/firebird/blob/pending/TODO.md#low-priority' )
50
- } else {
51
- return error ('Unknown wire encryption plugin name: ${plugin} ' )
52
64
}
53
- return
65
+
66
+ return error ('Unknown wire encryption plugin name: ${plugin} ' )
67
+ }
68
+
69
+ fn (mut c WireChannel) read (mut buf []u8 ) ! int {
70
+ if c.plugin != '' {
71
+ mut src := []u8 {}
72
+ n := c.reader.read (mut src)!
73
+ if c.plugin == 'Arc4' {
74
+ return error (firebird.arc4_ error)
75
+ }
76
+
77
+ if c.plugin == 'ChaCha' {
78
+ c.crypto_reader.xor_key_stream (mut buf, src[0 ..n])
79
+ }
80
+
81
+ return n
82
+ }
83
+
84
+ return c.reader.read (mut buf)
85
+ }
86
+
87
+ fn (mut c WireChannel) write (buf []u8 ) ! int {
88
+ return c.conn.write (buf)!
89
+ }
90
+
91
+ // fn (mut c WireChannel) write(buf []u8) !int {
92
+ // if c.plugin != '' {
93
+ // mut dst := []u8{}
94
+ // if c.plugin == 'Arc4' {
95
+ // return error(firebird.arc4_error)
96
+ // }
97
+
98
+ // if c.plugin == 'ChaCha' {
99
+ // c.crypto_writer.xor_key_stream(mut dst, buf)
100
+ // }
101
+
102
+ // mut written := 0
103
+ // for written < buf.len {
104
+ // written += c.writer.write(dst[written..])!
105
+ // }
106
+ // return written
107
+ // }
108
+
109
+ // return c.writer.write(mut buf)
110
+ // }
111
+
112
+ // fn (mut c WireChannel) flush() ! {
113
+ // c.writer.flush()!
114
+ // }
115
+
116
+ fn (mut c WireChannel) close () ! {
117
+ c.conn.close ()!
118
+ }
119
+
120
+ struct WireProtocol {
121
+ buf []u8
122
+
123
+ conn WireChannel
124
+ db_handle i32
125
+ addr string
126
+
127
+ protocol_version i32
128
+ accept_architecture i32
129
+ accept_type i32
130
+ lazy_response_count int
131
+
132
+ plugin_name string
133
+ user string
134
+ password string
135
+ auth_data []u8
136
+
137
+ charset string
138
+ charset_byte_len int
139
+
140
+ timezone string
141
+ }
142
+
143
+ fn new_wire_protocol (addr string , timezone string ) ! & WireProtocol {
144
+ conn := net.dial_tcp (addr)!
145
+ return & WireProtocol{
146
+ buf: []u8 {}
147
+ conn: new_wire_channel (conn)
148
+ addr: addr
149
+ charset: 'UTF8'
150
+ charset_byte_len: 4
151
+ timezone: timezone
152
+ }
54
153
}
55
154
56
155
fn user_identification (user string , auth_plugin_name string , wire_crypt bool , client_public big.Integer) []u8 {
@@ -94,7 +193,7 @@ fn user_identification(user string, auth_plugin_name string, wire_crypt bool, cl
94
193
}
95
194
96
195
if auth_plugin_name == 'Legacy_Auth' {
97
- panic ('Unsupported plugin: ${auth_plugin_name} ' )
196
+ panic (firebird.legacy_auth_error )
98
197
}
99
198
panic ('Unknown plugin name: ${auth_plugin_name} ' )
100
199
}
0 commit comments