-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
pam/gdm: Support conversations using JSON data sent to PAM via gdm bi…
…nary protocol Add an utility function to perform GDM-PAM binary conversations using the custom JSON protocol. This function does not much per se, but it allows us to do some proper testing via the dummy module transaction and so we can test how this data is passed back and forth the two sides, and stress the C <-> go structures conversions.
- Loading branch information
Showing
2 changed files
with
135 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package gdm | ||
|
||
import "C" | ||
|
||
import ( | ||
"errors" | ||
|
||
"github.com/msteinert/pam" | ||
) | ||
|
||
func sendToGdm(pamMTx pam.ModuleTransaction, data []byte) ([]byte, error) { | ||
binReq, err := NewBinaryJSONProtoRequest(data) | ||
if err != nil { | ||
return nil, err | ||
} | ||
defer binReq.Release() | ||
res, err := pamMTx.StartConv(binReq) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
binRes, ok := res.(pam.BinaryConvResponse) | ||
if !ok { | ||
return nil, errors.New("returned value is not in binary form") | ||
} | ||
defer binRes.Release() | ||
return binRes.Decode(decodeJSONProtoMessage) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
package gdm | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/msteinert/pam" | ||
"github.com/stretchr/testify/require" | ||
"github.com/ubuntu/authd/pam/pam_test" | ||
) | ||
|
||
func TestSendToGdm(t *testing.T) { | ||
t.Parallel() | ||
t.Cleanup(pam_test.MaybeDoLeakCheck) | ||
|
||
testCases := map[string]struct { | ||
value []byte | ||
|
||
wantReturn []byte | ||
wantError error | ||
}{ | ||
"JSON null data can be sent and received": { | ||
value: []byte(`null`), | ||
}, | ||
|
||
"JSON number can be sent and received": { | ||
value: []byte(`1.5`), | ||
}, | ||
|
||
"Single char is sent and received as string": { | ||
value: []byte(`"m"`), | ||
}, | ||
|
||
"JSON null is returned": { | ||
value: []byte(`"give me 🚫"`), | ||
wantReturn: []byte("null"), | ||
}, | ||
|
||
"Utf-8 data is sent and returned": { | ||
value: []byte(`"give me 🍕"`), | ||
wantReturn: []byte(`"😋"`), | ||
}, | ||
|
||
// Error cases | ||
"Error on empty data": { | ||
value: []byte{}, | ||
wantError: ErrInvalidJSON, | ||
}, | ||
|
||
"Error on nil data": { | ||
value: nil, | ||
wantError: ErrInvalidJSON, | ||
}, | ||
|
||
"Error with empty data returned": { | ||
value: []byte(`"give me 🗑‼"`), | ||
wantReturn: []byte{}, | ||
wantError: ErrInvalidJSON, | ||
}, | ||
|
||
"Error with nil data returned": { | ||
value: []byte(`"give me 🚫"`), | ||
wantReturn: []byte(nil), | ||
wantError: ErrInvalidJSON, | ||
}, | ||
} | ||
|
||
for name, tc := range testCases { | ||
tc := tc | ||
t.Run(name, func(t *testing.T) { | ||
t.Parallel() | ||
t.Cleanup(pam_test.MaybeDoLeakCheck) | ||
|
||
convFuncCalled := true | ||
mt := pam_test.NewModuleTransactionDummy(pam.BinaryPointerConversationFunc( | ||
func(ptr pam.BinaryPointer) (pam.BinaryPointer, error) { | ||
convFuncCalled = true | ||
require.NotNil(t, ptr) | ||
req, err := decodeJSONProtoMessage(ptr) | ||
require.NoError(t, err) | ||
require.Equal(t, tc.value, req) | ||
if tc.wantReturn != nil { | ||
msg, err := newJSONProtoMessage(tc.wantReturn) | ||
return pam.BinaryPointer(msg), err | ||
} | ||
msg, err := newJSONProtoMessage(req) | ||
return pam.BinaryPointer(msg), err | ||
})) | ||
|
||
data, err := sendToGdm(mt, tc.value) | ||
require.True(t, convFuncCalled) | ||
|
||
if tc.wantError != nil { | ||
require.Error(t, tc.wantError, err) | ||
return | ||
} | ||
|
||
require.NoError(t, err) | ||
|
||
if tc.wantReturn != nil { | ||
require.Equal(t, tc.wantReturn, data) | ||
return | ||
} | ||
|
||
require.Equal(t, tc.value, data) | ||
}) | ||
} | ||
} |