@@ -33,12 +33,19 @@ var clientPassword = "tiger"
33
33
// tryAuth runs a handshake with a given config against an SSH server
34
34
// with config serverConfig. Returns both client and server side errors.
35
35
func tryAuth (t * testing.T , config * ClientConfig ) error {
36
- err , _ := tryAuthBothSides (t , config )
36
+ err , _ := tryAuthBothSides (t , config , nil )
37
+ return err
38
+ }
39
+
40
+ // tryAuth runs a handshake with a given config against an SSH server
41
+ // with a given GSSAPIWithMICConfig and config serverConfig. Returns both client and server side errors.
42
+ func tryAuthWithGSSAPIWithMICConfig (t * testing.T , clientConfig * ClientConfig , gssAPIWithMICConfig * GSSAPIWithMICConfig ) error {
43
+ err , _ := tryAuthBothSides (t , clientConfig , gssAPIWithMICConfig )
37
44
return err
38
45
}
39
46
40
47
// tryAuthBothSides runs the handshake and returns the resulting errors from both sides of the connection.
41
- func tryAuthBothSides (t * testing.T , config * ClientConfig ) (clientError error , serverAuthErrors []error ) {
48
+ func tryAuthBothSides (t * testing.T , config * ClientConfig , gssAPIWithMICConfig * GSSAPIWithMICConfig ) (clientError error , serverAuthErrors []error ) {
42
49
c1 , c2 , err := netPipe ()
43
50
if err != nil {
44
51
t .Fatalf ("netPipe: %v" , err )
@@ -61,7 +68,6 @@ func tryAuthBothSides(t *testing.T, config *ClientConfig) (clientError error, se
61
68
return c .Serial == 666
62
69
},
63
70
}
64
-
65
71
serverConfig := & ServerConfig {
66
72
PasswordCallback : func (conn ConnMetadata , pass []byte ) (* Permissions , error ) {
67
73
if conn .User () == "testuser" && string (pass ) == clientPassword {
@@ -85,6 +91,7 @@ func tryAuthBothSides(t *testing.T, config *ClientConfig) (clientError error, se
85
91
}
86
92
return nil , errors .New ("keyboard-interactive failed" )
87
93
},
94
+ GSSAPIWithMICConfig : gssAPIWithMICConfig ,
88
95
}
89
96
serverConfig .AddHostKey (testSigners ["rsa" ])
90
97
@@ -247,7 +254,7 @@ func TestMethodInvalidAlgorithm(t *testing.T) {
247
254
HostKeyCallback : InsecureIgnoreHostKey (),
248
255
}
249
256
250
- err , serverErrors := tryAuthBothSides (t , config )
257
+ err , serverErrors := tryAuthBothSides (t , config , nil )
251
258
if err == nil {
252
259
t .Fatalf ("login succeeded" )
253
260
}
@@ -686,3 +693,206 @@ func TestClientAuthErrorList(t *testing.T) {
686
693
}
687
694
}
688
695
}
696
+
697
+ func TestAuthMethodGSSAPIWithMIC (t * testing.T ) {
698
+ type testcase struct {
699
+ config * ClientConfig
700
+ gssConfig * GSSAPIWithMICConfig
701
+ clientWantErr string
702
+ serverWantErr string
703
+ }
704
+ testcases := []* testcase {
705
+ {
706
+ config : & ClientConfig {
707
+ User : "testuser" ,
708
+ Auth : []AuthMethod {
709
+ GSSAPIWithMICAuthMethod (
710
+ & FakeClient {
711
+ exchanges : []* exchange {
712
+ {
713
+ outToken : "client-valid-token-1" ,
714
+ },
715
+ {
716
+ expectedToken : "server-valid-token-1" ,
717
+ },
718
+ },
719
+ mic : []byte ("valid-mic" ),
720
+ maxRound : 2 ,
721
+ }, "testtarget" ,
722
+ ),
723
+ },
724
+ HostKeyCallback : InsecureIgnoreHostKey (),
725
+ },
726
+ gssConfig : & GSSAPIWithMICConfig {
727
+ AllowLogin : func (conn ConnMetadata , srcName string ) (* Permissions , error ) {
728
+ if srcName != conn .User ()+ "@DOMAIN" {
729
+ return nil , fmt .Errorf ("srcName is %s, conn user is %s" , srcName , conn .User ())
730
+ }
731
+ return nil , nil
732
+ },
733
+ Server : & FakeServer {
734
+ exchanges : []* exchange {
735
+ {
736
+ outToken : "server-valid-token-1" ,
737
+ expectedToken : "client-valid-token-1" ,
738
+ },
739
+ },
740
+ maxRound : 1 ,
741
+ expectedMIC : []byte ("valid-mic" ),
742
+ srcName : "testuser@DOMAIN" ,
743
+ },
744
+ },
745
+ },
746
+ {
747
+ config : & ClientConfig {
748
+ User : "testuser" ,
749
+ Auth : []AuthMethod {
750
+ GSSAPIWithMICAuthMethod (
751
+ & FakeClient {
752
+ exchanges : []* exchange {
753
+ {
754
+ outToken : "client-valid-token-1" ,
755
+ },
756
+ {
757
+ expectedToken : "server-valid-token-1" ,
758
+ },
759
+ },
760
+ mic : []byte ("valid-mic" ),
761
+ maxRound : 2 ,
762
+ }, "testtarget" ,
763
+ ),
764
+ },
765
+ HostKeyCallback : InsecureIgnoreHostKey (),
766
+ },
767
+ gssConfig : & GSSAPIWithMICConfig {
768
+ AllowLogin : func (conn ConnMetadata , srcName string ) (* Permissions , error ) {
769
+ return nil , fmt .Errorf ("user is not allowed to login" )
770
+ },
771
+ Server : & FakeServer {
772
+ exchanges : []* exchange {
773
+ {
774
+ outToken : "server-valid-token-1" ,
775
+ expectedToken : "client-valid-token-1" ,
776
+ },
777
+ },
778
+ maxRound : 1 ,
779
+ expectedMIC : []byte ("valid-mic" ),
780
+ srcName : "testuser@DOMAIN" ,
781
+ },
782
+ },
783
+ serverWantErr : "user is not allowed to login" ,
784
+ clientWantErr : "ssh: handshake failed: ssh: unable to authenticate" ,
785
+ },
786
+ {
787
+ config : & ClientConfig {
788
+ User : "testuser" ,
789
+ Auth : []AuthMethod {
790
+ GSSAPIWithMICAuthMethod (
791
+ & FakeClient {
792
+ exchanges : []* exchange {
793
+ {
794
+ outToken : "client-valid-token-1" ,
795
+ },
796
+ {
797
+ expectedToken : "server-valid-token-1" ,
798
+ },
799
+ },
800
+ mic : []byte ("valid-mic" ),
801
+ maxRound : 2 ,
802
+ }, "testtarget" ,
803
+ ),
804
+ },
805
+ HostKeyCallback : InsecureIgnoreHostKey (),
806
+ },
807
+ gssConfig : & GSSAPIWithMICConfig {
808
+ AllowLogin : func (conn ConnMetadata , srcName string ) (* Permissions , error ) {
809
+ if srcName != conn .User () {
810
+ return nil , fmt .Errorf ("srcName is %s, conn user is %s" , srcName , conn .User ())
811
+ }
812
+ return nil , nil
813
+ },
814
+ Server : & FakeServer {
815
+ exchanges : []* exchange {
816
+ {
817
+ outToken : "server-invalid-token-1" ,
818
+ expectedToken : "client-valid-token-1" ,
819
+ },
820
+ },
821
+ maxRound : 1 ,
822
+ expectedMIC : []byte ("valid-mic" ),
823
+ srcName : "testuser@DOMAIN" ,
824
+ },
825
+ },
826
+ clientWantErr : "ssh: handshake failed: got \" server-invalid-token-1\" , want token \" server-valid-token-1\" " ,
827
+ },
828
+ {
829
+ config : & ClientConfig {
830
+ User : "testuser" ,
831
+ Auth : []AuthMethod {
832
+ GSSAPIWithMICAuthMethod (
833
+ & FakeClient {
834
+ exchanges : []* exchange {
835
+ {
836
+ outToken : "client-valid-token-1" ,
837
+ },
838
+ {
839
+ expectedToken : "server-valid-token-1" ,
840
+ },
841
+ },
842
+ mic : []byte ("invalid-mic" ),
843
+ maxRound : 2 ,
844
+ }, "testtarget" ,
845
+ ),
846
+ },
847
+ HostKeyCallback : InsecureIgnoreHostKey (),
848
+ },
849
+ gssConfig : & GSSAPIWithMICConfig {
850
+ AllowLogin : func (conn ConnMetadata , srcName string ) (* Permissions , error ) {
851
+ if srcName != conn .User () {
852
+ return nil , fmt .Errorf ("srcName is %s, conn user is %s" , srcName , conn .User ())
853
+ }
854
+ return nil , nil
855
+ },
856
+ Server : & FakeServer {
857
+ exchanges : []* exchange {
858
+ {
859
+ outToken : "server-valid-token-1" ,
860
+ expectedToken : "client-valid-token-1" ,
861
+ },
862
+ },
863
+ maxRound : 1 ,
864
+ expectedMIC : []byte ("valid-mic" ),
865
+ srcName : "testuser@DOMAIN" ,
866
+ },
867
+ },
868
+ serverWantErr : "got MICToken \" invalid-mic\" , want \" valid-mic\" " ,
869
+ clientWantErr : "ssh: handshake failed: ssh: unable to authenticate" ,
870
+ },
871
+ }
872
+
873
+ for i , c := range testcases {
874
+ clientErr , serverErrs := tryAuthBothSides (t , c .config , c .gssConfig )
875
+ if (c .clientWantErr == "" ) != (clientErr == nil ) {
876
+ t .Fatalf ("client got %v, want %s, case %d" , clientErr , c .clientWantErr , i )
877
+ }
878
+ if (c .serverWantErr == "" ) != (len (serverErrs ) == 2 && serverErrs [1 ] == nil || len (serverErrs ) == 1 ) {
879
+ t .Fatalf ("server got err %v, want %s" , serverErrs , c .serverWantErr )
880
+ }
881
+ if c .clientWantErr != "" {
882
+ if clientErr != nil && ! strings .Contains (clientErr .Error (), c .clientWantErr ) {
883
+ t .Fatalf ("client got %v, want %s, case %d" , clientErr , c .clientWantErr , i )
884
+ }
885
+ }
886
+ found := false
887
+ var errStrings []string
888
+ if c .serverWantErr != "" {
889
+ for _ , err := range serverErrs {
890
+ found = found || (err != nil && strings .Contains (err .Error (), c .serverWantErr ))
891
+ errStrings = append (errStrings , err .Error ())
892
+ }
893
+ if ! found {
894
+ t .Errorf ("server got error %q, want substring %q, case %d" , errStrings , c .serverWantErr , i )
895
+ }
896
+ }
897
+ }
898
+ }
0 commit comments