1 /*
2  * Helper functions for testing WebAuth code.
3  *
4  * Additional functions that are helpful for testing WebAuth code and have
5  * knowledge of WebAuth functions and data structures.
6  *
7  * Written by Russ Allbery <eagle@eyrie.org>
8  * Copyright 2013, 2014
9  *     The Board of Trustees of the Leland Stanford Junior University
10  *
11  * See LICENSE for licensing terms.
12  */
13 
14 #ifndef TAP_WEBAUTH_H
15 #define TAP_WEBAUTH_H 1
16 
17 #include <config.h>
18 #include <tests/tap/macros.h>
19 
20 #include <webauth/tokens.h>     /* struct webauth_token_* */
21 #include <webauth/webkdc.h>     /* struct webauth_login */
22 
23 struct kerberos_config;
24 struct webauth_context;
25 struct webauth_keyring;
26 
27 /* Empty tokens, used in building test data. */
28 #define EMPTY_TOKEN_ID       { NULL, NULL, NULL, NULL, 0, NULL, NULL, 0, 0, 0 }
29 #define EMPTY_TOKEN_LOGIN    { NULL, NULL, NULL, NULL, NULL, 0 }
30 #define EMPTY_TOKEN_PROXY    { NULL, NULL, NULL, NULL, NULL, 0, 0, 0 }
31 #define EMPTY_TOKEN_WKFACTOR { NULL, NULL, 0, 0 }
32 #define EMPTY_TOKEN_WKPROXY  { NULL, NULL, NULL, NULL, 0, NULL, 0, 0, 0, NULL }
33 
34 /* Empty webauth_login struct, used in building test data. */
35 #define EMPTY_LOGIN { NULL, NULL, 0 }
36 
37 /* Helper macro for a successful login with no message in WebKDC login data. */
38 #define LOGIN_SUCCESS 0, NULL
39 
40 /* Helper macro for no factor information in WebKDC login data. */
41 #define NO_FACTOR_DATA NULL, NULL
42 
43 /* Helper macro for no authorization identities in WebKDC login data. */
44 #define NO_AUTHZ_IDS { NULL, NULL, NULL }
45 
46 /* Helper macros for empty token sets in WebKDC login data. */
47 #define NO_TOKENS_LOGIN \
48     { EMPTY_TOKEN_LOGIN, EMPTY_TOKEN_LOGIN, EMPTY_TOKEN_LOGIN }
49 #define NO_TOKENS_WKFACTOR \
50     { EMPTY_TOKEN_WKFACTOR, EMPTY_TOKEN_WKFACTOR, EMPTY_TOKEN_WKFACTOR }
51 #define NO_TOKENS_WKPROXY \
52     { EMPTY_TOKEN_WKPROXY, EMPTY_TOKEN_WKPROXY, EMPTY_TOKEN_WKPROXY }
53 
54 /* Helper macro for an empty login history in WebKDC login data. */
55 #define NO_LOGINS { EMPTY_LOGIN, EMPTY_LOGIN, EMPTY_LOGIN }
56 
57 /*
58  * All of the following structs for test token data are paralle to the regular
59  * webauth_token_* definitions except that they may omit some data that must
60  * be constructed at runtime and have special handling for some fields.
61  *
62  * All identity strings plus the login password field support the following
63  * special tokens, which are replaced with information from the Kerberos
64  * configuration:
65  *
66  *     <principal>              Keytab principal
67  *     <krb5-principal>         Keytab principal prefixed with "krb5:"
68  *     <webkdc-principal>       Keytab principal prefixed with "WEBKDC:krb5:"
69  *     <userprinc>              User principal
70  *     <username>               User principal without the realm
71  *     <password>               User password
72  *
73  * For creation and expiration if the value is < 10000 and > 0, it is taken as
74  * a *negative* offset from now for creation and a *positive* offset from now
75  * for expiration.  If creation is 0, check that the creation is somewhere
76  * around the current time.  If expiration is 0, check to ensure that it's in
77  * the future but otherwise don't be picky.
78  */
79 
80 /*
81  * Data for an id token.  Authentication data may be generated or checked on
82  * the fly if the auth type is krb5.
83  */
84 struct wat_token_id {
85     const char *subject;
86     const char *authz_subject;
87     const char *auth;
88     const void *auth_data;
89     size_t auth_data_len;
90     const char *initial_factors;
91     const char *session_factors;
92     unsigned long loa;
93     time_t creation;
94     time_t expiration;
95 };
96 
97 /* Data for a login token. */
98 struct wat_token_login {
99     const char *username;
100     const char *password;
101     const char *otp;
102     const char *otp_type;
103     const char *device_id;
104     time_t creation;
105 };
106 
107 /*
108  * Data for proxy token.  The webkdc_proxy field of a regular proxy token
109  * struct is handled specially.
110  */
111 struct wat_token_proxy {
112     const char *subject;
113     const char *authz_subject;
114     const char *type;
115     const char *initial_factors;
116     const char *session_factors;
117     unsigned long loa;
118     time_t creation;
119     time_t expiration;
120 };
121 
122 /*
123  * Data for a webkdc-proxy token.  Proxy data may be generated or checked on
124  * the fly if the proxy_type is krb5.
125  */
126 struct wat_token_webkdc_proxy {
127     const char *subject;
128     const char *proxy_type;
129     const char *proxy_subject;
130     const void *data;
131     size_t data_len;
132     const char *initial_factors;
133     unsigned long loa;
134     time_t creation;
135     time_t expiration;
136 
137     /* Not included in the wire representation. */
138     const char *session_factors;
139 };
140 
141 /*
142  * Data for a test service token.  Omit the session key, which we generate on
143  * the fly while constructing the test.
144  */
145 struct wat_token_webkdc_service {
146     const char *subject;
147     time_t creation;
148     time_t expiration;
149 };
150 
151 /*
152  * Test data for a WebKDC login request (<requestTokensRequest>).  This is in
153  * a different form than the internal struct so that it can be statically
154  * initialized when building test cases and so that it doesn't contain
155  * encrypted tokens that will vary with each run.
156  */
157 struct wat_login_request {
158     struct wat_token_webkdc_service service;
159 
160     /* Authentication tokens. */
161     struct wat_token_login logins[3];
162     struct wat_token_webkdc_proxy wkproxies[3];
163     struct webauth_token_webkdc_factor wkfactors[3];
164 
165     /* Requested authorization subject. */
166     const char *authz_subject;
167 
168     /* Authentication request from the WAS. */
169     struct webauth_token_request request;
170 };
171 
172 /*
173  * Expected data for a WebKDC login response (<requestTokensResponse>).  This
174  * includes only the data that can't be trivially derived from the request or
175  * from other parts of the response, and is structured differently from the
176  * normal internal data structure so that it can be statically initialized and
177  * doesn't contain encrypted tokens that will vary with each run.
178  */
179 struct wat_login_response {
180     const char *user_message;
181     const char *login_state;
182 
183     /* Represented as strings of comma-separated factors. */
184     const char *factors_wanted;
185     const char *factors_configured;
186 
187     /* Single sign-on tokens and user identity. */
188     struct wat_token_webkdc_proxy proxies[3];
189     struct webauth_token_webkdc_factor factor_token;
190 
191     /* Only one of result_id or result_proxy will be set. */
192     struct wat_token_id result_id;
193     struct wat_token_proxy result_proxy;
194 
195     /* User information service information from logins. */
196     struct webauth_login logins[3];
197     time_t password_expires;
198 
199     /* Permitted authorization identities. */
200     const char *permitted_authz[3];
201 };
202 
203 /* Data for a single WebKDC login test case. */
204 struct wat_login_test {
205     const char *name;
206     int status;
207     const char *error;
208     struct wat_login_request request;
209     struct wat_login_response response;
210 };
211 
212 BEGIN_DECLS
213 
214 /* Compare two tokens of various types. */
215 void is_token_error(const struct webauth_token_error *wanted,
216                     const struct webauth_token_error *seen,
217                     const char *format, ...)
218     __attribute__((__format__(printf, 3, 4)));
219 void is_token_id(const struct webauth_token_id *wanted,
220                  const struct webauth_token_id *seen,
221                  const char *format, ...)
222     __attribute__((__format__(printf, 3, 4)));
223 void is_token_proxy(const struct webauth_token_proxy *wanted,
224                     const struct webauth_token_proxy *seen,
225                     const char *format, ...)
226     __attribute__((__format__(printf, 3, 4)));
227 void is_token_webkdc_factor(const struct webauth_token_webkdc_factor *wanted,
228                             const struct webauth_token_webkdc_factor *seen,
229                             const char *format, ...)
230     __attribute__((__format__(printf, 3, 4)));
231 void is_token_webkdc_proxy(const struct webauth_token_webkdc_proxy *wanted,
232                            const struct webauth_token_webkdc_proxy *seen,
233                            const char *format, ...)
234     __attribute__((__format__(printf, 3, 4)));
235 
236 /*
237  * Run a test of the WebKDC login handling.  Takes the WebAuth context in
238  * which to run the tests, the test case description, and the keyring to use
239  * for the WebKDC.
240  */
241 void run_login_test(struct webauth_context *, const struct wat_login_test *,
242                     const struct webauth_keyring *,
243                     const struct kerberos_config *)
244     __attribute__((__nonnull__(1, 2, 3)));
245 
246 END_DECLS
247 
248 #endif /* !TAP_WEBAUTH_H */
249