Add.
[shishi.git] / src / kdc.c
blobb2590f13415dafc5286f085ee66856381155f88a
1 /* kdc.c low-level authentication (AS and TGS) services
2 * Copyright (C) 2002, 2003 Simon Josefsson
4 * This file is part of Shishi.
6 * Shishi is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * Shishi is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Shishi; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "data.h"
24 int
25 kdc_write_apreq (Shishi * handle, struct arguments arg, ASN1_TYPE req)
27 int res, i, n;
29 res = asn1_number_of_elements (req, "KDC-REQ.padata", &n);
30 if (res == ASN1_ELEMENT_NOT_FOUND)
31 n = 0;
32 else if (res != ASN1_SUCCESS)
33 return SHISHI_ASN1_ERROR;
35 printf (_("Found %d PA-DATAs...\n"), n);
37 for (i = 1; i <= n; i++)
39 unsigned char patype;
40 int patypelen;
41 ASN1_TYPE apreq;
42 char format[BUFSIZ];
43 char errorDescription[MAX_ERROR_DESCRIPTION_SIZE];
44 char der[BUFSIZ];
45 int derlen;
46 int l;
48 sprintf (format, "KDC-REQ.padata.?%d.padata-type", i);
49 patypelen = sizeof (patype);
50 res = asn1_read_value (req, format, &patype, &patypelen);
51 if (res != ASN1_SUCCESS)
53 fprintf (stdout, libtasn1_strerror (res));
54 return SHISHI_ASN1_ERROR;
57 if (patype == SHISHI_PA_TGS_REQ)
59 sprintf (format, "KDC-REQ.padata.?%d.padata-value", i);
60 derlen = sizeof (der);
61 res = asn1_read_value (req, format, der, &derlen);
62 if (res != ASN1_SUCCESS)
64 fprintf (stdout, libtasn1_strerror (res));
65 return SHISHI_ASN1_ERROR;
68 apreq = shishi_d2a_apreq (handle, der, derlen, errorDescription);
69 if (apreq == ASN1_TYPE_EMPTY)
71 fprintf (stdout, "Could not DER deocde AP-REQ\n");
72 return SHISHI_ASN1_ERROR;
75 if (arg.apreqwritefile)
76 shishi_apreq_to_file (handle, apreq,
77 arg.apreqwritetype, arg.apreqwritefile);
79 break;
83 return SHISHI_OK;
86 int
87 kdc_response (Shishi * handle,
88 struct arguments arg,
89 ASN1_TYPE req, ASN1_TYPE rep,
90 Shishi_ticket * oldtkt, Shishi_ticket ** newtkt)
92 ASN1_TYPE kdcreppart = ASN1_TYPE_EMPTY;
93 ASN1_TYPE ticket = ASN1_TYPE_EMPTY;
94 int res;
96 if (arg.keyvalue && arg.algorithm)
98 unsigned char buf[BUFSIZ];
99 int keylen;
100 int keytype;
101 Shishi_key *key;
103 res = shishi_key_from_base64 (handle, arg.algorithm, arg.keyvalue, &key);
104 if (res != SHISHI_OK)
106 fprintf (stderr, _("Could not create key: %s\n"),
107 shishi_strerror (res));
108 return res;
111 res = shishi_kdc_process (handle, req, rep, key,
112 oldtkt ? 3 : 8, &kdcreppart);
114 else if (oldtkt)
115 res = shishi_tgs_process (handle, req, rep,
116 shishi_ticket_enckdcreppart (oldtkt),
117 &kdcreppart);
118 else if (arg.password)
119 res = shishi_as_process (handle, req, rep, arg.password, &kdcreppart);
120 else if (isatty (fileno (stdin)))
122 char user[BUFSIZ];
123 int userlen;
124 char password[BUFSIZ];
126 userlen = sizeof (user);
127 shishi_asreq_cnamerealm_get (handle, req, user, &userlen);
128 user[userlen] = '\0';
130 res = shishi_prompt_password (handle, stdin, password, BUFSIZ,
131 stdout, "Enter password for `%s': ",
132 user);
134 if (res == SHISHI_OK)
135 res = shishi_as_process (handle, req, rep, password, &kdcreppart);
137 else
139 fprintf (stderr, "Unable to locate key. Do a TGS request, use "
140 "--string-to-key for AS\nrequests, or specify the raw key "
141 "using --keyvalue and --algorithm.\n");
142 return 1;
145 if (res != SHISHI_OK)
147 fprintf (stderr, _("AS process failed: %s\n%s"), shishi_strerror (res),
148 shishi_strerror_details (handle));
149 return res;
152 res = shishi_kdcrep_get_ticket (handle, rep, &ticket);
153 if (res != SHISHI_OK)
155 shishi_error_printf (handle, "Could not extract ticket from AS-REP: %s",
156 shishi_strerror_details (handle));
157 return res;
160 *newtkt = shishi_ticket (handle, "jas@JOSEFSSON.ORG", ticket, kdcreppart);
161 if (*newtkt == NULL)
163 printf ("Could not create ticket\n");
164 return SHISHI_MALLOC_ERROR;
167 return SHISHI_OK;
171 kdc (Shishi * handle, struct arguments arg)
173 ASN1_TYPE req = ASN1_TYPE_EMPTY;
174 ASN1_TYPE rep = ASN1_TYPE_EMPTY;
175 Shishi_ticket *oldtkt;
176 Shishi_ticket *newtkt;
177 int res;
178 Shishi_as *as;
180 if (arg.cname == NULL)
181 arg.cname = shishi_principal_default (handle);
183 if (arg.realm == NULL)
184 arg.realm = shishi_realm_default (handle);
186 if (arg.sname == NULL)
188 int len = strlen ("krbtgt/") + strlen (arg.realm) + 1;
189 arg.sname = malloc (len);
190 if (arg.sname == NULL)
191 return SHISHI_MALLOC_ERROR;
192 sprintf (arg.sname, "krbtgt/%s", arg.realm);
195 if (arg.tgtname == NULL)
197 int len = strlen ("krbtgt/") + strlen (arg.realm) + 1;
198 arg.tgtname = malloc (len);
199 if (arg.tgtname == NULL)
200 return SHISHI_MALLOC_ERROR;
201 sprintf (arg.tgtname, "krbtgt/%s", arg.realm);
204 if (arg.verbose)
206 printf ("Client name: `%s'\n", arg.cname);
207 printf ("Realm: `%s'\n", arg.realm);
208 printf ("Ticket granter: `%s'\n", arg.tgtname);
209 printf ("Service name: `%s'\n", arg.sname);
212 if (!arg.request_p && !arg.sendrecv_p && !arg.response_p)
214 arg.request_p = 1;
215 arg.sendrecv_p = 1;
216 arg.response_p = 1;
219 if (arg.forceas_p)
221 if (!arg.silent)
222 printf (_("Forcing AS mode...\n"));
223 oldtkt = NULL;
225 else
227 oldtkt = shishi_ticketset_find_for_clientserver (handle,
228 NULL,
229 arg.cname,
230 arg.tgtname);
231 if (arg.forcetgs_p && oldtkt == NULL)
233 printf ("Could not find ticket for TGS\n");
234 return 1;
237 if (!arg.silent)
238 if (oldtkt)
240 fprintf (stderr, "Found ticket, doing TGS...\n");
241 if (arg.verbose)
242 shishi_ticket_print (oldtkt, stdout);
244 else
245 fprintf (stderr, "No usable ticket, doing AS...\n");
248 /* Get request */
250 if (!arg.silent)
251 printf ("Generating KDC-REQ...\n");
253 if (arg.kdcreqreadfile)
255 res = shishi_kdcreq_from_file (handle, &req,
256 arg.kdcreqreadtype, arg.kdcreqreadfile);
257 if (res != SHISHI_OK)
259 printf ("Could not read KDC-REQ: %s", shishi_strerror (res));
260 return res;
263 if (arg.apreqwritefile)
264 kdc_write_apreq (handle, arg, req);
266 else if (arg.request_p)
268 if (oldtkt == NULL)
269 req = shishi_asreq_rsc (handle, arg.realm, arg.sname, arg.cname);
270 else
271 req = shishi_tgsreq_rst (handle, arg.realm, arg.sname, oldtkt);
273 if (req == ASN1_TYPE_EMPTY)
275 printf ("Could not generate KDC-REQ: %s",
276 shishi_strerror_details (handle));
277 return 1;
280 if (oldtkt)
282 if (arg.verbose)
283 shishi_authenticator_print (handle, stdout,
284 shishi_last_authenticator (handle));
286 if (arg.authenticatorwritefile)
287 shishi_authenticator_to_file (handle,
288 shishi_last_authenticator (handle),
289 arg.authenticatorwritetype,
290 arg.authenticatorwritefile);
292 if (arg.verbose)
293 shishi_apreq_print (handle, stdout, shishi_last_apreq (handle));
295 if (arg.apreqwritefile)
296 shishi_apreq_to_file (handle, shishi_last_apreq (handle),
297 arg.apreqwritetype, arg.apreqwritefile);
300 if (!arg.sendrecv_p && !arg.response_p)
301 return 0;
303 else if (arg.sendrecv_p || arg.response_p)
305 fprintf
306 (stderr,
307 _("Request required, use --request or --read-kdc-request-file\n"));
308 return 1;
311 if (arg.verbose)
312 shishi_kdcreq_print (handle, stdout, req);
314 if (arg.kdcreqwritefile)
315 shishi_kdcreq_to_file (handle, req,
316 arg.kdcreqwritetype, arg.kdcreqwritefile);
318 if (!arg.silent)
319 printf ("Generating KDC-REQ...done\n");
321 /* Get response for request */
323 if (!arg.silent)
324 printf ("Sending KDC-REQ and receiving KDC-REP...\n");
326 if (arg.kdcrepreadfile)
328 res = shishi_kdcrep_from_file (handle, &rep,
329 arg.kdcrepreadtype, arg.kdcrepreadfile);
330 if (res != SHISHI_OK)
331 return res;
333 else if (arg.sendrecv_p)
335 res = shishi_kdcreq_sendrecv (handle, req, &rep);
336 if (res != SHISHI_OK)
338 printf ("Could not send to KDC: %s\n", shishi_strerror (res));
339 return res;
342 if (!arg.response_p)
343 return 0;
345 else if (arg.response_p)
347 fprintf (stderr,
348 _("Response required, use --sendrecv or --response-file\n"));
349 return 1;
352 if (arg.verbose)
353 shishi_kdcrep_print (handle, stdout, rep);
355 if (arg.kdcrepwritefile)
356 shishi_kdcrep_to_file (handle, rep,
357 arg.kdcrepwritetype, arg.kdcrepwritefile);
359 if (!arg.silent)
360 printf ("Sending KDC-REQ and receiving KDC-REP...done\n");
362 /* Process request and response */
364 if (!arg.silent)
365 printf ("Processing KDC-REP...\n");
367 if (arg.response_p)
369 res = kdc_response (handle, arg, req, rep, oldtkt, &newtkt);
370 if (res != 0)
371 return res;
374 if (!arg.silent)
375 printf ("Processing KDC-REP...done\n");
377 /* Add new ticket */
379 if (!arg.silent)
380 printf ("Adding new ticket...\n");
382 res = shishi_ticketset_add (handle, NULL, newtkt);
383 if (res != SHISHI_OK)
385 printf ("Could not add ticket: %s", shishi_strerror (res));
386 return res;
389 if (!arg.silent)
390 shishi_ticket_print (newtkt, stdout);
392 if (!arg.silent)
393 printf ("Adding new ticket...done\n");
395 return SHISHI_OK;