xref: /freebsd/crypto/heimdal/appl/gssmask/gssmaestro.c (revision 6a068746777241722b2b32c5d0bc443a2a64d80b)
1c19800e8SDoug Rabson /*
2*ae771770SStanislav Sedov  * Copyright (c) 2006 Kungliga Tekniska Högskolan
3c19800e8SDoug Rabson  * (Royal Institute of Technology, Stockholm, Sweden).
4c19800e8SDoug Rabson  * All rights reserved.
5c19800e8SDoug Rabson  *
6c19800e8SDoug Rabson  * Redistribution and use in source and binary forms, with or without
7c19800e8SDoug Rabson  * modification, are permitted provided that the following conditions
8c19800e8SDoug Rabson  * are met:
9c19800e8SDoug Rabson  *
10c19800e8SDoug Rabson  * 1. Redistributions of source code must retain the above copyright
11c19800e8SDoug Rabson  *    notice, this list of conditions and the following disclaimer.
12c19800e8SDoug Rabson  *
13c19800e8SDoug Rabson  * 2. Redistributions in binary form must reproduce the above copyright
14c19800e8SDoug Rabson  *    notice, this list of conditions and the following disclaimer in the
15c19800e8SDoug Rabson  *    documentation and/or other materials provided with the distribution.
16c19800e8SDoug Rabson  *
17c19800e8SDoug Rabson  * 3. Neither the name of KTH nor the names of its contributors may be
18c19800e8SDoug Rabson  *    used to endorse or promote products derived from this software without
19c19800e8SDoug Rabson  *    specific prior written permission.
20c19800e8SDoug Rabson  *
21c19800e8SDoug Rabson  * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
22c19800e8SDoug Rabson  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23c19800e8SDoug Rabson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24c19800e8SDoug Rabson  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
25c19800e8SDoug Rabson  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26c19800e8SDoug Rabson  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27c19800e8SDoug Rabson  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28c19800e8SDoug Rabson  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29c19800e8SDoug Rabson  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30c19800e8SDoug Rabson  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31c19800e8SDoug Rabson  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32c19800e8SDoug Rabson  */
33c19800e8SDoug Rabson 
34c19800e8SDoug Rabson #include <common.h>
35*ae771770SStanislav Sedov RCSID("$Id$");
36c19800e8SDoug Rabson 
37c19800e8SDoug Rabson static FILE *logfile;
38c19800e8SDoug Rabson 
39c19800e8SDoug Rabson /*
40c19800e8SDoug Rabson  *
41c19800e8SDoug Rabson  */
42c19800e8SDoug Rabson 
43c19800e8SDoug Rabson struct client {
44c19800e8SDoug Rabson     char *name;
45c19800e8SDoug Rabson     struct sockaddr *sa;
46c19800e8SDoug Rabson     socklen_t salen;
47c19800e8SDoug Rabson     krb5_storage *sock;
48c19800e8SDoug Rabson     int32_t capabilities;
49c19800e8SDoug Rabson     char *target_name;
50c19800e8SDoug Rabson     char *moniker;
51c19800e8SDoug Rabson     krb5_storage *logsock;
52c19800e8SDoug Rabson     int have_log;
53c19800e8SDoug Rabson #ifdef ENABLE_PTHREAD_SUPPORT
54c19800e8SDoug Rabson     pthread_t thr;
55c19800e8SDoug Rabson #else
56c19800e8SDoug Rabson     pid_t child;
57c19800e8SDoug Rabson #endif
58c19800e8SDoug Rabson };
59c19800e8SDoug Rabson 
60c19800e8SDoug Rabson static struct client **clients;
61c19800e8SDoug Rabson static int num_clients;
62c19800e8SDoug Rabson 
63c19800e8SDoug Rabson static int
init_sec_context(struct client * client,int32_t * hContext,int32_t * hCred,int32_t flags,const char * targetname,const krb5_data * itoken,krb5_data * otoken)64c19800e8SDoug Rabson init_sec_context(struct client *client,
65c19800e8SDoug Rabson 		 int32_t *hContext, int32_t *hCred,
66c19800e8SDoug Rabson 		 int32_t flags,
67c19800e8SDoug Rabson 		 const char *targetname,
68c19800e8SDoug Rabson 		 const krb5_data *itoken, krb5_data *otoken)
69c19800e8SDoug Rabson {
70c19800e8SDoug Rabson     int32_t val;
71c19800e8SDoug Rabson     krb5_data_zero(otoken);
72c19800e8SDoug Rabson     put32(client, eInitContext);
73c19800e8SDoug Rabson     put32(client, *hContext);
74c19800e8SDoug Rabson     put32(client, *hCred);
75c19800e8SDoug Rabson     put32(client, flags);
76c19800e8SDoug Rabson     putstring(client, targetname);
77c19800e8SDoug Rabson     putdata(client, *itoken);
78c19800e8SDoug Rabson     ret32(client, *hContext);
79c19800e8SDoug Rabson     ret32(client, val);
80c19800e8SDoug Rabson     retdata(client, *otoken);
81c19800e8SDoug Rabson     return val;
82c19800e8SDoug Rabson }
83c19800e8SDoug Rabson 
84c19800e8SDoug Rabson static int
accept_sec_context(struct client * client,int32_t * hContext,int32_t flags,const krb5_data * itoken,krb5_data * otoken,int32_t * hDelegCred)85c19800e8SDoug Rabson accept_sec_context(struct client *client,
86c19800e8SDoug Rabson 		   int32_t *hContext,
87c19800e8SDoug Rabson 		   int32_t flags,
88c19800e8SDoug Rabson 		   const krb5_data *itoken,
89c19800e8SDoug Rabson 		   krb5_data *otoken,
90c19800e8SDoug Rabson 		   int32_t *hDelegCred)
91c19800e8SDoug Rabson {
92c19800e8SDoug Rabson     int32_t val;
93c19800e8SDoug Rabson     krb5_data_zero(otoken);
94c19800e8SDoug Rabson     put32(client, eAcceptContext);
95c19800e8SDoug Rabson     put32(client, *hContext);
96c19800e8SDoug Rabson     put32(client, flags);
97c19800e8SDoug Rabson     putdata(client, *itoken);
98c19800e8SDoug Rabson     ret32(client, *hContext);
99c19800e8SDoug Rabson     ret32(client, val);
100c19800e8SDoug Rabson     retdata(client, *otoken);
101c19800e8SDoug Rabson     ret32(client, *hDelegCred);
102c19800e8SDoug Rabson     return val;
103c19800e8SDoug Rabson }
104c19800e8SDoug Rabson 
105c19800e8SDoug Rabson static int
acquire_cred(struct client * client,const char * username,const char * password,int32_t flags,int32_t * hCred)106c19800e8SDoug Rabson acquire_cred(struct client *client,
107c19800e8SDoug Rabson 	     const char *username,
108c19800e8SDoug Rabson 	     const char *password,
109c19800e8SDoug Rabson 	     int32_t flags,
110c19800e8SDoug Rabson 	     int32_t *hCred)
111c19800e8SDoug Rabson {
112c19800e8SDoug Rabson     int32_t val;
113c19800e8SDoug Rabson     put32(client, eAcquireCreds);
114c19800e8SDoug Rabson     putstring(client, username);
115c19800e8SDoug Rabson     putstring(client, password);
116c19800e8SDoug Rabson     put32(client, flags);
117c19800e8SDoug Rabson     ret32(client, val);
118c19800e8SDoug Rabson     ret32(client, *hCred);
119c19800e8SDoug Rabson     return val;
120c19800e8SDoug Rabson }
121c19800e8SDoug Rabson 
122c19800e8SDoug Rabson static int
toast_resource(struct client * client,int32_t hCred)123c19800e8SDoug Rabson toast_resource(struct client *client,
124c19800e8SDoug Rabson 	       int32_t hCred)
125c19800e8SDoug Rabson {
126c19800e8SDoug Rabson     int32_t val;
127c19800e8SDoug Rabson     put32(client, eToastResource);
128c19800e8SDoug Rabson     put32(client, hCred);
129c19800e8SDoug Rabson     ret32(client, val);
130c19800e8SDoug Rabson     return val;
131c19800e8SDoug Rabson }
132c19800e8SDoug Rabson 
133c19800e8SDoug Rabson static int
goodbye(struct client * client)134c19800e8SDoug Rabson goodbye(struct client *client)
135c19800e8SDoug Rabson {
136c19800e8SDoug Rabson     put32(client, eGoodBye);
137c19800e8SDoug Rabson     return GSMERR_OK;
138c19800e8SDoug Rabson }
139c19800e8SDoug Rabson 
140c19800e8SDoug Rabson static int
get_targetname(struct client * client,char ** target)141c19800e8SDoug Rabson get_targetname(struct client *client,
142c19800e8SDoug Rabson 	       char **target)
143c19800e8SDoug Rabson {
144c19800e8SDoug Rabson     put32(client, eGetTargetName);
145c19800e8SDoug Rabson     retstring(client, *target);
146c19800e8SDoug Rabson     return GSMERR_OK;
147c19800e8SDoug Rabson }
148c19800e8SDoug Rabson 
149c19800e8SDoug Rabson static int32_t
encrypt_token(struct client * client,int32_t hContext,int32_t flags,krb5_data * in,krb5_data * out)150c19800e8SDoug Rabson encrypt_token(struct client *client, int32_t hContext, int32_t flags,
151c19800e8SDoug Rabson 	   krb5_data *in, krb5_data *out)
152c19800e8SDoug Rabson {
153c19800e8SDoug Rabson     int32_t val;
154c19800e8SDoug Rabson     put32(client, eEncrypt);
155c19800e8SDoug Rabson     put32(client, hContext);
156c19800e8SDoug Rabson     put32(client, flags);
157c19800e8SDoug Rabson     put32(client, 0);
158c19800e8SDoug Rabson     putdata(client, *in);
159c19800e8SDoug Rabson     ret32(client, val);
160c19800e8SDoug Rabson     retdata(client, *out);
161c19800e8SDoug Rabson     return val;
162c19800e8SDoug Rabson }
163c19800e8SDoug Rabson 
164c19800e8SDoug Rabson static int32_t
decrypt_token(struct client * client,int32_t hContext,int flags,krb5_data * in,krb5_data * out)165c19800e8SDoug Rabson decrypt_token(struct client *client, int32_t hContext, int flags,
166c19800e8SDoug Rabson 	     krb5_data *in, krb5_data *out)
167c19800e8SDoug Rabson {
168c19800e8SDoug Rabson     int32_t val;
169c19800e8SDoug Rabson     put32(client, eDecrypt);
170c19800e8SDoug Rabson     put32(client, hContext);
171c19800e8SDoug Rabson     put32(client, flags);
172c19800e8SDoug Rabson     put32(client, 0);
173c19800e8SDoug Rabson     putdata(client, *in);
174c19800e8SDoug Rabson     ret32(client, val);
175c19800e8SDoug Rabson     retdata(client, *out);
176c19800e8SDoug Rabson     return val;
177c19800e8SDoug Rabson }
178c19800e8SDoug Rabson 
179c19800e8SDoug Rabson static int32_t
wrap_token_ext(struct client * client,int32_t hContext,int32_t flags,int32_t bflags,krb5_data * header,krb5_data * in,krb5_data * trailer,krb5_data * out)180*ae771770SStanislav Sedov wrap_token_ext(struct client *client, int32_t hContext, int32_t flags,
181*ae771770SStanislav Sedov 	       int32_t bflags, krb5_data *header, krb5_data *in, krb5_data *trailer,
182*ae771770SStanislav Sedov 	       krb5_data *out)
183*ae771770SStanislav Sedov {
184*ae771770SStanislav Sedov     int32_t val;
185*ae771770SStanislav Sedov     put32(client, eWrapExt);
186*ae771770SStanislav Sedov     put32(client, hContext);
187*ae771770SStanislav Sedov     put32(client, flags);
188*ae771770SStanislav Sedov     put32(client, bflags);
189*ae771770SStanislav Sedov     putdata(client, *header);
190*ae771770SStanislav Sedov     putdata(client, *in);
191*ae771770SStanislav Sedov     putdata(client, *trailer);
192*ae771770SStanislav Sedov     ret32(client, val);
193*ae771770SStanislav Sedov     retdata(client, *out);
194*ae771770SStanislav Sedov     return val;
195*ae771770SStanislav Sedov }
196*ae771770SStanislav Sedov 
197*ae771770SStanislav Sedov static int32_t
unwrap_token_ext(struct client * client,int32_t hContext,int32_t flags,int32_t bflags,krb5_data * header,krb5_data * in,krb5_data * trailer,krb5_data * out)198*ae771770SStanislav Sedov unwrap_token_ext(struct client *client, int32_t hContext, int32_t flags,
199*ae771770SStanislav Sedov 	       int32_t bflags, krb5_data *header, krb5_data *in, krb5_data *trailer,
200*ae771770SStanislav Sedov 	       krb5_data *out)
201*ae771770SStanislav Sedov {
202*ae771770SStanislav Sedov     int32_t val;
203*ae771770SStanislav Sedov     put32(client, eUnwrapExt);
204*ae771770SStanislav Sedov     put32(client, hContext);
205*ae771770SStanislav Sedov     put32(client, flags);
206*ae771770SStanislav Sedov     put32(client, bflags);
207*ae771770SStanislav Sedov     putdata(client, *header);
208*ae771770SStanislav Sedov     putdata(client, *in);
209*ae771770SStanislav Sedov     putdata(client, *trailer);
210*ae771770SStanislav Sedov     ret32(client, val);
211*ae771770SStanislav Sedov     retdata(client, *out);
212*ae771770SStanislav Sedov     return val;
213*ae771770SStanislav Sedov }
214*ae771770SStanislav Sedov 
215*ae771770SStanislav Sedov static int32_t
get_mic(struct client * client,int32_t hContext,krb5_data * in,krb5_data * mic)216c19800e8SDoug Rabson get_mic(struct client *client, int32_t hContext,
217c19800e8SDoug Rabson 	krb5_data *in, krb5_data *mic)
218c19800e8SDoug Rabson {
219c19800e8SDoug Rabson     int32_t val;
220c19800e8SDoug Rabson     put32(client, eSign);
221c19800e8SDoug Rabson     put32(client, hContext);
222c19800e8SDoug Rabson     put32(client, 0);
223c19800e8SDoug Rabson     put32(client, 0);
224c19800e8SDoug Rabson     putdata(client, *in);
225c19800e8SDoug Rabson     ret32(client, val);
226c19800e8SDoug Rabson     retdata(client, *mic);
227c19800e8SDoug Rabson     return val;
228c19800e8SDoug Rabson }
229c19800e8SDoug Rabson 
230c19800e8SDoug Rabson static int32_t
verify_mic(struct client * client,int32_t hContext,krb5_data * in,krb5_data * mic)231c19800e8SDoug Rabson verify_mic(struct client *client, int32_t hContext,
232c19800e8SDoug Rabson 	   krb5_data *in, krb5_data *mic)
233c19800e8SDoug Rabson {
234c19800e8SDoug Rabson     int32_t val;
235c19800e8SDoug Rabson     put32(client, eVerify);
236c19800e8SDoug Rabson     put32(client, hContext);
237c19800e8SDoug Rabson     put32(client, 0);
238c19800e8SDoug Rabson     put32(client, 0);
239c19800e8SDoug Rabson     putdata(client, *in);
240c19800e8SDoug Rabson     putdata(client, *mic);
241c19800e8SDoug Rabson     ret32(client, val);
242c19800e8SDoug Rabson     return val;
243c19800e8SDoug Rabson }
244c19800e8SDoug Rabson 
245c19800e8SDoug Rabson 
246c19800e8SDoug Rabson static int32_t
get_version_capa(struct client * client,int32_t * version,int32_t * capa,char ** version_str)247c19800e8SDoug Rabson get_version_capa(struct client *client,
248c19800e8SDoug Rabson 		 int32_t *version, int32_t *capa,
249c19800e8SDoug Rabson 		 char **version_str)
250c19800e8SDoug Rabson {
251c19800e8SDoug Rabson     put32(client, eGetVersionAndCapabilities);
252c19800e8SDoug Rabson     ret32(client, *version);
253c19800e8SDoug Rabson     ret32(client, *capa);
254c19800e8SDoug Rabson     retstring(client, *version_str);
255c19800e8SDoug Rabson     return GSMERR_OK;
256c19800e8SDoug Rabson }
257c19800e8SDoug Rabson 
258c19800e8SDoug Rabson static int32_t
get_moniker(struct client * client,char ** moniker)259c19800e8SDoug Rabson get_moniker(struct client *client,
260c19800e8SDoug Rabson 	    char **moniker)
261c19800e8SDoug Rabson {
262c19800e8SDoug Rabson     put32(client, eGetMoniker);
263c19800e8SDoug Rabson     retstring(client, *moniker);
264c19800e8SDoug Rabson     return GSMERR_OK;
265c19800e8SDoug Rabson }
266c19800e8SDoug Rabson 
267c19800e8SDoug Rabson static int
wait_log(struct client * c)268c19800e8SDoug Rabson wait_log(struct client *c)
269c19800e8SDoug Rabson {
270c19800e8SDoug Rabson     int32_t port;
271c19800e8SDoug Rabson     struct sockaddr_storage sast;
272c19800e8SDoug Rabson     socklen_t salen = sizeof(sast);
273c19800e8SDoug Rabson     int fd, fd2, ret;
274c19800e8SDoug Rabson 
275c19800e8SDoug Rabson     memset(&sast, 0, sizeof(sast));
276c19800e8SDoug Rabson 
277c19800e8SDoug Rabson     assert(sizeof(sast) >= c->salen);
278c19800e8SDoug Rabson 
279c19800e8SDoug Rabson     fd = socket(c->sa->sa_family, SOCK_STREAM, 0);
280c19800e8SDoug Rabson     if (fd < 0)
281c19800e8SDoug Rabson 	err(1, "failed to build socket for %s's logging port", c->moniker);
282c19800e8SDoug Rabson 
283c19800e8SDoug Rabson     ((struct sockaddr *)&sast)->sa_family = c->sa->sa_family;
284c19800e8SDoug Rabson     ret = bind(fd, (struct sockaddr *)&sast, c->salen);
285c19800e8SDoug Rabson     if (ret < 0)
286c19800e8SDoug Rabson 	err(1, "failed to bind %s's logging port", c->moniker);
287c19800e8SDoug Rabson 
288c19800e8SDoug Rabson     if (listen(fd, SOMAXCONN) < 0)
289c19800e8SDoug Rabson 	err(1, "failed to listen %s's logging port", c->moniker);
290c19800e8SDoug Rabson 
291c19800e8SDoug Rabson     salen = sizeof(sast);
292c19800e8SDoug Rabson     ret = getsockname(fd, (struct sockaddr *)&sast, &salen);
293c19800e8SDoug Rabson     if (ret < 0)
294c19800e8SDoug Rabson 	err(1, "failed to get address of local socket for %s", c->moniker);
295c19800e8SDoug Rabson 
296c19800e8SDoug Rabson     port = socket_get_port((struct sockaddr *)&sast);
297c19800e8SDoug Rabson 
298c19800e8SDoug Rabson     put32(c, eSetLoggingSocket);
299c19800e8SDoug Rabson     put32(c, ntohs(port));
300c19800e8SDoug Rabson 
301c19800e8SDoug Rabson     salen = sizeof(sast);
302c19800e8SDoug Rabson     fd2 = accept(fd, (struct sockaddr *)&sast, &salen);
303c19800e8SDoug Rabson     if (fd2 < 0)
304c19800e8SDoug Rabson 	err(1, "failed to accept local socket for %s", c->moniker);
305c19800e8SDoug Rabson     close(fd);
306c19800e8SDoug Rabson 
307c19800e8SDoug Rabson     return fd2;
308c19800e8SDoug Rabson }
309c19800e8SDoug Rabson 
310c19800e8SDoug Rabson 
311c19800e8SDoug Rabson 
312c19800e8SDoug Rabson 
313c19800e8SDoug Rabson static int
build_context(struct client * ipeer,struct client * apeer,int32_t flags,int32_t hCred,int32_t * iContext,int32_t * aContext,int32_t * hDelegCred)314c19800e8SDoug Rabson build_context(struct client *ipeer, struct client *apeer,
315c19800e8SDoug Rabson 	      int32_t flags, int32_t hCred,
316c19800e8SDoug Rabson 	      int32_t *iContext, int32_t *aContext, int32_t *hDelegCred)
317c19800e8SDoug Rabson {
318c19800e8SDoug Rabson     int32_t val = GSMERR_ERROR, ic = 0, ac = 0, deleg = 0;
319c19800e8SDoug Rabson     krb5_data itoken, otoken;
320c19800e8SDoug Rabson     int iDone = 0, aDone = 0;
321c19800e8SDoug Rabson     int step = 0;
322c19800e8SDoug Rabson     int first_call = 0x80;
323c19800e8SDoug Rabson 
324c19800e8SDoug Rabson     if (apeer->target_name == NULL)
325c19800e8SDoug Rabson 	errx(1, "apeer %s have no target name", apeer->name);
326c19800e8SDoug Rabson 
327c19800e8SDoug Rabson     krb5_data_zero(&itoken);
328c19800e8SDoug Rabson 
329c19800e8SDoug Rabson     while (!iDone || !aDone) {
330c19800e8SDoug Rabson 
331c19800e8SDoug Rabson 	if (iDone) {
332c19800e8SDoug Rabson 	    warnx("iPeer already done, aPeer want extra rtt");
333c19800e8SDoug Rabson 	    val = GSMERR_ERROR;
334c19800e8SDoug Rabson 	    goto out;
335c19800e8SDoug Rabson 	}
336c19800e8SDoug Rabson 
337c19800e8SDoug Rabson 	val = init_sec_context(ipeer, &ic, &hCred, flags|first_call,
338c19800e8SDoug Rabson 			       apeer->target_name, &itoken, &otoken);
339c19800e8SDoug Rabson 	step++;
340c19800e8SDoug Rabson 	switch(val) {
341c19800e8SDoug Rabson 	case GSMERR_OK:
342c19800e8SDoug Rabson 	    iDone = 1;
343c19800e8SDoug Rabson 	    if (aDone)
344c19800e8SDoug Rabson 		continue;
345c19800e8SDoug Rabson 	    break;
346c19800e8SDoug Rabson 	case GSMERR_CONTINUE_NEEDED:
347c19800e8SDoug Rabson 	    break;
348c19800e8SDoug Rabson 	default:
349c19800e8SDoug Rabson 	    warnx("iPeer %s failed with %d (step %d)",
350c19800e8SDoug Rabson 		  ipeer->name, (int)val, step);
351c19800e8SDoug Rabson 	    goto out;
352c19800e8SDoug Rabson 	}
353c19800e8SDoug Rabson 
354c19800e8SDoug Rabson 	if (aDone) {
355c19800e8SDoug Rabson 	    warnx("aPeer already done, iPeer want extra rtt");
356c19800e8SDoug Rabson 	    val = GSMERR_ERROR;
357c19800e8SDoug Rabson 	    goto out;
358c19800e8SDoug Rabson 	}
359c19800e8SDoug Rabson 
360c19800e8SDoug Rabson 	val = accept_sec_context(apeer, &ac, flags|first_call,
361c19800e8SDoug Rabson 				 &otoken, &itoken, &deleg);
362c19800e8SDoug Rabson 	step++;
363c19800e8SDoug Rabson 	switch(val) {
364c19800e8SDoug Rabson 	case GSMERR_OK:
365c19800e8SDoug Rabson 	    aDone = 1;
366c19800e8SDoug Rabson 	    if (iDone)
367c19800e8SDoug Rabson 		continue;
368c19800e8SDoug Rabson 	    break;
369c19800e8SDoug Rabson 	case GSMERR_CONTINUE_NEEDED:
370c19800e8SDoug Rabson 	    break;
371c19800e8SDoug Rabson 	default:
372c19800e8SDoug Rabson 	    warnx("aPeer %s failed with %d (step %d)",
373c19800e8SDoug Rabson 		 apeer->name, (int)val, step);
374c19800e8SDoug Rabson 	    val = GSMERR_ERROR;
375c19800e8SDoug Rabson 	    goto out;
376c19800e8SDoug Rabson 	}
377c19800e8SDoug Rabson 	first_call = 0;
378c19800e8SDoug Rabson 	val = GSMERR_OK;
379c19800e8SDoug Rabson     }
380c19800e8SDoug Rabson 
381c19800e8SDoug Rabson     if (iContext == NULL || val != GSMERR_OK) {
382c19800e8SDoug Rabson 	if (ic)
383c19800e8SDoug Rabson 	    toast_resource(ipeer, ic);
384c19800e8SDoug Rabson 	if (iContext)
385c19800e8SDoug Rabson 	    *iContext = 0;
386c19800e8SDoug Rabson     } else
387c19800e8SDoug Rabson 	*iContext = ic;
388c19800e8SDoug Rabson 
389c19800e8SDoug Rabson     if (aContext == NULL || val != GSMERR_OK) {
390c19800e8SDoug Rabson 	if (ac)
391c19800e8SDoug Rabson 	    toast_resource(apeer, ac);
392c19800e8SDoug Rabson 	if (aContext)
393c19800e8SDoug Rabson 	    *aContext = 0;
394c19800e8SDoug Rabson     } else
395c19800e8SDoug Rabson 	*aContext = ac;
396c19800e8SDoug Rabson 
397c19800e8SDoug Rabson     if (hDelegCred == NULL || val != GSMERR_OK) {
398c19800e8SDoug Rabson 	if (deleg)
399c19800e8SDoug Rabson 	    toast_resource(apeer, deleg);
400c19800e8SDoug Rabson 	if (hDelegCred)
401c19800e8SDoug Rabson 	    *hDelegCred = 0;
402c19800e8SDoug Rabson     } else
403c19800e8SDoug Rabson 	*hDelegCred = deleg;
404c19800e8SDoug Rabson 
405c19800e8SDoug Rabson out:
406c19800e8SDoug Rabson     return val;
407c19800e8SDoug Rabson }
408c19800e8SDoug Rabson 
409c19800e8SDoug Rabson static void
test_mic(struct client * c1,int32_t hc1,struct client * c2,int32_t hc2)410c19800e8SDoug Rabson test_mic(struct client *c1, int32_t hc1, struct client *c2, int32_t hc2)
411c19800e8SDoug Rabson {
412c19800e8SDoug Rabson     krb5_data msg, mic;
413c19800e8SDoug Rabson     int32_t val;
414c19800e8SDoug Rabson 
415c19800e8SDoug Rabson     msg.data = "foo";
416c19800e8SDoug Rabson     msg.length = 3;
417c19800e8SDoug Rabson 
418c19800e8SDoug Rabson     krb5_data_zero(&mic);
419c19800e8SDoug Rabson 
420c19800e8SDoug Rabson     val = get_mic(c1, hc1, &msg, &mic);
421c19800e8SDoug Rabson     if (val)
422c19800e8SDoug Rabson 	errx(1, "get_mic failed to host: %s", c1->moniker);
423c19800e8SDoug Rabson     val = verify_mic(c2, hc2, &msg, &mic);
424c19800e8SDoug Rabson     if (val)
425c19800e8SDoug Rabson 	errx(1, "verify_mic failed to host: %s", c2->moniker);
426c19800e8SDoug Rabson 
427c19800e8SDoug Rabson     krb5_data_free(&mic);
428c19800e8SDoug Rabson }
429c19800e8SDoug Rabson 
430c19800e8SDoug Rabson static int32_t
test_wrap(struct client * c1,int32_t hc1,struct client * c2,int32_t hc2,int conf)431c19800e8SDoug Rabson test_wrap(struct client *c1, int32_t hc1, struct client *c2, int32_t hc2,
432c19800e8SDoug Rabson 	  int conf)
433c19800e8SDoug Rabson {
434c19800e8SDoug Rabson     krb5_data msg, wrapped, out;
435c19800e8SDoug Rabson     int32_t val;
436c19800e8SDoug Rabson 
437c19800e8SDoug Rabson     msg.data = "foo";
438c19800e8SDoug Rabson     msg.length = 3;
439c19800e8SDoug Rabson 
440c19800e8SDoug Rabson     krb5_data_zero(&wrapped);
441c19800e8SDoug Rabson     krb5_data_zero(&out);
442c19800e8SDoug Rabson 
443c19800e8SDoug Rabson     val = encrypt_token(c1, hc1, conf, &msg, &wrapped);
444c19800e8SDoug Rabson     if (val) {
445c19800e8SDoug Rabson 	warnx("encrypt_token failed to host: %s", c1->moniker);
446c19800e8SDoug Rabson 	return val;
447c19800e8SDoug Rabson     }
448c19800e8SDoug Rabson     val = decrypt_token(c2, hc2, conf, &wrapped, &out);
449c19800e8SDoug Rabson     if (val) {
450c19800e8SDoug Rabson 	krb5_data_free(&wrapped);
451c19800e8SDoug Rabson 	warnx("decrypt_token failed to host: %s", c2->moniker);
452c19800e8SDoug Rabson 	return val;
453c19800e8SDoug Rabson     }
454c19800e8SDoug Rabson 
455c19800e8SDoug Rabson     if (msg.length != out.length) {
456c19800e8SDoug Rabson 	warnx("decrypted'ed token have wrong length (%lu != %lu)",
457c19800e8SDoug Rabson 	      (unsigned long)msg.length, (unsigned long)out.length);
458c19800e8SDoug Rabson 	val = GSMERR_ERROR;
459c19800e8SDoug Rabson     } else if (memcmp(msg.data, out.data, msg.length) != 0) {
460c19800e8SDoug Rabson 	warnx("decryptd'ed token have wrong data");
461c19800e8SDoug Rabson 	val = GSMERR_ERROR;
462c19800e8SDoug Rabson     }
463c19800e8SDoug Rabson 
464c19800e8SDoug Rabson     krb5_data_free(&wrapped);
465c19800e8SDoug Rabson     krb5_data_free(&out);
466c19800e8SDoug Rabson     return val;
467c19800e8SDoug Rabson }
468c19800e8SDoug Rabson 
469c19800e8SDoug Rabson static int32_t
test_wrap_ext(struct client * c1,int32_t hc1,struct client * c2,int32_t hc2,int conf,int bflags)470*ae771770SStanislav Sedov test_wrap_ext(struct client *c1, int32_t hc1, struct client *c2, int32_t hc2,
471*ae771770SStanislav Sedov 	      int conf, int bflags)
472*ae771770SStanislav Sedov {
473*ae771770SStanislav Sedov     krb5_data header, msg, trailer, wrapped, out;
474*ae771770SStanislav Sedov     int32_t val;
475*ae771770SStanislav Sedov 
476*ae771770SStanislav Sedov     header.data = "header";
477*ae771770SStanislav Sedov     header.length = 6;
478*ae771770SStanislav Sedov 
479*ae771770SStanislav Sedov     msg.data = "0123456789abcdef"; /* padded for most enctypes */
480*ae771770SStanislav Sedov     msg.length = 32;
481*ae771770SStanislav Sedov 
482*ae771770SStanislav Sedov     trailer.data = "trailer";
483*ae771770SStanislav Sedov     trailer.length = 7;
484*ae771770SStanislav Sedov 
485*ae771770SStanislav Sedov     krb5_data_zero(&wrapped);
486*ae771770SStanislav Sedov     krb5_data_zero(&out);
487*ae771770SStanislav Sedov 
488*ae771770SStanislav Sedov     val = wrap_token_ext(c1, hc1, conf, bflags, &header, &msg, &trailer, &wrapped);
489*ae771770SStanislav Sedov     if (val) {
490*ae771770SStanislav Sedov 	warnx("encrypt_token failed to host: %s", c1->moniker);
491*ae771770SStanislav Sedov 	return val;
492*ae771770SStanislav Sedov     }
493*ae771770SStanislav Sedov     val = unwrap_token_ext(c2, hc2, conf, bflags, &header, &wrapped, &trailer, &out);
494*ae771770SStanislav Sedov     if (val) {
495*ae771770SStanislav Sedov 	krb5_data_free(&wrapped);
496*ae771770SStanislav Sedov 	warnx("decrypt_token failed to host: %s", c2->moniker);
497*ae771770SStanislav Sedov 	return val;
498*ae771770SStanislav Sedov     }
499*ae771770SStanislav Sedov 
500*ae771770SStanislav Sedov     if (msg.length != out.length) {
501*ae771770SStanislav Sedov 	warnx("decrypted'ed token have wrong length (%lu != %lu)",
502*ae771770SStanislav Sedov 	      (unsigned long)msg.length, (unsigned long)out.length);
503*ae771770SStanislav Sedov 	val = GSMERR_ERROR;
504*ae771770SStanislav Sedov     } else if (memcmp(msg.data, out.data, msg.length) != 0) {
505*ae771770SStanislav Sedov 	warnx("decryptd'ed token have wrong data");
506*ae771770SStanislav Sedov 	val = GSMERR_ERROR;
507*ae771770SStanislav Sedov     }
508*ae771770SStanislav Sedov 
509*ae771770SStanislav Sedov     krb5_data_free(&wrapped);
510*ae771770SStanislav Sedov     krb5_data_free(&out);
511*ae771770SStanislav Sedov     return val;
512*ae771770SStanislav Sedov }
513*ae771770SStanislav Sedov 
514*ae771770SStanislav Sedov 
515*ae771770SStanislav Sedov static int32_t
test_token(struct client * c1,int32_t hc1,struct client * c2,int32_t hc2,int wrap_ext)516*ae771770SStanislav Sedov test_token(struct client *c1, int32_t hc1, struct client *c2, int32_t hc2, int wrap_ext)
517c19800e8SDoug Rabson {
518c19800e8SDoug Rabson     int32_t val;
519c19800e8SDoug Rabson     int i;
520c19800e8SDoug Rabson 
521c19800e8SDoug Rabson     for (i = 0; i < 10; i++) {
522*ae771770SStanislav Sedov 	/* mic */
523c19800e8SDoug Rabson 	test_mic(c1, hc1, c2, hc2);
524c19800e8SDoug Rabson 	test_mic(c2, hc2, c1, hc1);
525*ae771770SStanislav Sedov 
526*ae771770SStanislav Sedov 	/* wrap */
527c19800e8SDoug Rabson 	val = test_wrap(c1, hc1, c2, hc2, 0);
528c19800e8SDoug Rabson 	if (val) return val;
529c19800e8SDoug Rabson 	val = test_wrap(c2, hc2, c1, hc1, 0);
530c19800e8SDoug Rabson 	if (val) return val;
531*ae771770SStanislav Sedov 
532c19800e8SDoug Rabson 	val = test_wrap(c1, hc1, c2, hc2, 1);
533c19800e8SDoug Rabson 	if (val) return val;
534c19800e8SDoug Rabson 	val = test_wrap(c2, hc2, c1, hc1, 1);
535c19800e8SDoug Rabson 	if (val) return val;
536*ae771770SStanislav Sedov 
537*ae771770SStanislav Sedov 	if (wrap_ext) {
538*ae771770SStanislav Sedov 	    /* wrap ext */
539*ae771770SStanislav Sedov 	    val = test_wrap_ext(c1, hc1, c2, hc2, 1, 0);
540*ae771770SStanislav Sedov 	    if (val) return val;
541*ae771770SStanislav Sedov 	    val = test_wrap_ext(c2, hc2, c1, hc1, 1, 0);
542*ae771770SStanislav Sedov 	    if (val) return val;
543*ae771770SStanislav Sedov 
544*ae771770SStanislav Sedov 	    val = test_wrap_ext(c1, hc1, c2, hc2, 1, 1);
545*ae771770SStanislav Sedov 	    if (val) return val;
546*ae771770SStanislav Sedov 	    val = test_wrap_ext(c2, hc2, c1, hc1, 1, 1);
547*ae771770SStanislav Sedov 	    if (val) return val;
548*ae771770SStanislav Sedov 
549*ae771770SStanislav Sedov 	    val = test_wrap_ext(c1, hc1, c2, hc2, 0, 0);
550*ae771770SStanislav Sedov 	    if (val) return val;
551*ae771770SStanislav Sedov 	    val = test_wrap_ext(c2, hc2, c1, hc1, 0, 0);
552*ae771770SStanislav Sedov 	    if (val) return val;
553*ae771770SStanislav Sedov 
554*ae771770SStanislav Sedov 	    val = test_wrap_ext(c1, hc1, c2, hc2, 0, 1);
555*ae771770SStanislav Sedov 	    if (val) return val;
556*ae771770SStanislav Sedov 	    val = test_wrap_ext(c2, hc2, c1, hc1, 0, 1);
557*ae771770SStanislav Sedov 	    if (val) return val;
558*ae771770SStanislav Sedov 	}
559c19800e8SDoug Rabson     }
560c19800e8SDoug Rabson     return GSMERR_OK;
561c19800e8SDoug Rabson }
562c19800e8SDoug Rabson 
563c19800e8SDoug Rabson static int
log_function(void * ptr)564c19800e8SDoug Rabson log_function(void *ptr)
565c19800e8SDoug Rabson {
566c19800e8SDoug Rabson     struct client *c = ptr;
567c19800e8SDoug Rabson     int32_t cmd, line;
568c19800e8SDoug Rabson     char *file, *string;
569c19800e8SDoug Rabson 
570c19800e8SDoug Rabson     while (1) {
571c19800e8SDoug Rabson         if (krb5_ret_int32(c->logsock, &cmd))
572c19800e8SDoug Rabson 	    goto out;
573c19800e8SDoug Rabson 
574c19800e8SDoug Rabson 	switch (cmd) {
575c19800e8SDoug Rabson 	case eLogSetMoniker:
576c19800e8SDoug Rabson 	    if (krb5_ret_string(c->logsock, &file))
577c19800e8SDoug Rabson 		goto out;
578c19800e8SDoug Rabson 	    free(file);
579c19800e8SDoug Rabson 	    break;
580c19800e8SDoug Rabson 	case eLogInfo:
581c19800e8SDoug Rabson 	case eLogFailure:
582c19800e8SDoug Rabson 	    if (krb5_ret_string(c->logsock, &file))
583c19800e8SDoug Rabson 		goto out;
584c19800e8SDoug Rabson 	    if (krb5_ret_int32(c->logsock, &line))
585c19800e8SDoug Rabson 		goto out;
586c19800e8SDoug Rabson 	    if (krb5_ret_string(c->logsock, &string))
587c19800e8SDoug Rabson 		goto out;
588c19800e8SDoug Rabson 	    printf("%s:%lu: %s\n",
589c19800e8SDoug Rabson 		   file, (unsigned long)line, string);
590c19800e8SDoug Rabson 	    fprintf(logfile, "%s:%lu: %s\n",
591c19800e8SDoug Rabson 		    file, (unsigned long)line, string);
592c19800e8SDoug Rabson 	    fflush(logfile);
593c19800e8SDoug Rabson 	    free(file);
594c19800e8SDoug Rabson 	    free(string);
595c19800e8SDoug Rabson 	    if (krb5_store_int32(c->logsock, 0))
596c19800e8SDoug Rabson 		goto out;
597c19800e8SDoug Rabson 	    break;
598c19800e8SDoug Rabson 	default:
599c19800e8SDoug Rabson 	    errx(1, "client send bad log command: %d", (int)cmd);
600c19800e8SDoug Rabson 	}
601c19800e8SDoug Rabson     }
602c19800e8SDoug Rabson out:
603c19800e8SDoug Rabson 
604c19800e8SDoug Rabson     return 0;
605c19800e8SDoug Rabson }
606c19800e8SDoug Rabson 
607c19800e8SDoug Rabson static void
connect_client(const char * slave)608c19800e8SDoug Rabson connect_client(const char *slave)
609c19800e8SDoug Rabson {
610c19800e8SDoug Rabson     char *name, *port;
611c19800e8SDoug Rabson     struct client *c = ecalloc(1, sizeof(*c));
612c19800e8SDoug Rabson     struct addrinfo hints, *res0, *res;
613c19800e8SDoug Rabson     int ret, fd;
614c19800e8SDoug Rabson 
615c19800e8SDoug Rabson     name = estrdup(slave);
616c19800e8SDoug Rabson     port = strchr(name, ':');
617c19800e8SDoug Rabson     if (port == NULL)
618c19800e8SDoug Rabson 	errx(1, "port missing from %s", name);
619c19800e8SDoug Rabson     *port++ = 0;
620c19800e8SDoug Rabson 
621c19800e8SDoug Rabson     c->name = estrdup(slave);
622c19800e8SDoug Rabson 
623c19800e8SDoug Rabson     memset(&hints, 0, sizeof(hints));
624c19800e8SDoug Rabson     hints.ai_family = PF_UNSPEC;
625c19800e8SDoug Rabson     hints.ai_socktype = SOCK_STREAM;
626c19800e8SDoug Rabson 
627c19800e8SDoug Rabson     ret = getaddrinfo(name, port, &hints, &res0);
628c19800e8SDoug Rabson     if (ret)
629c19800e8SDoug Rabson 	errx(1, "error resolving %s", name);
630c19800e8SDoug Rabson 
631c19800e8SDoug Rabson     for (res = res0, fd = -1; res; res = res->ai_next) {
632c19800e8SDoug Rabson 	fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
633c19800e8SDoug Rabson 	if (fd < 0)
634c19800e8SDoug Rabson 	    continue;
635c19800e8SDoug Rabson 	if (connect(fd, res->ai_addr, res->ai_addrlen) < 0) {
636c19800e8SDoug Rabson 	    close(fd);
637c19800e8SDoug Rabson 	    fd = -1;
638c19800e8SDoug Rabson 	    continue;
639c19800e8SDoug Rabson 	}
640c19800e8SDoug Rabson 	c->sa = ecalloc(1, res->ai_addrlen);
641c19800e8SDoug Rabson 	memcpy(c->sa, res->ai_addr, res->ai_addrlen);
642c19800e8SDoug Rabson 	c->salen = res->ai_addrlen;
643c19800e8SDoug Rabson 	break;  /* okay we got one */
644c19800e8SDoug Rabson     }
645c19800e8SDoug Rabson     if (fd < 0)
646c19800e8SDoug Rabson 	err(1, "connect to host: %s", name);
647c19800e8SDoug Rabson     freeaddrinfo(res);
648c19800e8SDoug Rabson 
649c19800e8SDoug Rabson     c->sock = krb5_storage_from_fd(fd);
650c19800e8SDoug Rabson     close(fd);
651c19800e8SDoug Rabson     if (c->sock == NULL)
652c19800e8SDoug Rabson 	errx(1, "krb5_storage_from_fd");
653c19800e8SDoug Rabson 
654c19800e8SDoug Rabson     {
655c19800e8SDoug Rabson 	int32_t version;
656c19800e8SDoug Rabson 	char *str = NULL;
657c19800e8SDoug Rabson 	get_version_capa(c, &version, &c->capabilities, &str);
658c19800e8SDoug Rabson 	if (str) {
659c19800e8SDoug Rabson 	    free(str);
660c19800e8SDoug Rabson 	}
661c19800e8SDoug Rabson 	if (c->capabilities & HAS_MONIKER)
662c19800e8SDoug Rabson 	    get_moniker(c, &c->moniker);
663c19800e8SDoug Rabson 	else
664c19800e8SDoug Rabson 	    c->moniker = c->name;
665c19800e8SDoug Rabson 	if (c->capabilities & ISSERVER)
666c19800e8SDoug Rabson 	    get_targetname(c, &c->target_name);
667c19800e8SDoug Rabson     }
668c19800e8SDoug Rabson 
669c19800e8SDoug Rabson     if (logfile) {
670c19800e8SDoug Rabson 	int fd;
671c19800e8SDoug Rabson 
672c19800e8SDoug Rabson 	printf("starting log socket to client %s\n", c->moniker);
673c19800e8SDoug Rabson 
674c19800e8SDoug Rabson 	fd = wait_log(c);
675c19800e8SDoug Rabson 
676c19800e8SDoug Rabson 	c->logsock = krb5_storage_from_fd(fd);
677c19800e8SDoug Rabson 	close(fd);
678c19800e8SDoug Rabson 	if (c->logsock == NULL)
679c19800e8SDoug Rabson 	    errx(1, "failed to create log krb5_storage");
680c19800e8SDoug Rabson #ifdef ENABLE_PTHREAD_SUPPORT
681c19800e8SDoug Rabson 	pthread_create(&c->thr, NULL, log_function, c);
682c19800e8SDoug Rabson #else
683c19800e8SDoug Rabson 	c->child = fork();
684c19800e8SDoug Rabson 	if (c->child == -1)
685c19800e8SDoug Rabson 	    errx(1, "failed to fork");
686c19800e8SDoug Rabson 	else if (c->child == 0) {
687c19800e8SDoug Rabson 	    log_function(c);
688c19800e8SDoug Rabson 	    fclose(logfile);
689c19800e8SDoug Rabson 	    exit(0);
690c19800e8SDoug Rabson 	}
691c19800e8SDoug Rabson #endif
692c19800e8SDoug Rabson    }
693c19800e8SDoug Rabson 
694c19800e8SDoug Rabson 
695c19800e8SDoug Rabson     clients = erealloc(clients, (num_clients + 1) * sizeof(*clients));
696c19800e8SDoug Rabson 
697c19800e8SDoug Rabson     clients[num_clients] = c;
698c19800e8SDoug Rabson     num_clients++;
699c19800e8SDoug Rabson 
700c19800e8SDoug Rabson     free(name);
701c19800e8SDoug Rabson }
702c19800e8SDoug Rabson 
703c19800e8SDoug Rabson static struct client *
get_client(const char * slave)704c19800e8SDoug Rabson get_client(const char *slave)
705c19800e8SDoug Rabson {
706c19800e8SDoug Rabson     size_t i;
707c19800e8SDoug Rabson     for (i = 0; i < num_clients; i++)
708c19800e8SDoug Rabson 	if (strcmp(slave, clients[i]->name) == 0)
709c19800e8SDoug Rabson 	    return clients[i];
710c19800e8SDoug Rabson     errx(1, "failed to find client %s", slave);
711c19800e8SDoug Rabson }
712c19800e8SDoug Rabson 
713c19800e8SDoug Rabson /*
714c19800e8SDoug Rabson  *
715c19800e8SDoug Rabson  */
716c19800e8SDoug Rabson 
717c19800e8SDoug Rabson static int version_flag;
718c19800e8SDoug Rabson static int help_flag;
719*ae771770SStanislav Sedov static int wrap_ext = 0;
720c19800e8SDoug Rabson static char *logfile_str;
721c19800e8SDoug Rabson static getarg_strings principals;
722c19800e8SDoug Rabson static getarg_strings slaves;
723c19800e8SDoug Rabson 
724c19800e8SDoug Rabson struct getargs args[] = {
725c19800e8SDoug Rabson     { "principals", 0,  arg_strings,	&principals,	"Test principal",
726c19800e8SDoug Rabson       NULL },
727c19800e8SDoug Rabson     { "slaves", 0,  arg_strings,	&slaves,	"Slaves",
728c19800e8SDoug Rabson       NULL },
729c19800e8SDoug Rabson     { "log-file", 0, arg_string,	&logfile_str,	"Logfile",
730c19800e8SDoug Rabson       NULL },
731*ae771770SStanislav Sedov     { "wrap-ext", 0,  arg_flag,		&wrap_ext,	"test wrap extended",
732*ae771770SStanislav Sedov       NULL },
733c19800e8SDoug Rabson     { "version", 0,  arg_flag,		&version_flag,	"Print version",
734c19800e8SDoug Rabson       NULL },
735c19800e8SDoug Rabson     { "help",	 0,  arg_flag,		&help_flag,	NULL,
736c19800e8SDoug Rabson       NULL }
737c19800e8SDoug Rabson };
738c19800e8SDoug Rabson 
739c19800e8SDoug Rabson static void
usage(int ret)740c19800e8SDoug Rabson usage(int ret)
741c19800e8SDoug Rabson {
742c19800e8SDoug Rabson     arg_printusage (args,
743c19800e8SDoug Rabson 		    sizeof(args) / sizeof(args[0]),
744c19800e8SDoug Rabson 		    NULL,
745c19800e8SDoug Rabson 		    "");
746c19800e8SDoug Rabson     exit (ret);
747c19800e8SDoug Rabson }
748c19800e8SDoug Rabson 
749c19800e8SDoug Rabson int
main(int argc,char ** argv)750c19800e8SDoug Rabson main(int argc, char **argv)
751c19800e8SDoug Rabson {
752c19800e8SDoug Rabson     int optidx= 0;
753c19800e8SDoug Rabson     char *user;
754c19800e8SDoug Rabson     char *password;
755c19800e8SDoug Rabson     char ***list, **p;
756c19800e8SDoug Rabson     size_t num_list, i, j, k;
757c19800e8SDoug Rabson     int failed = 0;
758c19800e8SDoug Rabson 
759c19800e8SDoug Rabson     setprogname (argv[0]);
760c19800e8SDoug Rabson 
761c19800e8SDoug Rabson     if (getarg (args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
762c19800e8SDoug Rabson 	usage (1);
763c19800e8SDoug Rabson 
764c19800e8SDoug Rabson     if (help_flag)
765c19800e8SDoug Rabson 	usage (0);
766c19800e8SDoug Rabson 
767c19800e8SDoug Rabson     if (version_flag) {
768c19800e8SDoug Rabson 	print_version (NULL);
769c19800e8SDoug Rabson 	return 0;
770c19800e8SDoug Rabson     }
771c19800e8SDoug Rabson 
772c19800e8SDoug Rabson     if (optidx != argc)
773c19800e8SDoug Rabson 	usage (1);
774c19800e8SDoug Rabson 
775c19800e8SDoug Rabson     if (principals.num_strings == 0)
776c19800e8SDoug Rabson 	errx(1, "no principals");
777c19800e8SDoug Rabson 
778c19800e8SDoug Rabson     user = estrdup(principals.strings[0]);
779c19800e8SDoug Rabson     password = strchr(user, ':');
780c19800e8SDoug Rabson     if (password == NULL)
781c19800e8SDoug Rabson 	errx(1, "password missing from %s", user);
782c19800e8SDoug Rabson     *password++ = 0;
783c19800e8SDoug Rabson 
784c19800e8SDoug Rabson     if (slaves.num_strings == 0)
785c19800e8SDoug Rabson 	errx(1, "no principals");
786c19800e8SDoug Rabson 
787c19800e8SDoug Rabson     if (logfile_str) {
788c19800e8SDoug Rabson 	printf("open logfile %s\n", logfile_str);
789c19800e8SDoug Rabson 	logfile = fopen(logfile_str, "w+");
790c19800e8SDoug Rabson 	if (logfile == NULL)
791c19800e8SDoug Rabson 	    err(1, "failed to open: %s", logfile_str);
792c19800e8SDoug Rabson     }
793c19800e8SDoug Rabson 
794c19800e8SDoug Rabson     /*
795c19800e8SDoug Rabson      *
796c19800e8SDoug Rabson      */
797c19800e8SDoug Rabson 
798c19800e8SDoug Rabson     list = permutate_all(&slaves, &num_list);
799c19800e8SDoug Rabson 
800c19800e8SDoug Rabson     /*
801c19800e8SDoug Rabson      * Set up connection to all clients
802c19800e8SDoug Rabson      */
803c19800e8SDoug Rabson 
804c19800e8SDoug Rabson     printf("Connecting to slaves\n");
805c19800e8SDoug Rabson     for (i = 0; i < slaves.num_strings; i++)
806c19800e8SDoug Rabson 	connect_client(slaves.strings[i]);
807c19800e8SDoug Rabson 
808c19800e8SDoug Rabson     /*
809c19800e8SDoug Rabson      * Test acquire credentials
810c19800e8SDoug Rabson      */
811c19800e8SDoug Rabson 
812c19800e8SDoug Rabson     printf("Test acquire credentials\n");
813c19800e8SDoug Rabson     for (i = 0; i < slaves.num_strings; i++) {
814c19800e8SDoug Rabson 	int32_t hCred, val;
815c19800e8SDoug Rabson 
816c19800e8SDoug Rabson 	val = acquire_cred(clients[i], user, password, 1, &hCred);
817c19800e8SDoug Rabson 	if (val != GSMERR_OK) {
818c19800e8SDoug Rabson 	    warnx("Failed to acquire_cred on host %s: %d",
819c19800e8SDoug Rabson 		 clients[i]->moniker, (int)val);
820c19800e8SDoug Rabson 	    failed = 1;
821c19800e8SDoug Rabson 	} else
822c19800e8SDoug Rabson 	    toast_resource(clients[i], hCred);
823c19800e8SDoug Rabson     }
824c19800e8SDoug Rabson 
825c19800e8SDoug Rabson     if (failed)
826c19800e8SDoug Rabson 	goto out;
827c19800e8SDoug Rabson 
828c19800e8SDoug Rabson     /*
829c19800e8SDoug Rabson      * First test if all slaves can build context to them-self.
830c19800e8SDoug Rabson      */
831c19800e8SDoug Rabson 
832c19800e8SDoug Rabson     printf("Self context tests\n");
833c19800e8SDoug Rabson     for (i = 0; i < num_clients; i++) {
834c19800e8SDoug Rabson 	int32_t hCred, val, delegCred;
835c19800e8SDoug Rabson 	int32_t clientC, serverC;
836c19800e8SDoug Rabson 	struct client *c = clients[i];
837c19800e8SDoug Rabson 
838c19800e8SDoug Rabson 	if (c->target_name == NULL)
839c19800e8SDoug Rabson 	    continue;
840c19800e8SDoug Rabson 
841c19800e8SDoug Rabson 	printf("%s connects to self using %s\n",
842c19800e8SDoug Rabson 	       c->moniker, c->target_name);
843c19800e8SDoug Rabson 
844c19800e8SDoug Rabson 	val = acquire_cred(c, user, password, 1, &hCred);
845c19800e8SDoug Rabson 	if (val != GSMERR_OK)
846c19800e8SDoug Rabson 	    errx(1, "failed to acquire_cred: %d", (int)val);
847c19800e8SDoug Rabson 
848c19800e8SDoug Rabson 	val = build_context(c, c,
849c19800e8SDoug Rabson 			    GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG|
850c19800e8SDoug Rabson 			    GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG|
851c19800e8SDoug Rabson 			    GSS_C_DELEG_FLAG|GSS_C_MUTUAL_FLAG,
852c19800e8SDoug Rabson 			    hCred, &clientC, &serverC, &delegCred);
853c19800e8SDoug Rabson 	if (val == GSMERR_OK) {
854*ae771770SStanislav Sedov 	    test_token(c, clientC, c, serverC, wrap_ext);
855c19800e8SDoug Rabson 	    toast_resource(c, clientC);
856c19800e8SDoug Rabson 	    toast_resource(c, serverC);
857c19800e8SDoug Rabson 	    if (delegCred)
858c19800e8SDoug Rabson 		toast_resource(c, delegCred);
859c19800e8SDoug Rabson 	} else {
860c19800e8SDoug Rabson 	    warnx("build_context failed: %d", (int)val);
861c19800e8SDoug Rabson 	}
862c19800e8SDoug Rabson 	/*
863c19800e8SDoug Rabson 	 *
864c19800e8SDoug Rabson 	 */
865c19800e8SDoug Rabson 
866c19800e8SDoug Rabson 	val = build_context(c, c,
867c19800e8SDoug Rabson 			    GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG,
868c19800e8SDoug Rabson 			    hCred, &clientC, &serverC, &delegCred);
869c19800e8SDoug Rabson 	if (val == GSMERR_OK) {
870*ae771770SStanislav Sedov 	    test_token(c, clientC, c, serverC, wrap_ext);
871c19800e8SDoug Rabson 	    toast_resource(c, clientC);
872c19800e8SDoug Rabson 	    toast_resource(c, serverC);
873c19800e8SDoug Rabson 	    if (delegCred)
874c19800e8SDoug Rabson 		toast_resource(c, delegCred);
875c19800e8SDoug Rabson 	} else {
876c19800e8SDoug Rabson 	    warnx("build_context failed: %d", (int)val);
877c19800e8SDoug Rabson 	}
878c19800e8SDoug Rabson 
879c19800e8SDoug Rabson 	toast_resource(c, hCred);
880c19800e8SDoug Rabson     }
881c19800e8SDoug Rabson     /*
882c19800e8SDoug Rabson      * Build contexts though all entries in each lists, including the
883c19800e8SDoug Rabson      * step from the last entry to the first, ie treat the list as a
884c19800e8SDoug Rabson      * circle.
885c19800e8SDoug Rabson      *
886c19800e8SDoug Rabson      * Only follow the delegated credential, but test "all"
887c19800e8SDoug Rabson      * flags. (XXX only do deleg|mutual right now.
888c19800e8SDoug Rabson      */
889c19800e8SDoug Rabson 
890c19800e8SDoug Rabson     printf("\"All\" permutation tests\n");
891c19800e8SDoug Rabson 
892c19800e8SDoug Rabson     for (i = 0; i < num_list; i++) {
893c19800e8SDoug Rabson 	int32_t hCred, val, delegCred = 0;
894c19800e8SDoug Rabson 	int32_t clientC = 0, serverC = 0;
895c19800e8SDoug Rabson 	struct client *client, *server;
896c19800e8SDoug Rabson 
897c19800e8SDoug Rabson 	p = list[i];
898c19800e8SDoug Rabson 
899c19800e8SDoug Rabson 	client = get_client(p[0]);
900c19800e8SDoug Rabson 
901c19800e8SDoug Rabson 	val = acquire_cred(client, user, password, 1, &hCred);
902c19800e8SDoug Rabson 	if (val != GSMERR_OK)
903c19800e8SDoug Rabson 	    errx(1, "failed to acquire_cred: %d", (int)val);
904c19800e8SDoug Rabson 
905c19800e8SDoug Rabson 	for (j = 1; j < num_clients + 1; j++) {
906c19800e8SDoug Rabson 	    server = get_client(p[j % num_clients]);
907c19800e8SDoug Rabson 
908c19800e8SDoug Rabson 	    if (server->target_name == NULL)
909c19800e8SDoug Rabson 		break;
910c19800e8SDoug Rabson 
911c19800e8SDoug Rabson 	    for (k = 1; k < j; k++)
912c19800e8SDoug Rabson 		printf("\t");
913c19800e8SDoug Rabson 	    printf("%s -> %s\n", client->moniker, server->moniker);
914c19800e8SDoug Rabson 
915c19800e8SDoug Rabson 	    val = build_context(client, server,
916c19800e8SDoug Rabson 				GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG|
917c19800e8SDoug Rabson 				GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG|
918c19800e8SDoug Rabson 				GSS_C_DELEG_FLAG|GSS_C_MUTUAL_FLAG,
919c19800e8SDoug Rabson 				hCred, &clientC, &serverC, &delegCred);
920c19800e8SDoug Rabson 	    if (val != GSMERR_OK) {
921c19800e8SDoug Rabson 		warnx("build_context failed: %d", (int)val);
922c19800e8SDoug Rabson 		break;
923c19800e8SDoug Rabson 	    }
924c19800e8SDoug Rabson 
925*ae771770SStanislav Sedov 	    val = test_token(client, clientC, server, serverC, wrap_ext);
926c19800e8SDoug Rabson 	    if (val)
927c19800e8SDoug Rabson 		break;
928c19800e8SDoug Rabson 
929c19800e8SDoug Rabson 	    toast_resource(client, clientC);
930c19800e8SDoug Rabson 	    toast_resource(server, serverC);
931c19800e8SDoug Rabson 	    if (!delegCred) {
932c19800e8SDoug Rabson 		warnx("no delegated cred on %s", server->moniker);
933c19800e8SDoug Rabson 		break;
934c19800e8SDoug Rabson 	    }
935c19800e8SDoug Rabson 	    toast_resource(client, hCred);
936c19800e8SDoug Rabson 	    hCred = delegCred;
937c19800e8SDoug Rabson 	    client = server;
938c19800e8SDoug Rabson 	}
939c19800e8SDoug Rabson 	if (hCred)
940c19800e8SDoug Rabson 	    toast_resource(client, hCred);
941c19800e8SDoug Rabson     }
942c19800e8SDoug Rabson 
943c19800e8SDoug Rabson     /*
944c19800e8SDoug Rabson      * Close all connections to clients
945c19800e8SDoug Rabson      */
946c19800e8SDoug Rabson 
947c19800e8SDoug Rabson out:
948c19800e8SDoug Rabson     printf("sending goodbye and waiting for log sockets\n");
949c19800e8SDoug Rabson     for (i = 0; i < num_clients; i++) {
950c19800e8SDoug Rabson 	goodbye(clients[i]);
951c19800e8SDoug Rabson 	if (clients[i]->logsock) {
952c19800e8SDoug Rabson #ifdef ENABLE_PTHREAD_SUPPORT
953c19800e8SDoug Rabson 	    pthread_join(&clients[i]->thr, NULL);
954c19800e8SDoug Rabson #else
955c19800e8SDoug Rabson 	    waitpid(clients[i]->child, NULL, 0);
956c19800e8SDoug Rabson #endif
957c19800e8SDoug Rabson 	}
958c19800e8SDoug Rabson     }
959c19800e8SDoug Rabson 
960c19800e8SDoug Rabson     printf("done\n");
961c19800e8SDoug Rabson 
962c19800e8SDoug Rabson     return 0;
963c19800e8SDoug Rabson }
964