xref: /netbsd-src/crypto/external/bsd/openssh/dist/gss-serv-krb5.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /*	$NetBSD: gss-serv-krb5.c,v 1.10 2017/04/18 18:41:46 christos Exp $	*/
2 /* $OpenBSD: gss-serv-krb5.c,v 1.8 2013/07/20 01:55:13 djm Exp $ */
3 
4 /*
5  * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include "includes.h"
29 __RCSID("$NetBSD: gss-serv-krb5.c,v 1.10 2017/04/18 18:41:46 christos Exp $");
30 #ifdef GSSAPI
31 #ifdef KRB5
32 
33 #include <sys/types.h>
34 
35 #include <stdarg.h>
36 #include <string.h>
37 
38 #include "xmalloc.h"
39 #include "key.h"
40 #include "hostfile.h"
41 #include "auth.h"
42 #include "log.h"
43 
44 #include "buffer.h"
45 #include "misc.h"
46 #include "servconf.h"
47 #include "ssh-gss.h"
48 
49 extern ServerOptions options;
50 
51 #include <krb5.h>
52 #include <gssapi/gssapi_krb5.h>
53 
54 static krb5_context krb_context = NULL;
55 
56 /* Initialise the krb5 library, for the stuff that GSSAPI won't do */
57 
58 static int
59 ssh_gssapi_krb5_init(void)
60 {
61 	krb5_error_code problem;
62 
63 	if (krb_context != NULL)
64 		return 1;
65 
66 	problem = krb5_init_context(&krb_context);
67 	if (problem) {
68 		logit("Cannot initialize krb5 context");
69 		return 0;
70 	}
71 #ifdef isneeded
72 	krb5_init_ets(krb_context);
73 #endif
74 
75 	return 1;
76 }
77 
78 /* Check if this user is OK to login. This only works with krb5 - other
79  * GSSAPI mechanisms will need their own.
80  * Returns true if the user is OK to log in, otherwise returns 0
81  */
82 
83 static int
84 ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name)
85 {
86 	krb5_principal princ;
87 	int retval;
88 	const char *errmsg;
89 
90 	if (ssh_gssapi_krb5_init() == 0)
91 		return 0;
92 
93 	if ((retval = krb5_parse_name(krb_context, client->exportedname.value,
94 	    &princ))) {
95 		errmsg = krb5_get_error_message(krb_context, retval);
96 		logit("krb5_parse_name(): %.100s", errmsg);
97 		krb5_free_error_message(krb_context, errmsg);
98 		return 0;
99 	}
100 	if (krb5_kuserok(krb_context, princ, name)) {
101 		retval = 1;
102 		logit("Authorized to %s, krb5 principal %s (krb5_kuserok)",
103 		    name, (char *)client->displayname.value);
104 	} else
105 		retval = 0;
106 
107 	krb5_free_principal(krb_context, princ);
108 	return retval;
109 }
110 
111 
112 /* This writes out any forwarded credentials from the structure populated
113  * during userauth. Called after we have setuid to the user */
114 
115 static void
116 ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client)
117 {
118 	krb5_ccache ccache;
119 	krb5_error_code problem;
120 	krb5_principal princ;
121 	OM_uint32 maj_status, min_status;
122 	size_t len;
123 	const char *errmsg;
124 
125 	if (client->creds == NULL) {
126 		debug("No credentials stored");
127 		return;
128 	}
129 
130 	if (ssh_gssapi_krb5_init() == 0)
131 		return;
132 
133 	if ((problem = krb5_cc_new_unique(krb_context, krb5_fcc_ops.prefix,
134 	    NULL, &ccache)) != 0) {
135 		errmsg = krb5_get_error_message(krb_context, problem);
136 		logit("krb5_cc_new_unique(): %.100s", errmsg);
137 		krb5_free_error_message(krb_context, errmsg);
138 		return;
139 	}
140 
141 	if ((problem = krb5_parse_name(krb_context,
142 	    client->exportedname.value, &princ))) {
143 		errmsg = krb5_get_error_message(krb_context, problem);
144 		logit("krb5_parse_name(): %.100s", errmsg);
145 		krb5_free_error_message(krb_context, errmsg);
146 		krb5_cc_destroy(krb_context, ccache);
147 		return;
148 	}
149 
150 	if ((problem = krb5_cc_initialize(krb_context, ccache, princ))) {
151 		errmsg = krb5_get_error_message(krb_context, problem);
152 		logit("krb5_cc_initialize(): %.100s", errmsg);
153 		krb5_free_error_message(krb_context, errmsg);
154 		krb5_free_principal(krb_context, princ);
155 		krb5_cc_destroy(krb_context, ccache);
156 		return;
157 	}
158 
159 	krb5_free_principal(krb_context, princ);
160 
161 	if ((maj_status = gss_krb5_copy_ccache(&min_status,
162 	    client->creds, ccache))) {
163 		logit("gss_krb5_copy_ccache() failed");
164 		krb5_cc_destroy(krb_context, ccache);
165 		return;
166 	}
167 
168 	client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache));
169 	client->store.envvar = __UNCONST("KRB5CCNAME");
170 	len = strlen(client->store.filename) + 6;
171 	client->store.envval = xmalloc(len);
172 	snprintf(client->store.envval, len, "FILE:%s", client->store.filename);
173 
174 #ifdef USE_PAM
175 	if (options.use_pam)
176 		do_pam_putenv(client->store.envvar, client->store.envval);
177 #endif
178 
179 	krb5_cc_close(krb_context, ccache);
180 
181 	return;
182 }
183 
184 ssh_gssapi_mech gssapi_kerberos_mech = {
185 	"toWM5Slw5Ew8Mqkay+al2g==",
186 	"Kerberos",
187 	{9, __UNCONST("\x2A\x86\x48\x86\xF7\x12\x01\x02\x02")},
188 	NULL,
189 	&ssh_gssapi_krb5_userok,
190 	NULL,
191 	&ssh_gssapi_krb5_storecreds
192 };
193 
194 #endif /* KRB5 */
195 
196 #endif /* GSSAPI */
197