Annotation of src/usr.bin/ssh/auth-krb5.c, Revision 1.8
1.1 dugsong 1: /*
2: * Kerberos v5 authentication and ticket-passing routines.
1.8 ! markus 3: *
1.1 dugsong 4: * $FreeBSD: src/crypto/openssh/auth-krb5.c,v 1.6 2001/02/13 16:58:04 assar Exp $
5: */
1.7 stevesk 6: /*
7: * Copyright (c) 2002 Daniel Kouril. All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: *
18: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28: */
1.1 dugsong 29:
30: #include "includes.h"
1.8 ! markus 31: RCSID("$OpenBSD: auth-krb5.c,v 1.7 2002/03/16 17:41:25 stevesk Exp $");
1.6 stevesk 32:
1.1 dugsong 33: #include "ssh.h"
34: #include "ssh1.h"
35: #include "packet.h"
36: #include "xmalloc.h"
37: #include "log.h"
38: #include "servconf.h"
39: #include "uidswap.h"
40: #include "auth.h"
41:
42: #ifdef KRB5
43: #include <krb5.h>
44:
45: extern ServerOptions options;
46:
47: static int
48: krb5_init(void *context)
49: {
50: Authctxt *authctxt = (Authctxt *)context;
51: krb5_error_code problem;
52: static int cleanup_registered = 0;
1.3 deraadt 53:
1.1 dugsong 54: if (authctxt->krb5_ctx == NULL) {
55: problem = krb5_init_context(&authctxt->krb5_ctx);
56: if (problem)
57: return (problem);
58: krb5_init_ets(authctxt->krb5_ctx);
59: }
60: if (!cleanup_registered) {
61: fatal_add_cleanup(krb5_cleanup_proc, authctxt);
62: cleanup_registered = 1;
63: }
64: return (0);
65: }
66:
67: /*
68: * Try krb5 authentication. server_user is passed for logging purposes
69: * only, in auth is received ticket, in client is returned principal
70: * from the ticket
71: */
1.3 deraadt 72: int
1.1 dugsong 73: auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client)
74: {
75: krb5_error_code problem;
76: krb5_principal server;
77: krb5_data reply;
78: krb5_ticket *ticket;
1.2 dugsong 79: int fd, ret;
80:
81: ret = 0;
1.1 dugsong 82: server = NULL;
83: ticket = NULL;
84: reply.length = 0;
1.3 deraadt 85:
1.1 dugsong 86: problem = krb5_init(authctxt);
1.3 deraadt 87: if (problem)
1.1 dugsong 88: goto err;
1.3 deraadt 89:
1.1 dugsong 90: problem = krb5_auth_con_init(authctxt->krb5_ctx,
91: &authctxt->krb5_auth_ctx);
92: if (problem)
93: goto err;
1.3 deraadt 94:
1.1 dugsong 95: fd = packet_get_connection_in();
96: problem = krb5_auth_con_setaddrs_from_fd(authctxt->krb5_ctx,
97: authctxt->krb5_auth_ctx, &fd);
98: if (problem)
99: goto err;
1.3 deraadt 100:
1.1 dugsong 101: problem = krb5_sname_to_principal(authctxt->krb5_ctx, NULL, NULL ,
102: KRB5_NT_SRV_HST, &server);
103: if (problem)
104: goto err;
1.3 deraadt 105:
1.1 dugsong 106: problem = krb5_rd_req(authctxt->krb5_ctx, &authctxt->krb5_auth_ctx,
107: auth, server, NULL, NULL, &ticket);
108: if (problem)
109: goto err;
1.3 deraadt 110:
1.1 dugsong 111: problem = krb5_copy_principal(authctxt->krb5_ctx, ticket->client,
112: &authctxt->krb5_user);
113: if (problem)
114: goto err;
1.3 deraadt 115:
1.1 dugsong 116: /* if client wants mutual auth */
117: problem = krb5_mk_rep(authctxt->krb5_ctx, authctxt->krb5_auth_ctx,
118: &reply);
119: if (problem)
120: goto err;
1.3 deraadt 121:
1.1 dugsong 122: /* Check .k5login authorization now. */
123: if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user,
124: authctxt->pw->pw_name))
125: goto err;
1.3 deraadt 126:
1.1 dugsong 127: if (client)
128: krb5_unparse_name(authctxt->krb5_ctx, authctxt->krb5_user,
129: client);
1.3 deraadt 130:
1.1 dugsong 131: packet_start(SSH_SMSG_AUTH_KERBEROS_RESPONSE);
132: packet_put_string((char *) reply.data, reply.length);
133: packet_send();
134: packet_write_wait();
1.2 dugsong 135:
136: ret = 1;
1.1 dugsong 137: err:
138: if (server)
139: krb5_free_principal(authctxt->krb5_ctx, server);
140: if (ticket)
141: krb5_free_ticket(authctxt->krb5_ctx, ticket);
142: if (reply.length)
143: xfree(reply.data);
1.3 deraadt 144:
1.5 markus 145: if (problem) {
146: if (authctxt->krb5_ctx != NULL)
147: debug("Kerberos v5 authentication failed: %s",
148: krb5_get_err_text(authctxt->krb5_ctx, problem));
149: else
150: debug("Kerberos v5 authentication failed: %d",
151: problem);
152: }
1.2 dugsong 153:
154: return (ret);
1.1 dugsong 155: }
156:
157: int
158: auth_krb5_tgt(Authctxt *authctxt, krb5_data *tgt)
159: {
160: krb5_error_code problem;
161: krb5_ccache ccache = NULL;
162: char *pname;
1.3 deraadt 163:
1.1 dugsong 164: if (authctxt->pw == NULL || authctxt->krb5_user == NULL)
165: return (0);
1.3 deraadt 166:
1.1 dugsong 167: temporarily_use_uid(authctxt->pw);
1.3 deraadt 168:
1.1 dugsong 169: problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_fcc_ops, &ccache);
170: if (problem)
171: goto fail;
1.3 deraadt 172:
1.1 dugsong 173: problem = krb5_cc_initialize(authctxt->krb5_ctx, ccache,
174: authctxt->krb5_user);
175: if (problem)
176: goto fail;
1.3 deraadt 177:
1.1 dugsong 178: problem = krb5_rd_cred2(authctxt->krb5_ctx, authctxt->krb5_auth_ctx,
179: ccache, tgt);
180: if (problem)
181: goto fail;
1.3 deraadt 182:
1.1 dugsong 183: authctxt->krb5_fwd_ccache = ccache;
184: ccache = NULL;
1.3 deraadt 185:
1.1 dugsong 186: authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
1.3 deraadt 187:
1.1 dugsong 188: problem = krb5_unparse_name(authctxt->krb5_ctx, authctxt->krb5_user,
189: &pname);
190: if (problem)
191: goto fail;
1.3 deraadt 192:
1.1 dugsong 193: debug("Kerberos v5 TGT accepted (%s)", pname);
1.3 deraadt 194:
1.1 dugsong 195: restore_uid();
1.3 deraadt 196:
1.1 dugsong 197: return (1);
1.3 deraadt 198:
1.1 dugsong 199: fail:
200: if (problem)
201: debug("Kerberos v5 TGT passing failed: %s",
202: krb5_get_err_text(authctxt->krb5_ctx, problem));
203: if (ccache)
204: krb5_cc_destroy(authctxt->krb5_ctx, ccache);
1.3 deraadt 205:
1.1 dugsong 206: restore_uid();
1.3 deraadt 207:
1.1 dugsong 208: return (0);
209: }
210:
211: int
212: auth_krb5_password(Authctxt *authctxt, const char *password)
213: {
214: krb5_error_code problem;
1.3 deraadt 215:
1.1 dugsong 216: if (authctxt->pw == NULL)
217: return (0);
1.3 deraadt 218:
1.1 dugsong 219: temporarily_use_uid(authctxt->pw);
1.3 deraadt 220:
1.1 dugsong 221: problem = krb5_init(authctxt);
222: if (problem)
223: goto out;
1.3 deraadt 224:
1.1 dugsong 225: problem = krb5_parse_name(authctxt->krb5_ctx, authctxt->pw->pw_name,
226: &authctxt->krb5_user);
227: if (problem)
228: goto out;
1.3 deraadt 229:
1.1 dugsong 230: problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_mcc_ops,
231: &authctxt->krb5_fwd_ccache);
232: if (problem)
233: goto out;
1.3 deraadt 234:
1.1 dugsong 235: problem = krb5_cc_initialize(authctxt->krb5_ctx,
236: authctxt->krb5_fwd_ccache, authctxt->krb5_user);
237: if (problem)
238: goto out;
1.3 deraadt 239:
1.4 markus 240: restore_uid();
1.1 dugsong 241: problem = krb5_verify_user(authctxt->krb5_ctx, authctxt->krb5_user,
242: authctxt->krb5_fwd_ccache, password, 1, NULL);
1.4 markus 243: temporarily_use_uid(authctxt->pw);
244:
1.1 dugsong 245: if (problem)
246: goto out;
1.3 deraadt 247:
1.1 dugsong 248: authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
1.3 deraadt 249:
1.1 dugsong 250: out:
251: restore_uid();
1.3 deraadt 252:
1.1 dugsong 253: if (problem) {
1.5 markus 254: if (authctxt->krb5_ctx != NULL)
255: debug("Kerberos password authentication failed: %s",
256: krb5_get_err_text(authctxt->krb5_ctx, problem));
257: else
258: debug("Kerberos password authentication failed: %d",
259: problem);
1.3 deraadt 260:
1.1 dugsong 261: krb5_cleanup_proc(authctxt);
1.3 deraadt 262:
1.1 dugsong 263: if (options.kerberos_or_local_passwd)
264: return (-1);
265: else
266: return (0);
267: }
268: return (1);
269: }
270:
271: void
272: krb5_cleanup_proc(void *context)
273: {
274: Authctxt *authctxt = (Authctxt *)context;
1.3 deraadt 275:
1.1 dugsong 276: debug("krb5_cleanup_proc called");
277: if (authctxt->krb5_fwd_ccache) {
278: krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
279: authctxt->krb5_fwd_ccache = NULL;
280: }
281: if (authctxt->krb5_user) {
282: krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user);
283: authctxt->krb5_user = NULL;
284: }
285: if (authctxt->krb5_auth_ctx) {
286: krb5_auth_con_free(authctxt->krb5_ctx,
287: authctxt->krb5_auth_ctx);
288: authctxt->krb5_auth_ctx = NULL;
289: }
290: if (authctxt->krb5_ctx) {
291: krb5_free_context(authctxt->krb5_ctx);
292: authctxt->krb5_ctx = NULL;
293: }
294: }
295:
296: #endif /* KRB5 */