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
25 kdc_write_apreq (Shishi
* handle
, struct arguments arg
, ASN1_TYPE req
)
29 res
= asn1_number_of_elements (req
, "KDC-REQ.padata", &n
);
30 if (res
== ASN1_ELEMENT_NOT_FOUND
)
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
++)
43 char errorDescription
[MAX_ERROR_DESCRIPTION_SIZE
];
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
);
87 kdc_response (Shishi
* handle
,
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
;
96 if (arg
.keyvalue
&& arg
.algorithm
)
98 unsigned char buf
[BUFSIZ
];
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
));
111 res
= shishi_kdc_process (handle
, req
, rep
, key
,
112 oldtkt
? 3 : 8, &kdcreppart
);
115 res
= shishi_tgs_process (handle
, req
, rep
,
116 shishi_ticket_enckdcreppart (oldtkt
),
118 else if (arg
.password
)
119 res
= shishi_as_process (handle
, req
, rep
, arg
.password
, &kdcreppart
);
120 else if (isatty (fileno (stdin
)))
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': ",
134 if (res
== SHISHI_OK
)
135 res
= shishi_as_process (handle
, req
, rep
, password
, &kdcreppart
);
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");
145 if (res
!= SHISHI_OK
)
147 fprintf (stderr
, _("AS process failed: %s\n%s"), shishi_strerror (res
),
148 shishi_strerror_details (handle
));
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
));
160 *newtkt
= shishi_ticket (handle
, "jas@JOSEFSSON.ORG", ticket
, kdcreppart
);
163 printf ("Could not create ticket\n");
164 return SHISHI_MALLOC_ERROR
;
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
;
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
);
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
)
222 printf (_("Forcing AS mode...\n"));
227 oldtkt
= shishi_ticketset_find_for_clientserver (handle
,
231 if (arg
.forcetgs_p
&& oldtkt
== NULL
)
233 printf ("Could not find ticket for TGS\n");
240 fprintf (stderr
, "Found ticket, doing TGS...\n");
242 shishi_ticket_print (oldtkt
, stdout
);
245 fprintf (stderr
, "No usable ticket, doing AS...\n");
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
));
263 if (arg
.apreqwritefile
)
264 kdc_write_apreq (handle
, arg
, req
);
266 else if (arg
.request_p
)
269 req
= shishi_asreq_rsc (handle
, arg
.realm
, arg
.sname
, arg
.cname
);
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
));
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
);
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
)
303 else if (arg
.sendrecv_p
|| arg
.response_p
)
307 _("Request required, use --request or --read-kdc-request-file\n"));
312 shishi_kdcreq_print (handle
, stdout
, req
);
314 if (arg
.kdcreqwritefile
)
315 shishi_kdcreq_to_file (handle
, req
,
316 arg
.kdcreqwritetype
, arg
.kdcreqwritefile
);
319 printf ("Generating KDC-REQ...done\n");
321 /* Get response for request */
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
)
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
));
345 else if (arg
.response_p
)
348 _("Response required, use --sendrecv or --response-file\n"));
353 shishi_kdcrep_print (handle
, stdout
, rep
);
355 if (arg
.kdcrepwritefile
)
356 shishi_kdcrep_to_file (handle
, rep
,
357 arg
.kdcrepwritetype
, arg
.kdcrepwritefile
);
360 printf ("Sending KDC-REQ and receiving KDC-REP...done\n");
362 /* Process request and response */
365 printf ("Processing KDC-REP...\n");
369 res
= kdc_response (handle
, arg
, req
, rep
, oldtkt
, &newtkt
);
375 printf ("Processing KDC-REP...done\n");
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
));
390 shishi_ticket_print (newtkt
, stdout
);
393 printf ("Adding new ticket...done\n");