xref: /freebsd/crypto/openssh/auth-krb5.c (revision b15c83408cb1e9b86c1895af0f097de05fc92ccf)
1333ee039SDag-Erling Smørgrav /* $OpenBSD: auth-krb5.c,v 1.19 2006/08/03 03:34:41 deraadt Exp $ */
2fe5fd017SMark Murray /*
3fe5fd017SMark Murray  *    Kerberos v5 authentication and ticket-passing routines.
480628bacSDag-Erling Smørgrav  *
57396b2c4SDag-Erling Smørgrav  * $FreeBSD: src/crypto/openssh/auth-krb5.c,v 1.6 2001/02/13 16:58:04 assar Exp $
680628bacSDag-Erling Smørgrav  */
780628bacSDag-Erling Smørgrav /*
880628bacSDag-Erling Smørgrav  * Copyright (c) 2002 Daniel Kouril.  All rights reserved.
980628bacSDag-Erling Smørgrav  *
1080628bacSDag-Erling Smørgrav  * Redistribution and use in source and binary forms, with or without
1180628bacSDag-Erling Smørgrav  * modification, are permitted provided that the following conditions
1280628bacSDag-Erling Smørgrav  * are met:
1380628bacSDag-Erling Smørgrav  * 1. Redistributions of source code must retain the above copyright
1480628bacSDag-Erling Smørgrav  *    notice, this list of conditions and the following disclaimer.
1580628bacSDag-Erling Smørgrav  * 2. Redistributions in binary form must reproduce the above copyright
1680628bacSDag-Erling Smørgrav  *    notice, this list of conditions and the following disclaimer in the
1780628bacSDag-Erling Smørgrav  *    documentation and/or other materials provided with the distribution.
1880628bacSDag-Erling Smørgrav  *
1980628bacSDag-Erling Smørgrav  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2080628bacSDag-Erling Smørgrav  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2180628bacSDag-Erling Smørgrav  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2280628bacSDag-Erling Smørgrav  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2380628bacSDag-Erling Smørgrav  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2480628bacSDag-Erling Smørgrav  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2580628bacSDag-Erling Smørgrav  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2680628bacSDag-Erling Smørgrav  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2780628bacSDag-Erling Smørgrav  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2880628bacSDag-Erling Smørgrav  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29fe5fd017SMark Murray  */
30fe5fd017SMark Murray 
31fe5fd017SMark Murray #include "includes.h"
32af12a3e7SDag-Erling Smørgrav 
33333ee039SDag-Erling Smørgrav #include <sys/types.h>
34333ee039SDag-Erling Smørgrav #include <pwd.h>
35333ee039SDag-Erling Smørgrav #include <stdarg.h>
36333ee039SDag-Erling Smørgrav 
37333ee039SDag-Erling Smørgrav #include "xmalloc.h"
38fe5fd017SMark Murray #include "ssh.h"
39e7edf5a1SBrian Feldman #include "ssh1.h"
40fe5fd017SMark Murray #include "packet.h"
41af12a3e7SDag-Erling Smørgrav #include "log.h"
42333ee039SDag-Erling Smørgrav #include "buffer.h"
43af12a3e7SDag-Erling Smørgrav #include "servconf.h"
44af12a3e7SDag-Erling Smørgrav #include "uidswap.h"
45333ee039SDag-Erling Smørgrav #include "key.h"
46333ee039SDag-Erling Smørgrav #include "hostfile.h"
47af12a3e7SDag-Erling Smørgrav #include "auth.h"
48fe5fd017SMark Murray 
49fe5fd017SMark Murray #ifdef KRB5
50333ee039SDag-Erling Smørgrav #include <errno.h>
51333ee039SDag-Erling Smørgrav #include <unistd.h>
52333ee039SDag-Erling Smørgrav #include <string.h>
53af12a3e7SDag-Erling Smørgrav #include <krb5.h>
54fe5fd017SMark Murray 
55af12a3e7SDag-Erling Smørgrav extern ServerOptions	 options;
56fe5fd017SMark Murray 
57af12a3e7SDag-Erling Smørgrav static int
58af12a3e7SDag-Erling Smørgrav krb5_init(void *context)
59af12a3e7SDag-Erling Smørgrav {
60af12a3e7SDag-Erling Smørgrav 	Authctxt *authctxt = (Authctxt *)context;
61af12a3e7SDag-Erling Smørgrav 	krb5_error_code problem;
62af12a3e7SDag-Erling Smørgrav 
63af12a3e7SDag-Erling Smørgrav 	if (authctxt->krb5_ctx == NULL) {
64af12a3e7SDag-Erling Smørgrav 		problem = krb5_init_context(&authctxt->krb5_ctx);
65af12a3e7SDag-Erling Smørgrav 		if (problem)
66af12a3e7SDag-Erling Smørgrav 			return (problem);
67af12a3e7SDag-Erling Smørgrav 	}
68af12a3e7SDag-Erling Smørgrav 	return (0);
69af12a3e7SDag-Erling Smørgrav }
70af12a3e7SDag-Erling Smørgrav 
71fe5fd017SMark Murray int
72af12a3e7SDag-Erling Smørgrav auth_krb5_password(Authctxt *authctxt, const char *password)
73fe5fd017SMark Murray {
74989dd127SDag-Erling Smørgrav #ifndef HEIMDAL
75989dd127SDag-Erling Smørgrav 	krb5_creds creds;
76989dd127SDag-Erling Smørgrav 	krb5_principal server;
77989dd127SDag-Erling Smørgrav #endif
78fe5fd017SMark Murray 	krb5_error_code problem;
79cf2b5f3bSDag-Erling Smørgrav 	krb5_ccache ccache = NULL;
805962c0e9SDag-Erling Smørgrav 	int len;
81b15c8340SDag-Erling Smørgrav 	char *client, *platform_client;
82b15c8340SDag-Erling Smørgrav 
83b15c8340SDag-Erling Smørgrav 	/* get platform-specific kerberos client principal name (if it exists) */
84b15c8340SDag-Erling Smørgrav 	platform_client = platform_krb5_get_principal_name(authctxt->pw->pw_name);
85b15c8340SDag-Erling Smørgrav 	client = platform_client ? platform_client : authctxt->pw->pw_name;
86fe5fd017SMark Murray 
87af12a3e7SDag-Erling Smørgrav 	temporarily_use_uid(authctxt->pw);
88af12a3e7SDag-Erling Smørgrav 
89af12a3e7SDag-Erling Smørgrav 	problem = krb5_init(authctxt);
90fe5fd017SMark Murray 	if (problem)
91fe5fd017SMark Murray 		goto out;
92fe5fd017SMark Murray 
93b15c8340SDag-Erling Smørgrav 	problem = krb5_parse_name(authctxt->krb5_ctx, client,
94af12a3e7SDag-Erling Smørgrav 		    &authctxt->krb5_user);
95af12a3e7SDag-Erling Smørgrav 	if (problem)
96fe5fd017SMark Murray 		goto out;
97fe5fd017SMark Murray 
98989dd127SDag-Erling Smørgrav #ifdef HEIMDAL
99cf2b5f3bSDag-Erling Smørgrav 	problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_mcc_ops, &ccache);
100af12a3e7SDag-Erling Smørgrav 	if (problem)
101fe5fd017SMark Murray 		goto out;
102fe5fd017SMark Murray 
103cf2b5f3bSDag-Erling Smørgrav 	problem = krb5_cc_initialize(authctxt->krb5_ctx, ccache,
104cf2b5f3bSDag-Erling Smørgrav 		authctxt->krb5_user);
105af12a3e7SDag-Erling Smørgrav 	if (problem)
106fe5fd017SMark Murray 		goto out;
107fe5fd017SMark Murray 
108af12a3e7SDag-Erling Smørgrav 	restore_uid();
109cf2b5f3bSDag-Erling Smørgrav 
110af12a3e7SDag-Erling Smørgrav 	problem = krb5_verify_user(authctxt->krb5_ctx, authctxt->krb5_user,
111cf2b5f3bSDag-Erling Smørgrav 	    ccache, password, 1, NULL);
112cf2b5f3bSDag-Erling Smørgrav 
113af12a3e7SDag-Erling Smørgrav 	temporarily_use_uid(authctxt->pw);
114af12a3e7SDag-Erling Smørgrav 
115af12a3e7SDag-Erling Smørgrav 	if (problem)
116fe5fd017SMark Murray 		goto out;
1171ec0d754SDag-Erling Smørgrav 
118cf2b5f3bSDag-Erling Smørgrav 	problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_fcc_ops,
119cf2b5f3bSDag-Erling Smørgrav 	    &authctxt->krb5_fwd_ccache);
120cf2b5f3bSDag-Erling Smørgrav 	if (problem)
121cf2b5f3bSDag-Erling Smørgrav 		goto out;
122cf2b5f3bSDag-Erling Smørgrav 
123cf2b5f3bSDag-Erling Smørgrav 	problem = krb5_cc_copy_cache(authctxt->krb5_ctx, ccache,
124cf2b5f3bSDag-Erling Smørgrav 	    authctxt->krb5_fwd_ccache);
125cf2b5f3bSDag-Erling Smørgrav 	krb5_cc_destroy(authctxt->krb5_ctx, ccache);
126cf2b5f3bSDag-Erling Smørgrav 	ccache = NULL;
127cf2b5f3bSDag-Erling Smørgrav 	if (problem)
128cf2b5f3bSDag-Erling Smørgrav 		goto out;
129fe5fd017SMark Murray 
130989dd127SDag-Erling Smørgrav #else
131989dd127SDag-Erling Smørgrav 	problem = krb5_get_init_creds_password(authctxt->krb5_ctx, &creds,
132989dd127SDag-Erling Smørgrav 	    authctxt->krb5_user, (char *)password, NULL, NULL, 0, NULL, NULL);
133989dd127SDag-Erling Smørgrav 	if (problem)
134989dd127SDag-Erling Smørgrav 		goto out;
135989dd127SDag-Erling Smørgrav 
136989dd127SDag-Erling Smørgrav 	problem = krb5_sname_to_principal(authctxt->krb5_ctx, NULL, NULL,
137989dd127SDag-Erling Smørgrav 	    KRB5_NT_SRV_HST, &server);
138989dd127SDag-Erling Smørgrav 	if (problem)
139989dd127SDag-Erling Smørgrav 		goto out;
140989dd127SDag-Erling Smørgrav 
141989dd127SDag-Erling Smørgrav 	restore_uid();
142989dd127SDag-Erling Smørgrav 	problem = krb5_verify_init_creds(authctxt->krb5_ctx, &creds, server,
143989dd127SDag-Erling Smørgrav 	    NULL, NULL, NULL);
144989dd127SDag-Erling Smørgrav 	krb5_free_principal(authctxt->krb5_ctx, server);
145989dd127SDag-Erling Smørgrav 	temporarily_use_uid(authctxt->pw);
146989dd127SDag-Erling Smørgrav 	if (problem)
147989dd127SDag-Erling Smørgrav 		goto out;
148989dd127SDag-Erling Smørgrav 
149b15c8340SDag-Erling Smørgrav 	if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user, client)) {
150989dd127SDag-Erling Smørgrav 		problem = -1;
151989dd127SDag-Erling Smørgrav 		goto out;
152989dd127SDag-Erling Smørgrav 	}
153989dd127SDag-Erling Smørgrav 
154d4ecd108SDag-Erling Smørgrav 	problem = ssh_krb5_cc_gen(authctxt->krb5_ctx, &authctxt->krb5_fwd_ccache);
155989dd127SDag-Erling Smørgrav 	if (problem)
156989dd127SDag-Erling Smørgrav 		goto out;
157989dd127SDag-Erling Smørgrav 
158989dd127SDag-Erling Smørgrav 	problem = krb5_cc_initialize(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache,
159989dd127SDag-Erling Smørgrav 				     authctxt->krb5_user);
160989dd127SDag-Erling Smørgrav 	if (problem)
161989dd127SDag-Erling Smørgrav 		goto out;
162989dd127SDag-Erling Smørgrav 
163989dd127SDag-Erling Smørgrav 	problem= krb5_cc_store_cred(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache,
164989dd127SDag-Erling Smørgrav 				 &creds);
165989dd127SDag-Erling Smørgrav 	if (problem)
166989dd127SDag-Erling Smørgrav 		goto out;
167989dd127SDag-Erling Smørgrav #endif
168989dd127SDag-Erling Smørgrav 
169af12a3e7SDag-Erling Smørgrav 	authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
170af12a3e7SDag-Erling Smørgrav 
1715962c0e9SDag-Erling Smørgrav 	len = strlen(authctxt->krb5_ticket_file) + 6;
1725962c0e9SDag-Erling Smørgrav 	authctxt->krb5_ccname = xmalloc(len);
1735962c0e9SDag-Erling Smørgrav 	snprintf(authctxt->krb5_ccname, len, "FILE:%s",
1745962c0e9SDag-Erling Smørgrav 	    authctxt->krb5_ticket_file);
1755962c0e9SDag-Erling Smørgrav 
176aa49c926SDag-Erling Smørgrav #ifdef USE_PAM
177aa49c926SDag-Erling Smørgrav 	if (options.use_pam)
178aa49c926SDag-Erling Smørgrav 		do_pam_putenv("KRB5CCNAME", authctxt->krb5_ccname);
179aa49c926SDag-Erling Smørgrav #endif
180aa49c926SDag-Erling Smørgrav 
181fe5fd017SMark Murray  out:
182af12a3e7SDag-Erling Smørgrav 	restore_uid();
183af12a3e7SDag-Erling Smørgrav 
184b15c8340SDag-Erling Smørgrav 	if (platform_client != NULL)
185b15c8340SDag-Erling Smørgrav 		xfree(platform_client);
186b15c8340SDag-Erling Smørgrav 
187af12a3e7SDag-Erling Smørgrav 	if (problem) {
188cf2b5f3bSDag-Erling Smørgrav 		if (ccache)
189cf2b5f3bSDag-Erling Smørgrav 			krb5_cc_destroy(authctxt->krb5_ctx, ccache);
190cf2b5f3bSDag-Erling Smørgrav 
191989dd127SDag-Erling Smørgrav 		if (authctxt->krb5_ctx != NULL && problem!=-1)
192af12a3e7SDag-Erling Smørgrav 			debug("Kerberos password authentication failed: %s",
193af12a3e7SDag-Erling Smørgrav 			    krb5_get_err_text(authctxt->krb5_ctx, problem));
194af12a3e7SDag-Erling Smørgrav 		else
195af12a3e7SDag-Erling Smørgrav 			debug("Kerberos password authentication failed: %d",
196af12a3e7SDag-Erling Smørgrav 			    problem);
197af12a3e7SDag-Erling Smørgrav 
198af12a3e7SDag-Erling Smørgrav 		krb5_cleanup_proc(authctxt);
199af12a3e7SDag-Erling Smørgrav 
200af12a3e7SDag-Erling Smørgrav 		if (options.kerberos_or_local_passwd)
201af12a3e7SDag-Erling Smørgrav 			return (-1);
202af12a3e7SDag-Erling Smørgrav 		else
203af12a3e7SDag-Erling Smørgrav 			return (0);
204af12a3e7SDag-Erling Smørgrav 	}
205b74df5b2SDag-Erling Smørgrav 	return (authctxt->valid ? 1 : 0);
206fe5fd017SMark Murray }
207fe5fd017SMark Murray 
208fe5fd017SMark Murray void
2091ec0d754SDag-Erling Smørgrav krb5_cleanup_proc(Authctxt *authctxt)
210fe5fd017SMark Murray {
211af12a3e7SDag-Erling Smørgrav 	debug("krb5_cleanup_proc called");
212af12a3e7SDag-Erling Smørgrav 	if (authctxt->krb5_fwd_ccache) {
213af12a3e7SDag-Erling Smørgrav 		krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
214af12a3e7SDag-Erling Smørgrav 		authctxt->krb5_fwd_ccache = NULL;
215fe5fd017SMark Murray 	}
216af12a3e7SDag-Erling Smørgrav 	if (authctxt->krb5_user) {
217af12a3e7SDag-Erling Smørgrav 		krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user);
218af12a3e7SDag-Erling Smørgrav 		authctxt->krb5_user = NULL;
219fe5fd017SMark Murray 	}
220af12a3e7SDag-Erling Smørgrav 	if (authctxt->krb5_ctx) {
221af12a3e7SDag-Erling Smørgrav 		krb5_free_context(authctxt->krb5_ctx);
222af12a3e7SDag-Erling Smørgrav 		authctxt->krb5_ctx = NULL;
223af12a3e7SDag-Erling Smørgrav 	}
224fe5fd017SMark Murray }
225fe5fd017SMark Murray 
226d4ecd108SDag-Erling Smørgrav #ifndef HEIMDAL
227d4ecd108SDag-Erling Smørgrav krb5_error_code
228d4ecd108SDag-Erling Smørgrav ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
229d4ecd108SDag-Erling Smørgrav 	int tmpfd, ret;
230d4ecd108SDag-Erling Smørgrav 	char ccname[40];
231d4ecd108SDag-Erling Smørgrav 	mode_t old_umask;
232d4ecd108SDag-Erling Smørgrav 
233d4ecd108SDag-Erling Smørgrav 	ret = snprintf(ccname, sizeof(ccname),
234d4ecd108SDag-Erling Smørgrav 	    "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid());
235b74df5b2SDag-Erling Smørgrav 	if (ret < 0 || (size_t)ret >= sizeof(ccname))
236d4ecd108SDag-Erling Smørgrav 		return ENOMEM;
237d4ecd108SDag-Erling Smørgrav 
238d4ecd108SDag-Erling Smørgrav 	old_umask = umask(0177);
239d4ecd108SDag-Erling Smørgrav 	tmpfd = mkstemp(ccname + strlen("FILE:"));
240d4ecd108SDag-Erling Smørgrav 	umask(old_umask);
241d4ecd108SDag-Erling Smørgrav 	if (tmpfd == -1) {
242d4ecd108SDag-Erling Smørgrav 		logit("mkstemp(): %.100s", strerror(errno));
243d4ecd108SDag-Erling Smørgrav 		return errno;
244d4ecd108SDag-Erling Smørgrav 	}
245d4ecd108SDag-Erling Smørgrav 
246d4ecd108SDag-Erling Smørgrav 	if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) {
247d4ecd108SDag-Erling Smørgrav 		logit("fchmod(): %.100s", strerror(errno));
248d4ecd108SDag-Erling Smørgrav 		close(tmpfd);
249d4ecd108SDag-Erling Smørgrav 		return errno;
250d4ecd108SDag-Erling Smørgrav 	}
251d4ecd108SDag-Erling Smørgrav 	close(tmpfd);
252d4ecd108SDag-Erling Smørgrav 
253d4ecd108SDag-Erling Smørgrav 	return (krb5_cc_resolve(ctx, ccname, ccache));
254d4ecd108SDag-Erling Smørgrav }
255d4ecd108SDag-Erling Smørgrav #endif /* !HEIMDAL */
256fe5fd017SMark Murray #endif /* KRB5 */
257