1c19800e8SDoug Rabson /*
2ae771770SStanislav 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"
35ae771770SStanislav Sedov RCSID("$Id$");
36c19800e8SDoug Rabson
37c19800e8SDoug Rabson /*
38c19800e8SDoug Rabson *
39c19800e8SDoug Rabson */
40c19800e8SDoug Rabson
41c19800e8SDoug Rabson enum handle_type { handle_context, handle_cred };
42c19800e8SDoug Rabson
43c19800e8SDoug Rabson struct handle {
44c19800e8SDoug Rabson int32_t idx;
45c19800e8SDoug Rabson enum handle_type type;
46c19800e8SDoug Rabson void *ptr;
47c19800e8SDoug Rabson struct handle *next;
48c19800e8SDoug Rabson };
49c19800e8SDoug Rabson
50c19800e8SDoug Rabson struct client {
51c19800e8SDoug Rabson krb5_storage *sock;
52c19800e8SDoug Rabson krb5_storage *logging;
53c19800e8SDoug Rabson char *moniker;
54c19800e8SDoug Rabson int32_t nHandle;
55c19800e8SDoug Rabson struct handle *handles;
56c19800e8SDoug Rabson struct sockaddr_storage sa;
57c19800e8SDoug Rabson socklen_t salen;
58c19800e8SDoug Rabson char servername[MAXHOSTNAMELEN];
59c19800e8SDoug Rabson };
60c19800e8SDoug Rabson
61c19800e8SDoug Rabson FILE *logfile;
62c19800e8SDoug Rabson static char *targetname;
63c19800e8SDoug Rabson krb5_context context;
64c19800e8SDoug Rabson
65c19800e8SDoug Rabson /*
66c19800e8SDoug Rabson *
67c19800e8SDoug Rabson */
68c19800e8SDoug Rabson
69c19800e8SDoug Rabson static void
logmessage(struct client * c,const char * file,unsigned int lineno,int level,const char * fmt,...)70c19800e8SDoug Rabson logmessage(struct client *c, const char *file, unsigned int lineno,
71c19800e8SDoug Rabson int level, const char *fmt, ...)
72c19800e8SDoug Rabson {
73c19800e8SDoug Rabson char *message;
74c19800e8SDoug Rabson va_list ap;
75c19800e8SDoug Rabson int32_t ackid;
76c19800e8SDoug Rabson
77c19800e8SDoug Rabson va_start(ap, fmt);
78c19800e8SDoug Rabson vasprintf(&message, fmt, ap);
79c19800e8SDoug Rabson va_end(ap);
80c19800e8SDoug Rabson
81c19800e8SDoug Rabson if (logfile)
82c19800e8SDoug Rabson fprintf(logfile, "%s:%u: %d %s\n", file, lineno, level, message);
83c19800e8SDoug Rabson
84c19800e8SDoug Rabson if (c->logging) {
85c19800e8SDoug Rabson if (krb5_store_int32(c->logging, eLogInfo) != 0)
86c19800e8SDoug Rabson errx(1, "krb5_store_int32: log level");
87c19800e8SDoug Rabson if (krb5_store_string(c->logging, file) != 0)
88c19800e8SDoug Rabson errx(1, "krb5_store_string: filename");
89c19800e8SDoug Rabson if (krb5_store_int32(c->logging, lineno) != 0)
90c19800e8SDoug Rabson errx(1, "krb5_store_string: filename");
91c19800e8SDoug Rabson if (krb5_store_string(c->logging, message) != 0)
92c19800e8SDoug Rabson errx(1, "krb5_store_string: message");
93c19800e8SDoug Rabson if (krb5_ret_int32(c->logging, &ackid) != 0)
94c19800e8SDoug Rabson errx(1, "krb5_ret_int32: ackid");
95c19800e8SDoug Rabson }
96c19800e8SDoug Rabson free(message);
97c19800e8SDoug Rabson }
98c19800e8SDoug Rabson
99c19800e8SDoug Rabson /*
100c19800e8SDoug Rabson *
101c19800e8SDoug Rabson */
102c19800e8SDoug Rabson
103c19800e8SDoug Rabson static int32_t
add_handle(struct client * c,enum handle_type type,void * data)104c19800e8SDoug Rabson add_handle(struct client *c, enum handle_type type, void *data)
105c19800e8SDoug Rabson {
106c19800e8SDoug Rabson struct handle *h;
107c19800e8SDoug Rabson
108c19800e8SDoug Rabson h = ecalloc(1, sizeof(*h));
109c19800e8SDoug Rabson
110c19800e8SDoug Rabson h->idx = ++c->nHandle;
111c19800e8SDoug Rabson h->type = type;
112c19800e8SDoug Rabson h->ptr = data;
113c19800e8SDoug Rabson h->next = c->handles;
114c19800e8SDoug Rabson c->handles = h;
115c19800e8SDoug Rabson
116c19800e8SDoug Rabson return h->idx;
117c19800e8SDoug Rabson }
118c19800e8SDoug Rabson
119c19800e8SDoug Rabson static void
del_handle(struct handle ** h,int32_t idx)120c19800e8SDoug Rabson del_handle(struct handle **h, int32_t idx)
121c19800e8SDoug Rabson {
122c19800e8SDoug Rabson OM_uint32 min_stat;
123c19800e8SDoug Rabson
124c19800e8SDoug Rabson if (idx == 0)
125c19800e8SDoug Rabson return;
126c19800e8SDoug Rabson
127c19800e8SDoug Rabson while (*h) {
128c19800e8SDoug Rabson if ((*h)->idx == idx) {
129c19800e8SDoug Rabson struct handle *p = *h;
130c19800e8SDoug Rabson *h = (*h)->next;
131c19800e8SDoug Rabson switch(p->type) {
132c19800e8SDoug Rabson case handle_context: {
133c19800e8SDoug Rabson gss_ctx_id_t c = p->ptr;
134c19800e8SDoug Rabson gss_delete_sec_context(&min_stat, &c, NULL);
135c19800e8SDoug Rabson break; }
136c19800e8SDoug Rabson case handle_cred: {
137c19800e8SDoug Rabson gss_cred_id_t c = p->ptr;
138c19800e8SDoug Rabson gss_release_cred(&min_stat, &c);
139c19800e8SDoug Rabson break; }
140c19800e8SDoug Rabson }
141c19800e8SDoug Rabson free(p);
142c19800e8SDoug Rabson return;
143c19800e8SDoug Rabson }
144c19800e8SDoug Rabson h = &((*h)->next);
145c19800e8SDoug Rabson }
146c19800e8SDoug Rabson errx(1, "tried to delete an unexisting handle");
147c19800e8SDoug Rabson }
148c19800e8SDoug Rabson
149c19800e8SDoug Rabson static void *
find_handle(struct handle * h,int32_t idx,enum handle_type type)150c19800e8SDoug Rabson find_handle(struct handle *h, int32_t idx, enum handle_type type)
151c19800e8SDoug Rabson {
152c19800e8SDoug Rabson if (idx == 0)
153c19800e8SDoug Rabson return NULL;
154c19800e8SDoug Rabson
155c19800e8SDoug Rabson while (h) {
156c19800e8SDoug Rabson if (h->idx == idx) {
157c19800e8SDoug Rabson if (type == h->type)
158c19800e8SDoug Rabson return h->ptr;
159c19800e8SDoug Rabson errx(1, "monger switched type on handle!");
160c19800e8SDoug Rabson }
161c19800e8SDoug Rabson h = h->next;
162c19800e8SDoug Rabson }
163c19800e8SDoug Rabson return NULL;
164c19800e8SDoug Rabson }
165c19800e8SDoug Rabson
166c19800e8SDoug Rabson
167c19800e8SDoug Rabson static int32_t
convert_gss_to_gsm(OM_uint32 maj_stat)168c19800e8SDoug Rabson convert_gss_to_gsm(OM_uint32 maj_stat)
169c19800e8SDoug Rabson {
170c19800e8SDoug Rabson switch(maj_stat) {
171c19800e8SDoug Rabson case 0:
172c19800e8SDoug Rabson return GSMERR_OK;
173c19800e8SDoug Rabson case GSS_S_CONTINUE_NEEDED:
174c19800e8SDoug Rabson return GSMERR_CONTINUE_NEEDED;
175c19800e8SDoug Rabson case GSS_S_DEFECTIVE_TOKEN:
176c19800e8SDoug Rabson return GSMERR_INVALID_TOKEN;
177c19800e8SDoug Rabson case GSS_S_BAD_MIC:
178c19800e8SDoug Rabson return GSMERR_AP_MODIFIED;
179c19800e8SDoug Rabson default:
180c19800e8SDoug Rabson return GSMERR_ERROR;
181c19800e8SDoug Rabson }
182c19800e8SDoug Rabson }
183c19800e8SDoug Rabson
184c19800e8SDoug Rabson static int32_t
convert_krb5_to_gsm(krb5_error_code ret)185c19800e8SDoug Rabson convert_krb5_to_gsm(krb5_error_code ret)
186c19800e8SDoug Rabson {
187c19800e8SDoug Rabson switch(ret) {
188c19800e8SDoug Rabson case 0:
189c19800e8SDoug Rabson return GSMERR_OK;
190c19800e8SDoug Rabson default:
191c19800e8SDoug Rabson return GSMERR_ERROR;
192c19800e8SDoug Rabson }
193c19800e8SDoug Rabson }
194c19800e8SDoug Rabson
195c19800e8SDoug Rabson /*
196c19800e8SDoug Rabson *
197c19800e8SDoug Rabson */
198c19800e8SDoug Rabson
199c19800e8SDoug Rabson static int32_t
acquire_cred(struct client * c,krb5_principal principal,krb5_get_init_creds_opt * opt,int32_t * handle)200c19800e8SDoug Rabson acquire_cred(struct client *c,
201c19800e8SDoug Rabson krb5_principal principal,
202c19800e8SDoug Rabson krb5_get_init_creds_opt *opt,
203c19800e8SDoug Rabson int32_t *handle)
204c19800e8SDoug Rabson {
205c19800e8SDoug Rabson krb5_error_code ret;
206c19800e8SDoug Rabson krb5_creds cred;
207c19800e8SDoug Rabson krb5_ccache id;
208c19800e8SDoug Rabson gss_cred_id_t gcred;
209c19800e8SDoug Rabson OM_uint32 maj_stat, min_stat;
210c19800e8SDoug Rabson
211c19800e8SDoug Rabson *handle = 0;
212c19800e8SDoug Rabson
213c19800e8SDoug Rabson krb5_get_init_creds_opt_set_forwardable (opt, 1);
214c19800e8SDoug Rabson krb5_get_init_creds_opt_set_renew_life (opt, 3600 * 24 * 30);
215c19800e8SDoug Rabson
216c19800e8SDoug Rabson memset(&cred, 0, sizeof(cred));
217c19800e8SDoug Rabson
218c19800e8SDoug Rabson ret = krb5_get_init_creds_password (context,
219c19800e8SDoug Rabson &cred,
220c19800e8SDoug Rabson principal,
221c19800e8SDoug Rabson NULL,
222c19800e8SDoug Rabson NULL,
223c19800e8SDoug Rabson NULL,
224c19800e8SDoug Rabson 0,
225c19800e8SDoug Rabson NULL,
226c19800e8SDoug Rabson opt);
227c19800e8SDoug Rabson if (ret) {
228c19800e8SDoug Rabson logmessage(c, __FILE__, __LINE__, 0,
229c19800e8SDoug Rabson "krb5_get_init_creds failed: %d", ret);
230c19800e8SDoug Rabson return convert_krb5_to_gsm(ret);
231c19800e8SDoug Rabson }
232c19800e8SDoug Rabson
233c19800e8SDoug Rabson ret = krb5_cc_new_unique(context, "MEMORY", NULL, &id);
234c19800e8SDoug Rabson if (ret)
235c19800e8SDoug Rabson krb5_err (context, 1, ret, "krb5_cc_initialize");
236c19800e8SDoug Rabson
237c19800e8SDoug Rabson ret = krb5_cc_initialize (context, id, cred.client);
238c19800e8SDoug Rabson if (ret)
239c19800e8SDoug Rabson krb5_err (context, 1, ret, "krb5_cc_initialize");
240c19800e8SDoug Rabson
241c19800e8SDoug Rabson ret = krb5_cc_store_cred (context, id, &cred);
242c19800e8SDoug Rabson if (ret)
243c19800e8SDoug Rabson krb5_err (context, 1, ret, "krb5_cc_store_cred");
244c19800e8SDoug Rabson
245c19800e8SDoug Rabson krb5_free_cred_contents (context, &cred);
246c19800e8SDoug Rabson
247c19800e8SDoug Rabson maj_stat = gss_krb5_import_cred(&min_stat,
248c19800e8SDoug Rabson id,
249c19800e8SDoug Rabson NULL,
250c19800e8SDoug Rabson NULL,
251c19800e8SDoug Rabson &gcred);
252c19800e8SDoug Rabson krb5_cc_close(context, id);
253c19800e8SDoug Rabson if (maj_stat) {
254c19800e8SDoug Rabson logmessage(c, __FILE__, __LINE__, 0,
255c19800e8SDoug Rabson "krb5 import creds failed with: %d", maj_stat);
256c19800e8SDoug Rabson return convert_gss_to_gsm(maj_stat);
257c19800e8SDoug Rabson }
258c19800e8SDoug Rabson
259c19800e8SDoug Rabson *handle = add_handle(c, handle_cred, gcred);
260c19800e8SDoug Rabson
261c19800e8SDoug Rabson return 0;
262c19800e8SDoug Rabson }
263c19800e8SDoug Rabson
264c19800e8SDoug Rabson
265c19800e8SDoug Rabson /*
266c19800e8SDoug Rabson *
267c19800e8SDoug Rabson */
268c19800e8SDoug Rabson
269c19800e8SDoug Rabson #define HandleOP(h) \
270c19800e8SDoug Rabson handle##h(enum gssMaggotOp op, struct client *c)
271c19800e8SDoug Rabson
272c19800e8SDoug Rabson /*
273c19800e8SDoug Rabson *
274c19800e8SDoug Rabson */
275c19800e8SDoug Rabson
276c19800e8SDoug Rabson static int
HandleOP(GetVersionInfo)277c19800e8SDoug Rabson HandleOP(GetVersionInfo)
278c19800e8SDoug Rabson {
279c19800e8SDoug Rabson put32(c, GSSMAGGOTPROTOCOL);
280c19800e8SDoug Rabson errx(1, "GetVersionInfo");
281c19800e8SDoug Rabson }
282c19800e8SDoug Rabson
283c19800e8SDoug Rabson static int
HandleOP(GoodBye)284c19800e8SDoug Rabson HandleOP(GoodBye)
285c19800e8SDoug Rabson {
286c19800e8SDoug Rabson struct handle *h = c->handles;
287ae771770SStanislav Sedov unsigned int i = 0;
288c19800e8SDoug Rabson
289c19800e8SDoug Rabson while (h) {
290c19800e8SDoug Rabson h = h->next;
291c19800e8SDoug Rabson i++;
292c19800e8SDoug Rabson }
293c19800e8SDoug Rabson
294ae771770SStanislav Sedov if (i)
295c19800e8SDoug Rabson logmessage(c, __FILE__, __LINE__, 0,
296c19800e8SDoug Rabson "Did not toast all resources: %d", i);
297c19800e8SDoug Rabson return 1;
298c19800e8SDoug Rabson }
299c19800e8SDoug Rabson
300c19800e8SDoug Rabson static int
HandleOP(InitContext)301c19800e8SDoug Rabson HandleOP(InitContext)
302c19800e8SDoug Rabson {
303c19800e8SDoug Rabson OM_uint32 maj_stat, min_stat, ret_flags;
304c19800e8SDoug Rabson int32_t hContext, hCred, flags;
305c19800e8SDoug Rabson krb5_data target_name, in_token;
306c19800e8SDoug Rabson int32_t new_context_id = 0, gsm_error = 0;
307c19800e8SDoug Rabson krb5_data out_token = { 0 , NULL };
308c19800e8SDoug Rabson
309c19800e8SDoug Rabson gss_ctx_id_t ctx;
310c19800e8SDoug Rabson gss_cred_id_t creds;
311c19800e8SDoug Rabson gss_name_t gss_target_name;
312c19800e8SDoug Rabson gss_buffer_desc input_token, output_token;
313c19800e8SDoug Rabson gss_OID oid = GSS_C_NO_OID;
314c19800e8SDoug Rabson gss_buffer_t input_token_ptr = GSS_C_NO_BUFFER;
315c19800e8SDoug Rabson
316c19800e8SDoug Rabson ret32(c, hContext);
317c19800e8SDoug Rabson ret32(c, hCred);
318c19800e8SDoug Rabson ret32(c, flags);
319c19800e8SDoug Rabson retdata(c, target_name);
320c19800e8SDoug Rabson retdata(c, in_token);
321c19800e8SDoug Rabson
322c19800e8SDoug Rabson logmessage(c, __FILE__, __LINE__, 0,
323c19800e8SDoug Rabson "targetname: <%.*s>", (int)target_name.length,
324c19800e8SDoug Rabson (char *)target_name.data);
325c19800e8SDoug Rabson
326c19800e8SDoug Rabson ctx = find_handle(c->handles, hContext, handle_context);
327c19800e8SDoug Rabson if (ctx == NULL)
328c19800e8SDoug Rabson hContext = 0;
329c19800e8SDoug Rabson creds = find_handle(c->handles, hCred, handle_cred);
330c19800e8SDoug Rabson if (creds == NULL)
331c19800e8SDoug Rabson abort();
332c19800e8SDoug Rabson
333c19800e8SDoug Rabson input_token.length = target_name.length;
334c19800e8SDoug Rabson input_token.value = target_name.data;
335c19800e8SDoug Rabson
336c19800e8SDoug Rabson maj_stat = gss_import_name(&min_stat,
337c19800e8SDoug Rabson &input_token,
338c19800e8SDoug Rabson GSS_KRB5_NT_PRINCIPAL_NAME,
339c19800e8SDoug Rabson &gss_target_name);
340c19800e8SDoug Rabson if (GSS_ERROR(maj_stat)) {
341c19800e8SDoug Rabson logmessage(c, __FILE__, __LINE__, 0,
342c19800e8SDoug Rabson "import name creds failed with: %d", maj_stat);
343c19800e8SDoug Rabson gsm_error = convert_gss_to_gsm(maj_stat);
344c19800e8SDoug Rabson goto out;
345c19800e8SDoug Rabson }
346c19800e8SDoug Rabson
347c19800e8SDoug Rabson /* oid from flags */
348c19800e8SDoug Rabson
349c19800e8SDoug Rabson if (in_token.length) {
350c19800e8SDoug Rabson input_token.length = in_token.length;
351c19800e8SDoug Rabson input_token.value = in_token.data;
352c19800e8SDoug Rabson input_token_ptr = &input_token;
353c19800e8SDoug Rabson if (ctx == NULL)
354c19800e8SDoug Rabson krb5_errx(context, 1, "initcreds, context NULL, but not first req");
355c19800e8SDoug Rabson } else {
356c19800e8SDoug Rabson input_token.length = 0;
357c19800e8SDoug Rabson input_token.value = NULL;
358c19800e8SDoug Rabson if (ctx)
359c19800e8SDoug Rabson krb5_errx(context, 1, "initcreds, context not NULL, but first req");
360c19800e8SDoug Rabson }
361c19800e8SDoug Rabson
362c19800e8SDoug Rabson if ((flags & GSS_C_DELEG_FLAG) != 0)
363c19800e8SDoug Rabson logmessage(c, __FILE__, __LINE__, 0, "init_sec_context delegating");
364c19800e8SDoug Rabson if ((flags & GSS_C_DCE_STYLE) != 0)
365c19800e8SDoug Rabson logmessage(c, __FILE__, __LINE__, 0, "init_sec_context dce-style");
366c19800e8SDoug Rabson
367c19800e8SDoug Rabson maj_stat = gss_init_sec_context(&min_stat,
368c19800e8SDoug Rabson creds,
369c19800e8SDoug Rabson &ctx,
370c19800e8SDoug Rabson gss_target_name,
371c19800e8SDoug Rabson oid,
372c19800e8SDoug Rabson flags & 0x7f,
373c19800e8SDoug Rabson 0,
374c19800e8SDoug Rabson NULL,
375c19800e8SDoug Rabson input_token_ptr,
376c19800e8SDoug Rabson NULL,
377c19800e8SDoug Rabson &output_token,
378c19800e8SDoug Rabson &ret_flags,
379c19800e8SDoug Rabson NULL);
380c19800e8SDoug Rabson if (GSS_ERROR(maj_stat)) {
381c19800e8SDoug Rabson if (hContext != 0)
382c19800e8SDoug Rabson del_handle(&c->handles, hContext);
383c19800e8SDoug Rabson new_context_id = 0;
384c19800e8SDoug Rabson logmessage(c, __FILE__, __LINE__, 0,
385c19800e8SDoug Rabson "gss_init_sec_context returns code: %d/%d",
386c19800e8SDoug Rabson maj_stat, min_stat);
387c19800e8SDoug Rabson } else {
388c19800e8SDoug Rabson if (input_token.length == 0)
389c19800e8SDoug Rabson new_context_id = add_handle(c, handle_context, ctx);
390c19800e8SDoug Rabson else
391c19800e8SDoug Rabson new_context_id = hContext;
392c19800e8SDoug Rabson }
393c19800e8SDoug Rabson
394c19800e8SDoug Rabson gsm_error = convert_gss_to_gsm(maj_stat);
395c19800e8SDoug Rabson
396c19800e8SDoug Rabson if (output_token.length) {
397c19800e8SDoug Rabson out_token.data = output_token.value;
398c19800e8SDoug Rabson out_token.length = output_token.length;
399c19800e8SDoug Rabson }
400c19800e8SDoug Rabson
401c19800e8SDoug Rabson out:
402c19800e8SDoug Rabson logmessage(c, __FILE__, __LINE__, 0,
403c19800e8SDoug Rabson "InitContext return code: %d", gsm_error);
404c19800e8SDoug Rabson
405c19800e8SDoug Rabson put32(c, new_context_id);
406c19800e8SDoug Rabson put32(c, gsm_error);
407c19800e8SDoug Rabson putdata(c, out_token);
408c19800e8SDoug Rabson
409c19800e8SDoug Rabson gss_release_name(&min_stat, &gss_target_name);
410c19800e8SDoug Rabson if (output_token.length)
411c19800e8SDoug Rabson gss_release_buffer(&min_stat, &output_token);
412c19800e8SDoug Rabson krb5_data_free(&in_token);
413c19800e8SDoug Rabson krb5_data_free(&target_name);
414c19800e8SDoug Rabson
415c19800e8SDoug Rabson return 0;
416c19800e8SDoug Rabson }
417c19800e8SDoug Rabson
418c19800e8SDoug Rabson static int
HandleOP(AcceptContext)419c19800e8SDoug Rabson HandleOP(AcceptContext)
420c19800e8SDoug Rabson {
421c19800e8SDoug Rabson OM_uint32 maj_stat, min_stat, ret_flags;
422c19800e8SDoug Rabson int32_t hContext, deleg_hcred, flags;
423c19800e8SDoug Rabson krb5_data in_token;
424c19800e8SDoug Rabson int32_t new_context_id = 0, gsm_error = 0;
425c19800e8SDoug Rabson krb5_data out_token = { 0 , NULL };
426c19800e8SDoug Rabson
427c19800e8SDoug Rabson gss_ctx_id_t ctx;
428c19800e8SDoug Rabson gss_cred_id_t deleg_cred = GSS_C_NO_CREDENTIAL;
429c19800e8SDoug Rabson gss_buffer_desc input_token, output_token;
430c19800e8SDoug Rabson gss_buffer_t input_token_ptr = GSS_C_NO_BUFFER;
431c19800e8SDoug Rabson
432c19800e8SDoug Rabson ret32(c, hContext);
433c19800e8SDoug Rabson ret32(c, flags);
434c19800e8SDoug Rabson retdata(c, in_token);
435c19800e8SDoug Rabson
436c19800e8SDoug Rabson ctx = find_handle(c->handles, hContext, handle_context);
437c19800e8SDoug Rabson if (ctx == NULL)
438c19800e8SDoug Rabson hContext = 0;
439c19800e8SDoug Rabson
440c19800e8SDoug Rabson if (in_token.length) {
441c19800e8SDoug Rabson input_token.length = in_token.length;
442c19800e8SDoug Rabson input_token.value = in_token.data;
443c19800e8SDoug Rabson input_token_ptr = &input_token;
444c19800e8SDoug Rabson } else {
445c19800e8SDoug Rabson input_token.length = 0;
446c19800e8SDoug Rabson input_token.value = NULL;
447c19800e8SDoug Rabson }
448c19800e8SDoug Rabson
449c19800e8SDoug Rabson maj_stat = gss_accept_sec_context(&min_stat,
450c19800e8SDoug Rabson &ctx,
451c19800e8SDoug Rabson GSS_C_NO_CREDENTIAL,
452c19800e8SDoug Rabson &input_token,
453c19800e8SDoug Rabson GSS_C_NO_CHANNEL_BINDINGS,
454c19800e8SDoug Rabson NULL,
455c19800e8SDoug Rabson NULL,
456c19800e8SDoug Rabson &output_token,
457c19800e8SDoug Rabson &ret_flags,
458c19800e8SDoug Rabson NULL,
459c19800e8SDoug Rabson &deleg_cred);
460c19800e8SDoug Rabson if (GSS_ERROR(maj_stat)) {
461c19800e8SDoug Rabson if (hContext != 0)
462c19800e8SDoug Rabson del_handle(&c->handles, hContext);
463c19800e8SDoug Rabson logmessage(c, __FILE__, __LINE__, 0,
464c19800e8SDoug Rabson "gss_accept_sec_context returns code: %d/%d",
465c19800e8SDoug Rabson maj_stat, min_stat);
466c19800e8SDoug Rabson new_context_id = 0;
467c19800e8SDoug Rabson } else {
468c19800e8SDoug Rabson if (hContext == 0)
469c19800e8SDoug Rabson new_context_id = add_handle(c, handle_context, ctx);
470c19800e8SDoug Rabson else
471c19800e8SDoug Rabson new_context_id = hContext;
472c19800e8SDoug Rabson }
473c19800e8SDoug Rabson if (output_token.length) {
474c19800e8SDoug Rabson out_token.data = output_token.value;
475c19800e8SDoug Rabson out_token.length = output_token.length;
476c19800e8SDoug Rabson }
477c19800e8SDoug Rabson if ((ret_flags & GSS_C_DCE_STYLE) != 0)
478c19800e8SDoug Rabson logmessage(c, __FILE__, __LINE__, 0, "accept_sec_context dce-style");
479c19800e8SDoug Rabson if ((ret_flags & GSS_C_DELEG_FLAG) != 0) {
480c19800e8SDoug Rabson deleg_hcred = add_handle(c, handle_cred, deleg_cred);
481c19800e8SDoug Rabson logmessage(c, __FILE__, __LINE__, 0,
482c19800e8SDoug Rabson "accept_context delegated handle: %d", deleg_hcred);
483c19800e8SDoug Rabson } else {
484c19800e8SDoug Rabson gss_release_cred(&min_stat, &deleg_cred);
485c19800e8SDoug Rabson deleg_hcred = 0;
486c19800e8SDoug Rabson }
487c19800e8SDoug Rabson
488c19800e8SDoug Rabson
489c19800e8SDoug Rabson gsm_error = convert_gss_to_gsm(maj_stat);
490c19800e8SDoug Rabson
491c19800e8SDoug Rabson put32(c, new_context_id);
492c19800e8SDoug Rabson put32(c, gsm_error);
493c19800e8SDoug Rabson putdata(c, out_token);
494c19800e8SDoug Rabson put32(c, deleg_hcred);
495c19800e8SDoug Rabson
496c19800e8SDoug Rabson if (output_token.length)
497c19800e8SDoug Rabson gss_release_buffer(&min_stat, &output_token);
498c19800e8SDoug Rabson krb5_data_free(&in_token);
499c19800e8SDoug Rabson
500c19800e8SDoug Rabson return 0;
501c19800e8SDoug Rabson }
502c19800e8SDoug Rabson
503c19800e8SDoug Rabson static int
HandleOP(ToastResource)504c19800e8SDoug Rabson HandleOP(ToastResource)
505c19800e8SDoug Rabson {
506c19800e8SDoug Rabson int32_t handle;
507c19800e8SDoug Rabson
508c19800e8SDoug Rabson ret32(c, handle);
509c19800e8SDoug Rabson logmessage(c, __FILE__, __LINE__, 0, "toasting %d", handle);
510c19800e8SDoug Rabson del_handle(&c->handles, handle);
511c19800e8SDoug Rabson put32(c, GSMERR_OK);
512c19800e8SDoug Rabson
513c19800e8SDoug Rabson return 0;
514c19800e8SDoug Rabson }
515c19800e8SDoug Rabson
516c19800e8SDoug Rabson static int
HandleOP(AcquireCreds)517c19800e8SDoug Rabson HandleOP(AcquireCreds)
518c19800e8SDoug Rabson {
519c19800e8SDoug Rabson char *name, *password;
520c19800e8SDoug Rabson int32_t gsm_error, flags, handle = 0;
521c19800e8SDoug Rabson krb5_principal principal = NULL;
522c19800e8SDoug Rabson krb5_get_init_creds_opt *opt = NULL;
523c19800e8SDoug Rabson krb5_error_code ret;
524c19800e8SDoug Rabson
525c19800e8SDoug Rabson retstring(c, name);
526c19800e8SDoug Rabson retstring(c, password);
527c19800e8SDoug Rabson ret32(c, flags);
528c19800e8SDoug Rabson
529c19800e8SDoug Rabson logmessage(c, __FILE__, __LINE__, 0,
530c19800e8SDoug Rabson "username: %s password: %s", name, password);
531c19800e8SDoug Rabson
532c19800e8SDoug Rabson ret = krb5_parse_name(context, name, &principal);
533c19800e8SDoug Rabson if (ret) {
534c19800e8SDoug Rabson gsm_error = convert_krb5_to_gsm(ret);
535c19800e8SDoug Rabson goto out;
536c19800e8SDoug Rabson }
537c19800e8SDoug Rabson
538c19800e8SDoug Rabson ret = krb5_get_init_creds_opt_alloc (context, &opt);
539c19800e8SDoug Rabson if (ret)
540c19800e8SDoug Rabson krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc");
541c19800e8SDoug Rabson
542c19800e8SDoug Rabson krb5_get_init_creds_opt_set_pa_password(context, opt, password, NULL);
543c19800e8SDoug Rabson
544c19800e8SDoug Rabson gsm_error = acquire_cred(c, principal, opt, &handle);
545c19800e8SDoug Rabson
546c19800e8SDoug Rabson out:
547c19800e8SDoug Rabson logmessage(c, __FILE__, __LINE__, 0,
548c19800e8SDoug Rabson "AcquireCreds handle: %d return code: %d", handle, gsm_error);
549c19800e8SDoug Rabson
550c19800e8SDoug Rabson if (opt)
551c19800e8SDoug Rabson krb5_get_init_creds_opt_free (context, opt);
552c19800e8SDoug Rabson if (principal)
553c19800e8SDoug Rabson krb5_free_principal(context, principal);
554c19800e8SDoug Rabson free(name);
555c19800e8SDoug Rabson free(password);
556c19800e8SDoug Rabson
557c19800e8SDoug Rabson put32(c, gsm_error);
558c19800e8SDoug Rabson put32(c, handle);
559c19800e8SDoug Rabson
560c19800e8SDoug Rabson return 0;
561c19800e8SDoug Rabson }
562c19800e8SDoug Rabson
563c19800e8SDoug Rabson static int
HandleOP(Sign)564c19800e8SDoug Rabson HandleOP(Sign)
565c19800e8SDoug Rabson {
566c19800e8SDoug Rabson OM_uint32 maj_stat, min_stat;
567c19800e8SDoug Rabson int32_t hContext, flags, seqno;
568c19800e8SDoug Rabson krb5_data token;
569c19800e8SDoug Rabson gss_ctx_id_t ctx;
570c19800e8SDoug Rabson gss_buffer_desc input_token, output_token;
571c19800e8SDoug Rabson
572c19800e8SDoug Rabson ret32(c, hContext);
573c19800e8SDoug Rabson ret32(c, flags);
574c19800e8SDoug Rabson ret32(c, seqno);
575c19800e8SDoug Rabson retdata(c, token);
576c19800e8SDoug Rabson
577c19800e8SDoug Rabson ctx = find_handle(c->handles, hContext, handle_context);
578c19800e8SDoug Rabson if (ctx == NULL)
579c19800e8SDoug Rabson errx(1, "sign: reference to unknown context");
580c19800e8SDoug Rabson
581c19800e8SDoug Rabson input_token.length = token.length;
582c19800e8SDoug Rabson input_token.value = token.data;
583c19800e8SDoug Rabson
584c19800e8SDoug Rabson maj_stat = gss_get_mic(&min_stat, ctx, 0, &input_token,
585c19800e8SDoug Rabson &output_token);
586c19800e8SDoug Rabson if (maj_stat != GSS_S_COMPLETE)
587c19800e8SDoug Rabson errx(1, "gss_get_mic failed");
588c19800e8SDoug Rabson
589c19800e8SDoug Rabson krb5_data_free(&token);
590c19800e8SDoug Rabson
591c19800e8SDoug Rabson token.data = output_token.value;
592c19800e8SDoug Rabson token.length = output_token.length;
593c19800e8SDoug Rabson
594c19800e8SDoug Rabson put32(c, 0); /* XXX fix gsm_error */
595c19800e8SDoug Rabson putdata(c, token);
596c19800e8SDoug Rabson
597c19800e8SDoug Rabson gss_release_buffer(&min_stat, &output_token);
598c19800e8SDoug Rabson
599c19800e8SDoug Rabson return 0;
600c19800e8SDoug Rabson }
601c19800e8SDoug Rabson
602c19800e8SDoug Rabson static int
HandleOP(Verify)603c19800e8SDoug Rabson HandleOP(Verify)
604c19800e8SDoug Rabson {
605c19800e8SDoug Rabson OM_uint32 maj_stat, min_stat;
606c19800e8SDoug Rabson int32_t hContext, flags, seqno;
607c19800e8SDoug Rabson krb5_data msg, mic;
608c19800e8SDoug Rabson gss_ctx_id_t ctx;
609c19800e8SDoug Rabson gss_buffer_desc msg_token, mic_token;
610c19800e8SDoug Rabson gss_qop_t qop;
611c19800e8SDoug Rabson
612c19800e8SDoug Rabson ret32(c, hContext);
613c19800e8SDoug Rabson
614c19800e8SDoug Rabson ctx = find_handle(c->handles, hContext, handle_context);
615c19800e8SDoug Rabson if (ctx == NULL)
616c19800e8SDoug Rabson errx(1, "verify: reference to unknown context");
617c19800e8SDoug Rabson
618c19800e8SDoug Rabson ret32(c, flags);
619c19800e8SDoug Rabson ret32(c, seqno);
620c19800e8SDoug Rabson retdata(c, msg);
621c19800e8SDoug Rabson
622c19800e8SDoug Rabson msg_token.length = msg.length;
623c19800e8SDoug Rabson msg_token.value = msg.data;
624c19800e8SDoug Rabson
625c19800e8SDoug Rabson retdata(c, mic);
626c19800e8SDoug Rabson
627c19800e8SDoug Rabson mic_token.length = mic.length;
628c19800e8SDoug Rabson mic_token.value = mic.data;
629c19800e8SDoug Rabson
630c19800e8SDoug Rabson maj_stat = gss_verify_mic(&min_stat, ctx, &msg_token,
631c19800e8SDoug Rabson &mic_token, &qop);
632c19800e8SDoug Rabson if (maj_stat != GSS_S_COMPLETE)
633c19800e8SDoug Rabson errx(1, "gss_verify_mic failed");
634c19800e8SDoug Rabson
635c19800e8SDoug Rabson krb5_data_free(&mic);
636c19800e8SDoug Rabson krb5_data_free(&msg);
637c19800e8SDoug Rabson
638c19800e8SDoug Rabson put32(c, 0); /* XXX fix gsm_error */
639c19800e8SDoug Rabson
640c19800e8SDoug Rabson return 0;
641c19800e8SDoug Rabson }
642c19800e8SDoug Rabson
643c19800e8SDoug Rabson static int
HandleOP(GetVersionAndCapabilities)644c19800e8SDoug Rabson HandleOP(GetVersionAndCapabilities)
645c19800e8SDoug Rabson {
646c19800e8SDoug Rabson int32_t cap = HAS_MONIKER;
647c19800e8SDoug Rabson char name[256] = "unknown", *str;
648c19800e8SDoug Rabson
649c19800e8SDoug Rabson if (targetname)
650c19800e8SDoug Rabson cap |= ISSERVER; /* is server */
651c19800e8SDoug Rabson
652c19800e8SDoug Rabson #ifdef HAVE_UNAME
653c19800e8SDoug Rabson {
654c19800e8SDoug Rabson struct utsname ut;
655c19800e8SDoug Rabson if (uname(&ut) == 0) {
656c19800e8SDoug Rabson snprintf(name, sizeof(name), "%s-%s-%s",
657c19800e8SDoug Rabson ut.sysname, ut.version, ut.machine);
658c19800e8SDoug Rabson }
659c19800e8SDoug Rabson }
660c19800e8SDoug Rabson #endif
661c19800e8SDoug Rabson
662c19800e8SDoug Rabson asprintf(&str, "gssmask %s %s", PACKAGE_STRING, name);
663c19800e8SDoug Rabson
664c19800e8SDoug Rabson put32(c, GSSMAGGOTPROTOCOL);
665c19800e8SDoug Rabson put32(c, cap);
666c19800e8SDoug Rabson putstring(c, str);
667c19800e8SDoug Rabson free(str);
668c19800e8SDoug Rabson
669c19800e8SDoug Rabson return 0;
670c19800e8SDoug Rabson }
671c19800e8SDoug Rabson
672c19800e8SDoug Rabson static int
HandleOP(GetTargetName)673c19800e8SDoug Rabson HandleOP(GetTargetName)
674c19800e8SDoug Rabson {
675c19800e8SDoug Rabson if (targetname)
676c19800e8SDoug Rabson putstring(c, targetname);
677c19800e8SDoug Rabson else
678c19800e8SDoug Rabson putstring(c, "");
679c19800e8SDoug Rabson return 0;
680c19800e8SDoug Rabson }
681c19800e8SDoug Rabson
682c19800e8SDoug Rabson static int
HandleOP(SetLoggingSocket)683c19800e8SDoug Rabson HandleOP(SetLoggingSocket)
684c19800e8SDoug Rabson {
685c19800e8SDoug Rabson int32_t portnum;
686c19800e8SDoug Rabson int fd, ret;
687c19800e8SDoug Rabson
688c19800e8SDoug Rabson ret32(c, portnum);
689c19800e8SDoug Rabson
690c19800e8SDoug Rabson logmessage(c, __FILE__, __LINE__, 0,
691c19800e8SDoug Rabson "logging port on peer is: %d", (int)portnum);
692c19800e8SDoug Rabson
693c19800e8SDoug Rabson socket_set_port((struct sockaddr *)(&c->sa), htons(portnum));
694c19800e8SDoug Rabson
695c19800e8SDoug Rabson fd = socket(((struct sockaddr *)&c->sa)->sa_family, SOCK_STREAM, 0);
696c19800e8SDoug Rabson if (fd < 0)
697c19800e8SDoug Rabson return 0;
698c19800e8SDoug Rabson
699c19800e8SDoug Rabson ret = connect(fd, (struct sockaddr *)&c->sa, c->salen);
700c19800e8SDoug Rabson if (ret < 0) {
701c19800e8SDoug Rabson logmessage(c, __FILE__, __LINE__, 0, "failed connect to log port: %s",
702c19800e8SDoug Rabson strerror(errno));
703c19800e8SDoug Rabson close(fd);
704c19800e8SDoug Rabson return 0;
705c19800e8SDoug Rabson }
706c19800e8SDoug Rabson
707c19800e8SDoug Rabson if (c->logging)
708c19800e8SDoug Rabson krb5_storage_free(c->logging);
709c19800e8SDoug Rabson c->logging = krb5_storage_from_fd(fd);
710c19800e8SDoug Rabson close(fd);
711c19800e8SDoug Rabson
712c19800e8SDoug Rabson krb5_store_int32(c->logging, eLogSetMoniker);
713c19800e8SDoug Rabson store_string(c->logging, c->moniker);
714c19800e8SDoug Rabson
715c19800e8SDoug Rabson logmessage(c, __FILE__, __LINE__, 0, "logging turned on");
716c19800e8SDoug Rabson
717c19800e8SDoug Rabson return 0;
718c19800e8SDoug Rabson }
719c19800e8SDoug Rabson
720c19800e8SDoug Rabson
721c19800e8SDoug Rabson static int
HandleOP(ChangePassword)722c19800e8SDoug Rabson HandleOP(ChangePassword)
723c19800e8SDoug Rabson {
724c19800e8SDoug Rabson errx(1, "ChangePassword");
725c19800e8SDoug Rabson }
726c19800e8SDoug Rabson
727c19800e8SDoug Rabson static int
HandleOP(SetPasswordSelf)728c19800e8SDoug Rabson HandleOP(SetPasswordSelf)
729c19800e8SDoug Rabson {
730c19800e8SDoug Rabson errx(1, "SetPasswordSelf");
731c19800e8SDoug Rabson }
732c19800e8SDoug Rabson
733c19800e8SDoug Rabson static int
HandleOP(Wrap)734c19800e8SDoug Rabson HandleOP(Wrap)
735c19800e8SDoug Rabson {
736c19800e8SDoug Rabson OM_uint32 maj_stat, min_stat;
737c19800e8SDoug Rabson int32_t hContext, flags, seqno;
738c19800e8SDoug Rabson krb5_data token;
739c19800e8SDoug Rabson gss_ctx_id_t ctx;
740c19800e8SDoug Rabson gss_buffer_desc input_token, output_token;
741c19800e8SDoug Rabson int conf_state;
742c19800e8SDoug Rabson
743c19800e8SDoug Rabson ret32(c, hContext);
744c19800e8SDoug Rabson ret32(c, flags);
745c19800e8SDoug Rabson ret32(c, seqno);
746c19800e8SDoug Rabson retdata(c, token);
747c19800e8SDoug Rabson
748c19800e8SDoug Rabson ctx = find_handle(c->handles, hContext, handle_context);
749c19800e8SDoug Rabson if (ctx == NULL)
750c19800e8SDoug Rabson errx(1, "wrap: reference to unknown context");
751c19800e8SDoug Rabson
752c19800e8SDoug Rabson input_token.length = token.length;
753c19800e8SDoug Rabson input_token.value = token.data;
754c19800e8SDoug Rabson
755c19800e8SDoug Rabson maj_stat = gss_wrap(&min_stat, ctx, flags, 0, &input_token,
756c19800e8SDoug Rabson &conf_state, &output_token);
757c19800e8SDoug Rabson if (maj_stat != GSS_S_COMPLETE)
758c19800e8SDoug Rabson errx(1, "gss_wrap failed");
759c19800e8SDoug Rabson
760c19800e8SDoug Rabson krb5_data_free(&token);
761c19800e8SDoug Rabson
762c19800e8SDoug Rabson token.data = output_token.value;
763c19800e8SDoug Rabson token.length = output_token.length;
764c19800e8SDoug Rabson
765c19800e8SDoug Rabson put32(c, 0); /* XXX fix gsm_error */
766c19800e8SDoug Rabson putdata(c, token);
767c19800e8SDoug Rabson
768c19800e8SDoug Rabson gss_release_buffer(&min_stat, &output_token);
769c19800e8SDoug Rabson
770c19800e8SDoug Rabson return 0;
771c19800e8SDoug Rabson }
772c19800e8SDoug Rabson
773c19800e8SDoug Rabson
774c19800e8SDoug Rabson static int
HandleOP(Unwrap)775c19800e8SDoug Rabson HandleOP(Unwrap)
776c19800e8SDoug Rabson {
777c19800e8SDoug Rabson OM_uint32 maj_stat, min_stat;
778c19800e8SDoug Rabson int32_t hContext, flags, seqno;
779c19800e8SDoug Rabson krb5_data token;
780c19800e8SDoug Rabson gss_ctx_id_t ctx;
781c19800e8SDoug Rabson gss_buffer_desc input_token, output_token;
782c19800e8SDoug Rabson int conf_state;
783c19800e8SDoug Rabson gss_qop_t qop_state;
784c19800e8SDoug Rabson
785c19800e8SDoug Rabson ret32(c, hContext);
786c19800e8SDoug Rabson ret32(c, flags);
787c19800e8SDoug Rabson ret32(c, seqno);
788c19800e8SDoug Rabson retdata(c, token);
789c19800e8SDoug Rabson
790c19800e8SDoug Rabson ctx = find_handle(c->handles, hContext, handle_context);
791c19800e8SDoug Rabson if (ctx == NULL)
792c19800e8SDoug Rabson errx(1, "unwrap: reference to unknown context");
793c19800e8SDoug Rabson
794c19800e8SDoug Rabson input_token.length = token.length;
795c19800e8SDoug Rabson input_token.value = token.data;
796c19800e8SDoug Rabson
797c19800e8SDoug Rabson maj_stat = gss_unwrap(&min_stat, ctx, &input_token,
798c19800e8SDoug Rabson &output_token, &conf_state, &qop_state);
799c19800e8SDoug Rabson
800c19800e8SDoug Rabson if (maj_stat != GSS_S_COMPLETE)
801c19800e8SDoug Rabson errx(1, "gss_unwrap failed: %d/%d", maj_stat, min_stat);
802c19800e8SDoug Rabson
803c19800e8SDoug Rabson krb5_data_free(&token);
804c19800e8SDoug Rabson if (maj_stat == GSS_S_COMPLETE) {
805c19800e8SDoug Rabson token.data = output_token.value;
806c19800e8SDoug Rabson token.length = output_token.length;
807c19800e8SDoug Rabson } else {
808c19800e8SDoug Rabson token.data = NULL;
809c19800e8SDoug Rabson token.length = 0;
810c19800e8SDoug Rabson }
811c19800e8SDoug Rabson put32(c, 0); /* XXX fix gsm_error */
812c19800e8SDoug Rabson putdata(c, token);
813c19800e8SDoug Rabson
814c19800e8SDoug Rabson if (maj_stat == GSS_S_COMPLETE)
815c19800e8SDoug Rabson gss_release_buffer(&min_stat, &output_token);
816c19800e8SDoug Rabson
817c19800e8SDoug Rabson return 0;
818c19800e8SDoug Rabson }
819c19800e8SDoug Rabson
820c19800e8SDoug Rabson static int
HandleOP(Encrypt)821c19800e8SDoug Rabson HandleOP(Encrypt)
822c19800e8SDoug Rabson {
823c19800e8SDoug Rabson return handleWrap(op, c);
824c19800e8SDoug Rabson }
825c19800e8SDoug Rabson
826c19800e8SDoug Rabson static int
HandleOP(Decrypt)827c19800e8SDoug Rabson HandleOP(Decrypt)
828c19800e8SDoug Rabson {
829c19800e8SDoug Rabson return handleUnwrap(op, c);
830c19800e8SDoug Rabson }
831c19800e8SDoug Rabson
832c19800e8SDoug Rabson static int
HandleOP(ConnectLoggingService2)833c19800e8SDoug Rabson HandleOP(ConnectLoggingService2)
834c19800e8SDoug Rabson {
835c19800e8SDoug Rabson errx(1, "ConnectLoggingService2");
836c19800e8SDoug Rabson }
837c19800e8SDoug Rabson
838c19800e8SDoug Rabson static int
HandleOP(GetMoniker)839c19800e8SDoug Rabson HandleOP(GetMoniker)
840c19800e8SDoug Rabson {
841c19800e8SDoug Rabson putstring(c, c->moniker);
842c19800e8SDoug Rabson return 0;
843c19800e8SDoug Rabson }
844c19800e8SDoug Rabson
845c19800e8SDoug Rabson static int
HandleOP(CallExtension)846c19800e8SDoug Rabson HandleOP(CallExtension)
847c19800e8SDoug Rabson {
848c19800e8SDoug Rabson errx(1, "CallExtension");
849c19800e8SDoug Rabson }
850c19800e8SDoug Rabson
851c19800e8SDoug Rabson static int
HandleOP(AcquirePKInitCreds)852c19800e8SDoug Rabson HandleOP(AcquirePKInitCreds)
853c19800e8SDoug Rabson {
854c19800e8SDoug Rabson int32_t flags;
855c19800e8SDoug Rabson krb5_data pfxdata;
856ae771770SStanislav Sedov char fn[] = "FILE:/tmp/pkcs12-creds-XXXXXXX";
857ae771770SStanislav Sedov krb5_principal principal = NULL;
858ae771770SStanislav Sedov int fd;
859c19800e8SDoug Rabson
860c19800e8SDoug Rabson ret32(c, flags);
861c19800e8SDoug Rabson retdata(c, pfxdata);
862c19800e8SDoug Rabson
863ae771770SStanislav Sedov fd = mkstemp(fn + 5);
864ae771770SStanislav Sedov if (fd < 0)
865ae771770SStanislav Sedov errx(1, "mkstemp");
866c19800e8SDoug Rabson
867ae771770SStanislav Sedov net_write(fd, pfxdata.data, pfxdata.length);
868c19800e8SDoug Rabson krb5_data_free(&pfxdata);
869ae771770SStanislav Sedov close(fd);
870ae771770SStanislav Sedov
871ae771770SStanislav Sedov if (principal)
872ae771770SStanislav Sedov krb5_free_principal(context, principal);
873c19800e8SDoug Rabson
874c19800e8SDoug Rabson put32(c, -1); /* hResource */
875c19800e8SDoug Rabson put32(c, GSMERR_NOT_SUPPORTED);
876c19800e8SDoug Rabson return 0;
877c19800e8SDoug Rabson }
878c19800e8SDoug Rabson
879ae771770SStanislav Sedov static int
HandleOP(WrapExt)880ae771770SStanislav Sedov HandleOP(WrapExt)
881ae771770SStanislav Sedov {
882ae771770SStanislav Sedov OM_uint32 maj_stat, min_stat;
883ae771770SStanislav Sedov int32_t hContext, flags, bflags;
884ae771770SStanislav Sedov krb5_data token, header, trailer;
885ae771770SStanislav Sedov gss_ctx_id_t ctx;
886ae771770SStanislav Sedov unsigned char *p;
887ae771770SStanislav Sedov int conf_state, iov_len;
888ae771770SStanislav Sedov gss_iov_buffer_desc iov[6];
889ae771770SStanislav Sedov
890ae771770SStanislav Sedov ret32(c, hContext);
891ae771770SStanislav Sedov ret32(c, flags);
892ae771770SStanislav Sedov ret32(c, bflags);
893ae771770SStanislav Sedov retdata(c, header);
894ae771770SStanislav Sedov retdata(c, token);
895ae771770SStanislav Sedov retdata(c, trailer);
896ae771770SStanislav Sedov
897ae771770SStanislav Sedov ctx = find_handle(c->handles, hContext, handle_context);
898ae771770SStanislav Sedov if (ctx == NULL)
899ae771770SStanislav Sedov errx(1, "wrap: reference to unknown context");
900ae771770SStanislav Sedov
901ae771770SStanislav Sedov memset(&iov, 0, sizeof(iov));
902ae771770SStanislav Sedov
903ae771770SStanislav Sedov iov_len = sizeof(iov)/sizeof(iov[0]);
904ae771770SStanislav Sedov
905ae771770SStanislav Sedov if (bflags & WRAP_EXP_ONLY_HEADER)
906ae771770SStanislav Sedov iov_len -= 2; /* skip trailer and padding, aka dce-style */
907ae771770SStanislav Sedov
908ae771770SStanislav Sedov iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE;
909ae771770SStanislav Sedov if (header.length != 0) {
910ae771770SStanislav Sedov iov[1].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY;
911ae771770SStanislav Sedov iov[1].buffer.length = header.length;
912ae771770SStanislav Sedov iov[1].buffer.value = header.data;
913ae771770SStanislav Sedov } else {
914ae771770SStanislav Sedov iov[1].type = GSS_IOV_BUFFER_TYPE_EMPTY;
915ae771770SStanislav Sedov }
916ae771770SStanislav Sedov iov[2].type = GSS_IOV_BUFFER_TYPE_DATA;
917ae771770SStanislav Sedov iov[2].buffer.length = token.length;
918ae771770SStanislav Sedov iov[2].buffer.value = token.data;
919ae771770SStanislav Sedov if (trailer.length != 0) {
920ae771770SStanislav Sedov iov[3].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY;
921ae771770SStanislav Sedov iov[3].buffer.length = trailer.length;
922ae771770SStanislav Sedov iov[3].buffer.value = trailer.data;
923ae771770SStanislav Sedov } else {
924ae771770SStanislav Sedov iov[3].type = GSS_IOV_BUFFER_TYPE_EMPTY;
925ae771770SStanislav Sedov }
926ae771770SStanislav Sedov iov[4].type = GSS_IOV_BUFFER_TYPE_PADDING | GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE;
927ae771770SStanislav Sedov iov[5].type = GSS_IOV_BUFFER_TYPE_TRAILER | GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE;
928ae771770SStanislav Sedov
929ae771770SStanislav Sedov maj_stat = gss_wrap_iov_length(&min_stat, ctx, flags, 0, &conf_state,
930ae771770SStanislav Sedov iov, iov_len);
931ae771770SStanislav Sedov if (maj_stat != GSS_S_COMPLETE)
932ae771770SStanislav Sedov errx(1, "gss_wrap_iov_length failed");
933ae771770SStanislav Sedov
934ae771770SStanislav Sedov maj_stat = gss_wrap_iov(&min_stat, ctx, flags, 0, &conf_state,
935ae771770SStanislav Sedov iov, iov_len);
936ae771770SStanislav Sedov if (maj_stat != GSS_S_COMPLETE)
937ae771770SStanislav Sedov errx(1, "gss_wrap_iov failed");
938ae771770SStanislav Sedov
939ae771770SStanislav Sedov krb5_data_free(&token);
940ae771770SStanislav Sedov
941ae771770SStanislav Sedov token.length = iov[0].buffer.length + iov[2].buffer.length + iov[4].buffer.length + iov[5].buffer.length;
942ae771770SStanislav Sedov token.data = malloc(token.length);
943ae771770SStanislav Sedov
944ae771770SStanislav Sedov p = token.data;
945ae771770SStanislav Sedov memcpy(p, iov[0].buffer.value, iov[0].buffer.length);
946ae771770SStanislav Sedov p += iov[0].buffer.length;
947ae771770SStanislav Sedov memcpy(p, iov[2].buffer.value, iov[2].buffer.length);
948ae771770SStanislav Sedov p += iov[2].buffer.length;
949ae771770SStanislav Sedov memcpy(p, iov[4].buffer.value, iov[4].buffer.length);
950ae771770SStanislav Sedov p += iov[4].buffer.length;
951ae771770SStanislav Sedov memcpy(p, iov[5].buffer.value, iov[5].buffer.length);
952*ed549cb0SCy Schubert #ifndef __clang_analyzer__
953ae771770SStanislav Sedov p += iov[5].buffer.length;
954*ed549cb0SCy Schubert #endif
955ae771770SStanislav Sedov
956ae771770SStanislav Sedov gss_release_iov_buffer(NULL, iov, iov_len);
957ae771770SStanislav Sedov
958ae771770SStanislav Sedov put32(c, 0); /* XXX fix gsm_error */
959ae771770SStanislav Sedov putdata(c, token);
960ae771770SStanislav Sedov
961ae771770SStanislav Sedov free(token.data);
962ae771770SStanislav Sedov
963ae771770SStanislav Sedov return 0;
964ae771770SStanislav Sedov }
965ae771770SStanislav Sedov
966ae771770SStanislav Sedov
967ae771770SStanislav Sedov static int
HandleOP(UnwrapExt)968ae771770SStanislav Sedov HandleOP(UnwrapExt)
969ae771770SStanislav Sedov {
970ae771770SStanislav Sedov OM_uint32 maj_stat, min_stat;
971ae771770SStanislav Sedov int32_t hContext, flags, bflags;
972ae771770SStanislav Sedov krb5_data token, header, trailer;
973ae771770SStanislav Sedov gss_ctx_id_t ctx;
974ae771770SStanislav Sedov gss_iov_buffer_desc iov[3];
975ae771770SStanislav Sedov int conf_state, iov_len;
976ae771770SStanislav Sedov gss_qop_t qop_state;
977ae771770SStanislav Sedov
978ae771770SStanislav Sedov ret32(c, hContext);
979ae771770SStanislav Sedov ret32(c, flags);
980ae771770SStanislav Sedov ret32(c, bflags);
981ae771770SStanislav Sedov retdata(c, header);
982ae771770SStanislav Sedov retdata(c, token);
983ae771770SStanislav Sedov retdata(c, trailer);
984ae771770SStanislav Sedov
985ae771770SStanislav Sedov iov_len = sizeof(iov)/sizeof(iov[0]);
986ae771770SStanislav Sedov
987ae771770SStanislav Sedov if (bflags & WRAP_EXP_ONLY_HEADER)
988ae771770SStanislav Sedov iov_len -= 1; /* skip trailer and padding, aka dce-style */
989ae771770SStanislav Sedov
990ae771770SStanislav Sedov ctx = find_handle(c->handles, hContext, handle_context);
991ae771770SStanislav Sedov if (ctx == NULL)
992ae771770SStanislav Sedov errx(1, "unwrap: reference to unknown context");
993ae771770SStanislav Sedov
994ae771770SStanislav Sedov if (header.length != 0) {
995ae771770SStanislav Sedov iov[0].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY;
996ae771770SStanislav Sedov iov[0].buffer.length = header.length;
997ae771770SStanislav Sedov iov[0].buffer.value = header.data;
998ae771770SStanislav Sedov } else {
999ae771770SStanislav Sedov iov[0].type = GSS_IOV_BUFFER_TYPE_EMPTY;
1000ae771770SStanislav Sedov }
1001ae771770SStanislav Sedov iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
1002ae771770SStanislav Sedov iov[1].buffer.length = token.length;
1003ae771770SStanislav Sedov iov[1].buffer.value = token.data;
1004ae771770SStanislav Sedov
1005ae771770SStanislav Sedov if (trailer.length != 0) {
1006ae771770SStanislav Sedov iov[2].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY;
1007ae771770SStanislav Sedov iov[2].buffer.length = trailer.length;
1008ae771770SStanislav Sedov iov[2].buffer.value = trailer.data;
1009ae771770SStanislav Sedov } else {
1010ae771770SStanislav Sedov iov[2].type = GSS_IOV_BUFFER_TYPE_EMPTY;
1011ae771770SStanislav Sedov }
1012ae771770SStanislav Sedov
1013ae771770SStanislav Sedov maj_stat = gss_unwrap_iov(&min_stat, ctx, &conf_state, &qop_state,
1014ae771770SStanislav Sedov iov, iov_len);
1015ae771770SStanislav Sedov
1016ae771770SStanislav Sedov if (maj_stat != GSS_S_COMPLETE)
1017ae771770SStanislav Sedov errx(1, "gss_unwrap failed: %d/%d", maj_stat, min_stat);
1018ae771770SStanislav Sedov
1019ae771770SStanislav Sedov if (maj_stat == GSS_S_COMPLETE) {
1020ae771770SStanislav Sedov token.data = iov[1].buffer.value;
1021ae771770SStanislav Sedov token.length = iov[1].buffer.length;
1022ae771770SStanislav Sedov } else {
1023ae771770SStanislav Sedov token.data = NULL;
1024ae771770SStanislav Sedov token.length = 0;
1025ae771770SStanislav Sedov }
1026ae771770SStanislav Sedov put32(c, 0); /* XXX fix gsm_error */
1027ae771770SStanislav Sedov putdata(c, token);
1028ae771770SStanislav Sedov
1029ae771770SStanislav Sedov return 0;
1030ae771770SStanislav Sedov }
1031ae771770SStanislav Sedov
1032c19800e8SDoug Rabson /*
1033c19800e8SDoug Rabson *
1034c19800e8SDoug Rabson */
1035c19800e8SDoug Rabson
1036c19800e8SDoug Rabson struct handler {
1037c19800e8SDoug Rabson enum gssMaggotOp op;
1038c19800e8SDoug Rabson const char *name;
1039c19800e8SDoug Rabson int (*func)(enum gssMaggotOp, struct client *);
1040c19800e8SDoug Rabson };
1041c19800e8SDoug Rabson
1042c19800e8SDoug Rabson #define S(a) { e##a, #a, handle##a }
1043c19800e8SDoug Rabson
1044c19800e8SDoug Rabson struct handler handlers[] = {
1045c19800e8SDoug Rabson S(GetVersionInfo),
1046c19800e8SDoug Rabson S(GoodBye),
1047c19800e8SDoug Rabson S(InitContext),
1048c19800e8SDoug Rabson S(AcceptContext),
1049c19800e8SDoug Rabson S(ToastResource),
1050c19800e8SDoug Rabson S(AcquireCreds),
1051c19800e8SDoug Rabson S(Encrypt),
1052c19800e8SDoug Rabson S(Decrypt),
1053c19800e8SDoug Rabson S(Sign),
1054c19800e8SDoug Rabson S(Verify),
1055c19800e8SDoug Rabson S(GetVersionAndCapabilities),
1056c19800e8SDoug Rabson S(GetTargetName),
1057c19800e8SDoug Rabson S(SetLoggingSocket),
1058c19800e8SDoug Rabson S(ChangePassword),
1059c19800e8SDoug Rabson S(SetPasswordSelf),
1060c19800e8SDoug Rabson S(Wrap),
1061c19800e8SDoug Rabson S(Unwrap),
1062c19800e8SDoug Rabson S(ConnectLoggingService2),
1063c19800e8SDoug Rabson S(GetMoniker),
1064c19800e8SDoug Rabson S(CallExtension),
1065ae771770SStanislav Sedov S(AcquirePKInitCreds),
1066ae771770SStanislav Sedov S(WrapExt),
1067ae771770SStanislav Sedov S(UnwrapExt),
1068c19800e8SDoug Rabson };
1069c19800e8SDoug Rabson
1070c19800e8SDoug Rabson #undef S
1071c19800e8SDoug Rabson
1072c19800e8SDoug Rabson /*
1073c19800e8SDoug Rabson *
1074c19800e8SDoug Rabson */
1075c19800e8SDoug Rabson
1076c19800e8SDoug Rabson static struct handler *
find_op(int32_t op)1077c19800e8SDoug Rabson find_op(int32_t op)
1078c19800e8SDoug Rabson {
1079c19800e8SDoug Rabson int i;
1080c19800e8SDoug Rabson
1081c19800e8SDoug Rabson for (i = 0; i < sizeof(handlers)/sizeof(handlers[0]); i++)
1082c19800e8SDoug Rabson if (handlers[i].op == op)
1083c19800e8SDoug Rabson return &handlers[i];
1084c19800e8SDoug Rabson return NULL;
1085c19800e8SDoug Rabson }
1086c19800e8SDoug Rabson
1087c19800e8SDoug Rabson static struct client *
create_client(int fd,int port,const char * moniker)1088c19800e8SDoug Rabson create_client(int fd, int port, const char *moniker)
1089c19800e8SDoug Rabson {
1090c19800e8SDoug Rabson struct client *c;
1091c19800e8SDoug Rabson
1092c19800e8SDoug Rabson c = ecalloc(1, sizeof(*c));
1093c19800e8SDoug Rabson
1094c19800e8SDoug Rabson if (moniker) {
1095c19800e8SDoug Rabson c->moniker = estrdup(moniker);
1096c19800e8SDoug Rabson } else {
1097c19800e8SDoug Rabson char hostname[MAXHOSTNAMELEN];
1098c19800e8SDoug Rabson gethostname(hostname, sizeof(hostname));
1099c19800e8SDoug Rabson asprintf(&c->moniker, "gssmask: %s:%d", hostname, port);
1100c19800e8SDoug Rabson }
1101c19800e8SDoug Rabson
1102c19800e8SDoug Rabson {
1103c19800e8SDoug Rabson c->salen = sizeof(c->sa);
1104c19800e8SDoug Rabson getpeername(fd, (struct sockaddr *)&c->sa, &c->salen);
1105c19800e8SDoug Rabson
1106c19800e8SDoug Rabson getnameinfo((struct sockaddr *)&c->sa, c->salen,
1107c19800e8SDoug Rabson c->servername, sizeof(c->servername),
1108c19800e8SDoug Rabson NULL, 0, NI_NUMERICHOST);
1109c19800e8SDoug Rabson }
1110c19800e8SDoug Rabson
1111c19800e8SDoug Rabson c->sock = krb5_storage_from_fd(fd);
1112c19800e8SDoug Rabson if (c->sock == NULL)
1113c19800e8SDoug Rabson errx(1, "krb5_storage_from_fd");
1114c19800e8SDoug Rabson
1115c19800e8SDoug Rabson close(fd);
1116c19800e8SDoug Rabson
1117c19800e8SDoug Rabson return c;
1118c19800e8SDoug Rabson }
1119c19800e8SDoug Rabson
1120c19800e8SDoug Rabson static void
free_client(struct client * c)1121c19800e8SDoug Rabson free_client(struct client *c)
1122c19800e8SDoug Rabson {
1123c19800e8SDoug Rabson while(c->handles)
1124c19800e8SDoug Rabson del_handle(&c->handles, c->handles->idx);
1125c19800e8SDoug Rabson
1126c19800e8SDoug Rabson free(c->moniker);
1127c19800e8SDoug Rabson krb5_storage_free(c->sock);
1128c19800e8SDoug Rabson if (c->logging)
1129c19800e8SDoug Rabson krb5_storage_free(c->logging);
1130c19800e8SDoug Rabson free(c);
1131c19800e8SDoug Rabson }
1132c19800e8SDoug Rabson
1133c19800e8SDoug Rabson
1134c19800e8SDoug Rabson static void *
handleServer(void * ptr)1135c19800e8SDoug Rabson handleServer(void *ptr)
1136c19800e8SDoug Rabson {
1137c19800e8SDoug Rabson struct handler *handler;
1138c19800e8SDoug Rabson struct client *c;
1139c19800e8SDoug Rabson int32_t op;
1140c19800e8SDoug Rabson
1141c19800e8SDoug Rabson c = (struct client *)ptr;
1142c19800e8SDoug Rabson
1143c19800e8SDoug Rabson
1144c19800e8SDoug Rabson while(1) {
1145c19800e8SDoug Rabson ret32(c, op);
1146c19800e8SDoug Rabson
1147c19800e8SDoug Rabson handler = find_op(op);
1148c19800e8SDoug Rabson if (handler == NULL) {
1149c19800e8SDoug Rabson logmessage(c, __FILE__, __LINE__, 0,
1150c19800e8SDoug Rabson "op %d not supported", (int)op);
1151c19800e8SDoug Rabson exit(1);
1152c19800e8SDoug Rabson }
1153c19800e8SDoug Rabson
1154c19800e8SDoug Rabson logmessage(c, __FILE__, __LINE__, 0,
1155c19800e8SDoug Rabson "---> Got op %s from server %s",
1156c19800e8SDoug Rabson handler->name, c->servername);
1157c19800e8SDoug Rabson
1158c19800e8SDoug Rabson if ((handler->func)(handler->op, c))
1159c19800e8SDoug Rabson break;
1160c19800e8SDoug Rabson }
1161c19800e8SDoug Rabson
1162c19800e8SDoug Rabson return NULL;
1163c19800e8SDoug Rabson }
1164c19800e8SDoug Rabson
1165c19800e8SDoug Rabson
1166c19800e8SDoug Rabson static char *port_str;
1167c19800e8SDoug Rabson static int version_flag;
1168c19800e8SDoug Rabson static int help_flag;
1169c19800e8SDoug Rabson static char *logfile_str;
1170c19800e8SDoug Rabson static char *moniker_str;
1171c19800e8SDoug Rabson
1172c19800e8SDoug Rabson static int port = 4711;
1173c19800e8SDoug Rabson
1174c19800e8SDoug Rabson struct getargs args[] = {
1175c19800e8SDoug Rabson { "spn", 0, arg_string, &targetname, "This host's SPN",
1176c19800e8SDoug Rabson "service/host@REALM" },
1177c19800e8SDoug Rabson { "port", 'p', arg_string, &port_str, "Use this port",
1178c19800e8SDoug Rabson "number-of-service" },
1179c19800e8SDoug Rabson { "logfile", 0, arg_string, &logfile_str, "logfile",
1180c19800e8SDoug Rabson "number-of-service" },
1181c19800e8SDoug Rabson { "moniker", 0, arg_string, &moniker_str, "nickname",
1182c19800e8SDoug Rabson "name" },
1183c19800e8SDoug Rabson { "version", 0, arg_flag, &version_flag, "Print version",
1184c19800e8SDoug Rabson NULL },
1185c19800e8SDoug Rabson { "help", 0, arg_flag, &help_flag, NULL,
1186c19800e8SDoug Rabson NULL }
1187c19800e8SDoug Rabson };
1188c19800e8SDoug Rabson
1189c19800e8SDoug Rabson static void
usage(int ret)1190c19800e8SDoug Rabson usage(int ret)
1191c19800e8SDoug Rabson {
1192c19800e8SDoug Rabson arg_printusage (args,
1193c19800e8SDoug Rabson sizeof(args) / sizeof(args[0]),
1194c19800e8SDoug Rabson NULL,
1195c19800e8SDoug Rabson "");
1196c19800e8SDoug Rabson exit (ret);
1197c19800e8SDoug Rabson }
1198c19800e8SDoug Rabson
1199c19800e8SDoug Rabson int
main(int argc,char ** argv)1200c19800e8SDoug Rabson main(int argc, char **argv)
1201c19800e8SDoug Rabson {
1202c19800e8SDoug Rabson int optidx = 0;
1203c19800e8SDoug Rabson
1204c19800e8SDoug Rabson setprogname (argv[0]);
1205c19800e8SDoug Rabson
1206c19800e8SDoug Rabson if (getarg (args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
1207c19800e8SDoug Rabson usage (1);
1208c19800e8SDoug Rabson
1209c19800e8SDoug Rabson if (help_flag)
1210c19800e8SDoug Rabson usage (0);
1211c19800e8SDoug Rabson
1212c19800e8SDoug Rabson if (version_flag) {
1213c19800e8SDoug Rabson print_version (NULL);
1214c19800e8SDoug Rabson return 0;
1215c19800e8SDoug Rabson }
1216c19800e8SDoug Rabson
1217c19800e8SDoug Rabson if (optidx != argc)
1218c19800e8SDoug Rabson usage (1);
1219c19800e8SDoug Rabson
1220c19800e8SDoug Rabson if (port_str) {
1221c19800e8SDoug Rabson char *ptr;
1222c19800e8SDoug Rabson
1223c19800e8SDoug Rabson port = strtol (port_str, &ptr, 10);
1224c19800e8SDoug Rabson if (port == 0 && ptr == port_str)
1225c19800e8SDoug Rabson errx (1, "Bad port `%s'", port_str);
1226c19800e8SDoug Rabson }
1227c19800e8SDoug Rabson
1228c19800e8SDoug Rabson krb5_init_context(&context);
1229c19800e8SDoug Rabson
1230c19800e8SDoug Rabson {
1231c19800e8SDoug Rabson const char *lf = logfile_str;
1232c19800e8SDoug Rabson if (lf == NULL)
1233c19800e8SDoug Rabson lf = "/dev/tty";
1234c19800e8SDoug Rabson
1235c19800e8SDoug Rabson logfile = fopen(lf, "w");
1236c19800e8SDoug Rabson if (logfile == NULL)
1237c19800e8SDoug Rabson err(1, "error opening %s", lf);
1238c19800e8SDoug Rabson }
1239c19800e8SDoug Rabson
1240ae771770SStanislav Sedov mini_inetd(htons(port), NULL);
1241c19800e8SDoug Rabson fprintf(logfile, "connected\n");
1242c19800e8SDoug Rabson
1243c19800e8SDoug Rabson {
1244c19800e8SDoug Rabson struct client *c;
1245c19800e8SDoug Rabson
1246c19800e8SDoug Rabson c = create_client(0, port, moniker_str);
1247c19800e8SDoug Rabson /* close(0); */
1248c19800e8SDoug Rabson
1249c19800e8SDoug Rabson handleServer(c);
1250c19800e8SDoug Rabson
1251c19800e8SDoug Rabson free_client(c);
1252c19800e8SDoug Rabson }
1253c19800e8SDoug Rabson
1254c19800e8SDoug Rabson krb5_free_context(context);
1255c19800e8SDoug Rabson
1256c19800e8SDoug Rabson return 0;
1257c19800e8SDoug Rabson }
1258