]> andersk Git - gssapi-openssh.git/blame - openssh/auth-krb5.c
fix error on merge of Simon's latest patch (remove duplicate code)
[gssapi-openssh.git] / openssh / auth-krb5.c
CommitLineData
3c0ef626 1/*
2 * Kerberos v5 authentication and ticket-passing routines.
3 *
4 * $FreeBSD: src/crypto/openssh/auth-krb5.c,v 1.6 2001/02/13 16:58:04 assar Exp $
3c0ef626 5 */
6
7#include "includes.h"
e9702f7d 8RCSID("$OpenBSD: auth-krb5.c,v 1.6 2002/03/04 17:27:39 stevesk Exp $");
9
3c0ef626 10#include "ssh.h"
11#include "ssh1.h"
12#include "packet.h"
13#include "xmalloc.h"
14#include "log.h"
15#include "servconf.h"
16#include "uidswap.h"
17#include "auth.h"
18
19#ifdef KRB5
20#include <krb5.h>
63119dd9 21#ifndef HEIMDAL
22#define krb5_get_err_text(context,code) error_message(code)
23#endif /* !HEIMDAL */
3c0ef626 24
25extern ServerOptions options;
26
27static int
28krb5_init(void *context)
29{
30 Authctxt *authctxt = (Authctxt *)context;
31 krb5_error_code problem;
32 static int cleanup_registered = 0;
e9702f7d 33
3c0ef626 34 if (authctxt->krb5_ctx == NULL) {
35 problem = krb5_init_context(&authctxt->krb5_ctx);
36 if (problem)
37 return (problem);
38 krb5_init_ets(authctxt->krb5_ctx);
39 }
40 if (!cleanup_registered) {
41 fatal_add_cleanup(krb5_cleanup_proc, authctxt);
42 cleanup_registered = 1;
43 }
44 return (0);
45}
46
47/*
48 * Try krb5 authentication. server_user is passed for logging purposes
49 * only, in auth is received ticket, in client is returned principal
50 * from the ticket
51 */
e9702f7d 52int
3c0ef626 53auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client)
54{
55 krb5_error_code problem;
56 krb5_principal server;
57 krb5_data reply;
58 krb5_ticket *ticket;
59 int fd, ret;
60
61 ret = 0;
62 server = NULL;
63 ticket = NULL;
64 reply.length = 0;
e9702f7d 65
3c0ef626 66 problem = krb5_init(authctxt);
e9702f7d 67 if (problem)
3c0ef626 68 goto err;
e9702f7d 69
3c0ef626 70 problem = krb5_auth_con_init(authctxt->krb5_ctx,
71 &authctxt->krb5_auth_ctx);
72 if (problem)
73 goto err;
e9702f7d 74
3c0ef626 75 fd = packet_get_connection_in();
63119dd9 76#ifdef HEIMDAL
3c0ef626 77 problem = krb5_auth_con_setaddrs_from_fd(authctxt->krb5_ctx,
78 authctxt->krb5_auth_ctx, &fd);
63119dd9 79#else
80 problem = krb5_auth_con_genaddrs(authctxt->krb5_ctx,
81 authctxt->krb5_auth_ctx,fd,
82 KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR |
83 KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR);
84#endif
3c0ef626 85 if (problem)
86 goto err;
e9702f7d 87
3c0ef626 88 problem = krb5_sname_to_principal(authctxt->krb5_ctx, NULL, NULL ,
89 KRB5_NT_SRV_HST, &server);
90 if (problem)
91 goto err;
e9702f7d 92
3c0ef626 93 problem = krb5_rd_req(authctxt->krb5_ctx, &authctxt->krb5_auth_ctx,
94 auth, server, NULL, NULL, &ticket);
95 if (problem)
96 goto err;
905081a4 97
98#ifdef HEIMDAL
3c0ef626 99 problem = krb5_copy_principal(authctxt->krb5_ctx, ticket->client,
100 &authctxt->krb5_user);
63119dd9 101#else
905081a4 102 problem = krb5_copy_principal(authctxt->krb5_ctx,
103 ticket->enc_part2->client,
104 &authctxt->krb5_user);
63119dd9 105#endif
3c0ef626 106 if (problem)
107 goto err;
e9702f7d 108
3c0ef626 109 /* if client wants mutual auth */
110 problem = krb5_mk_rep(authctxt->krb5_ctx, authctxt->krb5_auth_ctx,
111 &reply);
112 if (problem)
113 goto err;
e9702f7d 114
3c0ef626 115 /* Check .k5login authorization now. */
116 if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user,
117 authctxt->pw->pw_name))
118 goto err;
e9702f7d 119
3c0ef626 120 if (client)
121 krb5_unparse_name(authctxt->krb5_ctx, authctxt->krb5_user,
122 client);
e9702f7d 123
3c0ef626 124 packet_start(SSH_SMSG_AUTH_KERBEROS_RESPONSE);
125 packet_put_string((char *) reply.data, reply.length);
126 packet_send();
127 packet_write_wait();
128
129 ret = 1;
130 err:
131 if (server)
132 krb5_free_principal(authctxt->krb5_ctx, server);
133 if (ticket)
134 krb5_free_ticket(authctxt->krb5_ctx, ticket);
135 if (reply.length)
136 xfree(reply.data);
e9702f7d 137
138 if (problem) {
139 if (authctxt->krb5_ctx != NULL)
140 debug("Kerberos v5 authentication failed: %s",
141 krb5_get_err_text(authctxt->krb5_ctx, problem));
142 else
143 debug("Kerberos v5 authentication failed: %d",
144 problem);
145 }
3c0ef626 146
147 return (ret);
148}
149
150int
151auth_krb5_tgt(Authctxt *authctxt, krb5_data *tgt)
152{
153 krb5_error_code problem;
154 krb5_ccache ccache = NULL;
155 char *pname;
63119dd9 156 krb5_creds **creds;
905081a4 157
3c0ef626 158 if (authctxt->pw == NULL || authctxt->krb5_user == NULL)
159 return (0);
e9702f7d 160
3c0ef626 161 temporarily_use_uid(authctxt->pw);
905081a4 162
163#ifdef HEIMDAL
3c0ef626 164 problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_fcc_ops, &ccache);
63119dd9 165#else
166{
905081a4 167 char ccname[40];
168 int tmpfd;
63119dd9 169
905081a4 170 snprintf(ccname,sizeof(ccname),"FILE:/tmp/krb5cc_%d_XXXXXX",geteuid());
171
172 if ((tmpfd = mkstemp(ccname))==-1) {
173 log("mkstemp(): %.100s", strerror(errno));
174 problem = errno;
175 goto fail;
176 }
177 if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) {
178 log("fchmod(): %.100s", strerror(errno));
179 close(tmpfd);
180 problem = errno;
181 goto fail;
182 }
183 close(tmpfd);
63119dd9 184 problem = krb5_cc_resolve(authctxt->krb5_ctx, ccname, &ccache);
185}
186#endif
3c0ef626 187 if (problem)
188 goto fail;
e9702f7d 189
3c0ef626 190 problem = krb5_cc_initialize(authctxt->krb5_ctx, ccache,
191 authctxt->krb5_user);
192 if (problem)
193 goto fail;
905081a4 194
195#ifdef HEIMDAL
3c0ef626 196 problem = krb5_rd_cred2(authctxt->krb5_ctx, authctxt->krb5_auth_ctx,
197 ccache, tgt);
198 if (problem)
199 goto fail;
63119dd9 200#else
201 problem = krb5_rd_cred(authctxt->krb5_ctx, authctxt->krb5_auth_ctx,
202 tgt, &creds, NULL);
905081a4 203 if (problem)
63119dd9 204 goto fail;
205 problem = krb5_cc_store_cred(authctxt->krb5_ctx, ccache, *creds);
206 if (problem)
905081a4 207 goto fail;
63119dd9 208#endif
905081a4 209
3c0ef626 210 authctxt->krb5_fwd_ccache = ccache;
211 ccache = NULL;
e9702f7d 212
3c0ef626 213 authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
e9702f7d 214
3c0ef626 215 problem = krb5_unparse_name(authctxt->krb5_ctx, authctxt->krb5_user,
216 &pname);
217 if (problem)
218 goto fail;
e9702f7d 219
3c0ef626 220 debug("Kerberos v5 TGT accepted (%s)", pname);
e9702f7d 221
3c0ef626 222 restore_uid();
e9702f7d 223
3c0ef626 224 return (1);
e9702f7d 225
3c0ef626 226 fail:
227 if (problem)
228 debug("Kerberos v5 TGT passing failed: %s",
229 krb5_get_err_text(authctxt->krb5_ctx, problem));
230 if (ccache)
231 krb5_cc_destroy(authctxt->krb5_ctx, ccache);
e9702f7d 232
3c0ef626 233 restore_uid();
e9702f7d 234
3c0ef626 235 return (0);
236}
237
238int
239auth_krb5_password(Authctxt *authctxt, const char *password)
240{
63119dd9 241#ifndef HEIMDAL
242 krb5_creds creds;
243 krb5_principal server;
244#endif
3c0ef626 245 krb5_error_code problem;
e9702f7d 246
3c0ef626 247 if (authctxt->pw == NULL)
248 return (0);
e9702f7d 249
3c0ef626 250 temporarily_use_uid(authctxt->pw);
e9702f7d 251
3c0ef626 252 problem = krb5_init(authctxt);
253 if (problem)
254 goto out;
e9702f7d 255
3c0ef626 256 problem = krb5_parse_name(authctxt->krb5_ctx, authctxt->pw->pw_name,
257 &authctxt->krb5_user);
258 if (problem)
259 goto out;
905081a4 260
261#ifdef HEIMDAL
3c0ef626 262 problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_mcc_ops,
263 &authctxt->krb5_fwd_ccache);
63119dd9 264#else
905081a4 265 problem = krb5_cc_resolve(authctxt->krb5_ctx, "MEMORY:",
63119dd9 266 &authctxt->krb5_fwd_ccache);
267#endif
3c0ef626 268 if (problem)
269 goto out;
e9702f7d 270
3c0ef626 271 problem = krb5_cc_initialize(authctxt->krb5_ctx,
272 authctxt->krb5_fwd_ccache, authctxt->krb5_user);
273 if (problem)
274 goto out;
905081a4 275
e9702f7d 276 restore_uid();
905081a4 277
278#ifdef HEIMDAL
3c0ef626 279 problem = krb5_verify_user(authctxt->krb5_ctx, authctxt->krb5_user,
280 authctxt->krb5_fwd_ccache, password, 1, NULL);
905081a4 281 if (problem) {
282 temporarily_use_uid(authctxt->pw);
3c0ef626 283 goto out;
905081a4 284 }
63119dd9 285#else
905081a4 286 problem = krb5_get_init_creds_password(authctxt->krb5_ctx, &creds,
287 authctxt->krb5_user, password, NULL, NULL, 0, NULL, NULL);
288 if (problem) {
289 temporarily_use_uid(authctxt->pw);
290 goto out;
291 }
292
293 problem = krb5_sname_to_principal(authctxt->krb5_ctx, NULL, NULL,
294 KRB5_NT_SRV_HST, &server);
295 if (problem) {
296 temporarily_use_uid(authctxt->pw);
297 goto out;
298 }
299
300 problem = krb5_verify_init_creds(authctxt->krb5_ctx, &creds, server,
301 NULL, NULL, NULL);
302
303 krb5_free_principal(authctxt->krb5_ctx, server);
63119dd9 304
63119dd9 305 temporarily_use_uid(authctxt->pw);
905081a4 306 if (problem) {
307 goto out;
308 }
63119dd9 309
905081a4 310 problem= krb5_cc_store_cred(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache,
311 &creds);
312 if (problem) {
313 temporarily_use_uid(authctxt->pw);
314 goto out;
315 }
316#endif
317 temporarily_use_uid(authctxt->pw);
63119dd9 318
905081a4 319 if (problem)
320 goto out;
63119dd9 321
3c0ef626 322 authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
e9702f7d 323
3c0ef626 324 out:
325 restore_uid();
e9702f7d 326
3c0ef626 327 if (problem) {
e9702f7d 328 if (authctxt->krb5_ctx != NULL)
329 debug("Kerberos password authentication failed: %s",
330 krb5_get_err_text(authctxt->krb5_ctx, problem));
331 else
332 debug("Kerberos password authentication failed: %d",
333 problem);
334
3c0ef626 335 krb5_cleanup_proc(authctxt);
e9702f7d 336
3c0ef626 337 if (options.kerberos_or_local_passwd)
338 return (-1);
339 else
340 return (0);
341 }
342 return (1);
343}
344
345void
346krb5_cleanup_proc(void *context)
347{
348 Authctxt *authctxt = (Authctxt *)context;
e9702f7d 349
3c0ef626 350 debug("krb5_cleanup_proc called");
351 if (authctxt->krb5_fwd_ccache) {
352 krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
353 authctxt->krb5_fwd_ccache = NULL;
354 }
355 if (authctxt->krb5_user) {
356 krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user);
357 authctxt->krb5_user = NULL;
358 }
359 if (authctxt->krb5_auth_ctx) {
360 krb5_auth_con_free(authctxt->krb5_ctx,
361 authctxt->krb5_auth_ctx);
362 authctxt->krb5_auth_ctx = NULL;
363 }
364 if (authctxt->krb5_ctx) {
365 krb5_free_context(authctxt->krb5_ctx);
366 authctxt->krb5_ctx = NULL;
367 }
368}
369
370#endif /* KRB5 */
This page took 2.051155 seconds and 5 git commands to generate.