@@ -5,7 +5,10 @@ import (
55 "fmt"
66 "log/slog"
77 "net"
8+ "strconv"
9+ "strings"
810 "testing"
11+ "time"
912
1013 "github.com/jkroepke/openvpn-auth-oauth2/internal/openvpn"
1114 "github.com/jkroepke/openvpn-auth-oauth2/internal/utils/testutils"
@@ -48,6 +51,10 @@ func TestServer_Listen(t *testing.T) {
4851 client , err := dialer .DialContext (t .Context (), tc .protocol , managementInterface .Addr ().String ())
4952 require .NoError (t , err )
5053
54+ t .Cleanup (func () {
55+ _ = client .Close ()
56+ })
57+
5158 clientReader := bufio .NewReader (client )
5259
5360 testutils .ExpectMessage (t , client , clientReader , openvpn .WelcomeBanner )
@@ -108,7 +115,7 @@ func TestServer_Listen_Invalid_Addr(t *testing.T) {
108115 }
109116}
110117
111- func TestServer_Listen_Password (t * testing.T ) {
118+ func TestServer_Listen_Password_Correct (t * testing.T ) {
112119 t .Parallel ()
113120
114121 managementInterface , err := nettest .NewLocalListener ("tcp" )
@@ -128,6 +135,10 @@ func TestServer_Listen_Password(t *testing.T) {
128135 client , err := dialer .DialContext (t .Context (), "tcp" , managementInterface .Addr ().String ())
129136 require .NoError (t , err )
130137
138+ t .Cleanup (func () {
139+ _ = client .Close ()
140+ })
141+
131142 clientReader := bufio .NewReader (client )
132143
133144 resp , err := clientReader .ReadString (':' )
@@ -139,3 +150,237 @@ func TestServer_Listen_Password(t *testing.T) {
139150 testutils .ExpectMessage (t , client , clientReader , openvpn .WelcomeBanner )
140151 testutils .SendMessagef (t , client , "quit" )
141152}
153+
154+ func TestServer_Listen_Password_Incorrect (t * testing.T ) {
155+ t .Parallel ()
156+
157+ managementInterface , err := nettest .NewLocalListener ("tcp" )
158+ require .NoError (t , err )
159+
160+ err = managementInterface .Close ()
161+ require .NoError (t , err )
162+
163+ managementServer := management .NewServer (slog .New (slog .DiscardHandler ), testutils .Secret )
164+ err = managementServer .Listen (t .Context (), fmt .Sprintf ("%s://%s" , managementInterface .Addr ().Network (), managementInterface .Addr ().String ()))
165+ require .NoError (t , err )
166+
167+ t .Cleanup (managementServer .Close )
168+
169+ var dialer net.Dialer
170+
171+ client , err := dialer .DialContext (t .Context (), "tcp" , managementInterface .Addr ().String ())
172+ require .NoError (t , err )
173+
174+ t .Cleanup (func () {
175+ _ = client .Close ()
176+ })
177+
178+ clientReader := bufio .NewReader (client )
179+
180+ resp , err := clientReader .ReadString (':' )
181+ require .NoError (t , err )
182+ require .Equal (t , "ENTER PASSWORD:" , resp )
183+
184+ testutils .SendMessagef (t , client , testutils .Password )
185+ testutils .ExpectMessage (t , client , clientReader , "ERROR: bad password" )
186+ testutils .SendMessagef (t , client , "quit" )
187+ }
188+
189+ func TestServer_AuthPendingPoller (t * testing.T ) {
190+ t .Parallel ()
191+
192+ for _ , tc := range []struct {
193+ name string
194+ command string
195+ resp string
196+ testFn func (t * testing.T , response * management.Response )
197+ }{
198+ {
199+ name : "client-auth-nt" ,
200+ command : "client-auth-nt 1 0" ,
201+ resp : "SUCCESS: client-auth command succeeded" ,
202+ testFn : func (t * testing.T , response * management.Response ) {
203+ t .Helper ()
204+
205+ require .Equal (t , uint32 (1 ), response .ClientID )
206+ require .Equal (t , management .ClientAuthAccept , response .ClientAuth )
207+ },
208+ },
209+ {
210+ name : "client-auth-nt invalid" ,
211+ command : "client-auth-nt A B" ,
212+ resp : "ERROR: client-auth command failed" ,
213+ },
214+ {
215+ name : "client-auth" ,
216+ command : "client-auth 2 0\r \n push \" reneg-sec 0\" \r \n END" ,
217+ resp : "SUCCESS: client-auth command succeeded" ,
218+ testFn : func (t * testing.T , response * management.Response ) {
219+ t .Helper ()
220+
221+ require .Equal (t , uint32 (2 ), response .ClientID )
222+ require .Equal (t , management .ClientAuthAccept , response .ClientAuth )
223+ require .Equal (t , "push \" reneg-sec 0\" " , response .ClientConfig )
224+ },
225+ },
226+ {
227+ name : "client-deny without reason" ,
228+ command : "client-deny 3 0" ,
229+ resp : "SUCCESS: client-deny command succeeded" ,
230+ testFn : func (t * testing.T , response * management.Response ) {
231+ t .Helper ()
232+
233+ require .Equal (t , uint32 (3 ), response .ClientID )
234+ require .Equal (t , management .ClientAuthDeny , response .ClientAuth )
235+ require .Equal (t , "access denied" , response .Message )
236+ },
237+ },
238+ {
239+ name : "client-deny" ,
240+ command : "client-deny 3 0 \" internal error\" " ,
241+ resp : "SUCCESS: client-deny command succeeded" ,
242+ testFn : func (t * testing.T , response * management.Response ) {
243+ t .Helper ()
244+
245+ require .Equal (t , uint32 (3 ), response .ClientID )
246+ require .Equal (t , management .ClientAuthDeny , response .ClientAuth )
247+ require .Equal (t , "internal error" , response .Message )
248+ },
249+ },
250+ {
251+ name : "client-pending-auth" ,
252+ command : "client-pending-auth 4 0 \" WEB_AUTH::https://sso.example.com/auth?session=xyz\" 300" ,
253+ resp : "SUCCESS: client-pending-auth command succeeded" ,
254+ testFn : func (t * testing.T , response * management.Response ) {
255+ t .Helper ()
256+
257+ require .Equal (t , uint32 (4 ), response .ClientID )
258+ require .Equal (t , management .ClientAuthPending , response .ClientAuth )
259+ require .Equal (t , "WEB_AUTH::https://sso.example.com/auth?session=xyz" , response .Message )
260+ require .Equal (t , "300" , response .Timeout )
261+ },
262+ },
263+ {
264+ name : "client-pending-auth without timeout" ,
265+ command : "client-pending-auth 4 0 \" WEB_AUTH::https://sso.example.com/auth?session=xyz\" " ,
266+ resp : "ERROR: client-pending-auth command failed" ,
267+ testFn : func (t * testing.T , response * management.Response ) {
268+ t .Helper ()
269+
270+ require .Equal (t , uint32 (4 ), response .ClientID )
271+ require .Equal (t , management .ClientAuthDeny , response .ClientAuth )
272+ require .Equal (t , "internal error" , response .Message )
273+ },
274+ },
275+ {
276+ name : "invalid" ,
277+ command : "invalid" ,
278+ resp : "ERROR: unknown command, enter 'help' for more options" ,
279+ },
280+ } {
281+ t .Run (tc .name , func (t * testing.T ) {
282+ t .Parallel ()
283+
284+ managementInterface , err := nettest .NewLocalListener ("tcp" )
285+ require .NoError (t , err )
286+
287+ err = managementInterface .Close ()
288+ require .NoError (t , err )
289+
290+ managementServer := management .NewServer (slog .New (slog .DiscardHandler ), "" )
291+ err = managementServer .Listen (t .Context (), fmt .Sprintf ("%s://%s" , managementInterface .Addr ().Network (), managementInterface .Addr ().String ()))
292+ require .NoError (t , err )
293+
294+ t .Cleanup (managementServer .Close )
295+
296+ responseCh := make (chan * management.Response , 1 )
297+ errCh := make (chan error , 1 )
298+
299+ var clientID uint64
300+
301+ if ! strings .HasSuffix (tc .name , "invalid" ) {
302+ clientID , err = strconv .ParseUint (strings .Split (tc .command , " " )[1 ], 10 , 64 )
303+ require .NoError (t , err )
304+
305+ go func () {
306+ response , err := managementServer .AuthPendingPoller (clientID , time .Second * 5 )
307+
308+ errCh <- err
309+
310+ responseCh <- response
311+ }()
312+ }
313+
314+ var dialer net.Dialer
315+
316+ client , err := dialer .DialContext (t .Context (), "tcp" , managementInterface .Addr ().String ())
317+ require .NoError (t , err )
318+
319+ t .Cleanup (func () {
320+ _ = client .Close ()
321+ })
322+
323+ clientReader := bufio .NewReader (client )
324+
325+ testutils .ExpectMessage (t , client , clientReader , openvpn .WelcomeBanner )
326+ testutils .SendMessagef (t , client , tc .command )
327+
328+ testutils .ExpectMessage (t , client , clientReader , tc .resp )
329+
330+ if strings .HasSuffix (tc .name , "invalid" ) {
331+ return
332+ }
333+
334+ require .NoError (t , <- errCh )
335+
336+ response := <- responseCh
337+ require .NotNil (t , response )
338+
339+ if tc .testFn == nil {
340+ return
341+ }
342+
343+ tc .testFn (t , response )
344+ })
345+ }
346+ }
347+
348+ func TestServer_AuthPendingPoller_Twice (t * testing.T ) {
349+ t .Parallel ()
350+
351+ managementInterface , err := nettest .NewLocalListener ("tcp" )
352+ require .NoError (t , err )
353+
354+ err = managementInterface .Close ()
355+ require .NoError (t , err )
356+
357+ managementServer := management .NewServer (slog .New (slog .DiscardHandler ), "" )
358+ err = managementServer .Listen (t .Context (), fmt .Sprintf ("%s://%s" , managementInterface .Addr ().Network (), managementInterface .Addr ().String ()))
359+ require .NoError (t , err )
360+
361+ t .Cleanup (managementServer .Close )
362+
363+ errCh := make (chan error , 1 )
364+
365+ go func () {
366+ _ , err := managementServer .AuthPendingPoller (0 , time .Millisecond * 10 )
367+ errCh <- err
368+ }()
369+
370+ go func () {
371+ _ , err := managementServer .AuthPendingPoller (0 , time .Millisecond * 10 )
372+ errCh <- err
373+ }()
374+
375+ require .EqualError (t , <- errCh , "poller for client ID 0 already exists" )
376+ require .EqualError (t , <- errCh , "timeout waiting for client response" )
377+ }
378+
379+ func TestClientAuth_String (t * testing.T ) {
380+ t .Parallel ()
381+
382+ require .Equal (t , "ACCEPT" , management .ClientAuthAccept .String ())
383+ require .Equal (t , "DENY" , management .ClientAuthDeny .String ())
384+ require .Equal (t , "PENDING" , management .ClientAuthPending .String ())
385+ require .Equal (t , "UNKNOWN" , management .ClientAuth (4 ).String ())
386+ }
0 commit comments