]> andersk Git - gssapi-openssh.git/blob - openssh/gss-serv-krb5.c
11 Apr 2003 patch from Simon
[gssapi-openssh.git] / openssh / gss-serv-krb5.c
1 /*
2  * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #include "includes.h"
26
27 #ifdef GSSAPI
28 #ifdef KRB5
29
30 #include "auth.h"
31 #include "auth-pam.h"
32 #include "xmalloc.h"
33 #include "log.h"
34 #include "servconf.h"
35
36 #include "ssh-gss.h"
37
38 extern ServerOptions options;
39
40 #ifdef HEIMDAL
41 #include <krb5.h>
42 #else
43 #include <gssapi_krb5.h>
44 #define krb5_get_err_text(context,code) error_message(code)
45 #endif
46
47 static krb5_context krb_context = NULL;
48
49 /* Initialise the krb5 library, so we can use it for those bits that
50  * GSSAPI won't do */
51
52 static int 
53 ssh_gssapi_krb5_init() {
54         krb5_error_code problem;
55         
56         if (krb_context !=NULL)
57                 return 1;
58                 
59         problem = krb5_init_context(&krb_context);
60         if (problem) {
61                 log("Cannot initialize krb5 context");
62                 return 0;
63         }
64         krb5_init_ets(krb_context);
65
66         return 1;       
67 }                       
68
69 /* Check if this user is OK to login. This only works with krb5 - other 
70  * GSSAPI mechanisms will need their own.
71  * Returns true if the user is OK to log in, otherwise returns 0
72  */
73
74 static int
75 ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name) {
76         krb5_principal princ;
77         int retval;
78
79         if (ssh_gssapi_krb5_init() == 0)
80                 return 0;
81                 
82         if ((retval=krb5_parse_name(krb_context, client->name.value, 
83                                     &princ))) {
84                 log("krb5_parse_name(): %.100s", 
85                         krb5_get_err_text(krb_context,retval));
86                 return 0;
87         }
88         if (krb5_kuserok(krb_context, princ, name)) {
89                 retval = 1;
90                 log("Authorized to %s, krb5 principal %s (krb5_kuserok)",name,
91                     (char *)client->name.value);
92         }
93         else
94                 retval = 0;
95         
96         krb5_free_principal(krb_context, princ);
97         return retval;
98 }
99
100 /* Retrieve the local username associated with a set of Kerberos 
101  * credentials. Hopefully we can use this for the 'empty' username
102  * logins discussed in the draft  */
103 static int
104 ssh_gssapi_krb5_localname(ssh_gssapi_client *client, char **user) {
105         krb5_principal princ;
106         int retval;
107         
108         if (ssh_gssapi_krb5_init() == 0)
109                 return 0;
110
111         if ((retval=krb5_parse_name(krb_context, client->name.value, 
112                                     &princ))) {
113                 log("krb5_parse_name(): %.100s", 
114                         krb5_get_err_text(krb_context,retval));
115                 return 0;
116         }
117         
118         /* We've got to return a malloc'd string */
119         *user = (char *)xmalloc(256);
120         if (krb5_aname_to_localname(krb_context, princ, 256, *user)) {
121                 xfree(*user);
122                 *user = NULL;
123                 return(0);
124         }
125         
126         return(1);
127 }
128         
129 /* Make sure that this is called _after_ we've setuid to the user */
130
131 /* This writes out any forwarded credentials. Its specific to the Kerberos
132  * GSSAPI mechanism
133  *
134  * We assume that our caller has made sure that the user has selected
135  * delegated credentials, and that the client_creds structure is correctly
136  * populated.
137  */
138
139 static void
140 ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) {
141         krb5_ccache ccache;
142         krb5_error_code problem;
143         krb5_principal princ;
144         char ccname[35];
145         static char name[40];
146         int tmpfd;
147         OM_uint32 maj_status,min_status;
148
149         if (client->creds==NULL) {
150                 debug("No credentials stored"); 
151                 return;
152         }
153                 
154         if (ssh_gssapi_krb5_init() == 0)
155                 return;
156
157         if (options.gss_use_session_ccache) {
158                 snprintf(ccname,sizeof(ccname),"/tmp/krb5cc_%d_XXXXXX",geteuid());
159        
160                 if ((tmpfd = mkstemp(ccname))==-1) {
161                         log("mkstemp(): %.100s", strerror(errno));
162                         return;
163                 }
164                 if (fchmod(tmpfd, S_IRUSR | S_IWUSR) == -1) {
165                         log("fchmod(): %.100s", strerror(errno));
166                         close(tmpfd);
167                         return;
168                 }
169         } else {
170                 snprintf(ccname,sizeof(ccname),"/tmp/krb5cc_%d",geteuid());
171                 tmpfd = open(ccname, O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
172                 if (tmpfd == -1) {
173                         log("open(): %.100s", strerror(errno));
174                         return;
175                 }
176         }
177
178         close(tmpfd);
179         snprintf(name, sizeof(name), "FILE:%s",ccname);
180  
181         if ((problem = krb5_cc_resolve(krb_context, name, &ccache))) {
182                 log("krb5_cc_default(): %.100s", 
183                         krb5_get_err_text(krb_context,problem));
184                 return;
185         }
186
187         if ((problem = krb5_parse_name(krb_context, client->name.value, 
188                                        &princ))) {
189                 log("krb5_parse_name(): %.100s", 
190                         krb5_get_err_text(krb_context,problem));
191                 krb5_cc_destroy(krb_context,ccache);
192                 return;
193         }
194         
195         if ((problem = krb5_cc_initialize(krb_context, ccache, princ))) {
196                 log("krb5_cc_initialize(): %.100s", 
197                         krb5_get_err_text(krb_context,problem));
198                 krb5_free_principal(krb_context,princ);
199                 krb5_cc_destroy(krb_context,ccache);
200                 return;
201         }
202         
203         krb5_free_principal(krb_context,princ);
204
205         #ifdef HEIMDAL
206         if ((problem = krb5_cc_copy_cache(krb_context, 
207                                            client->creds->ccache,
208                                            ccache))) {
209                 log("krb5_cc_copy_cache(): %.100s", 
210                         krb5_get_err_text(krb_context,problem));
211                 krb5_cc_destroy(krb_context,ccache);
212                 return;
213         }
214         #else
215         if ((maj_status = gss_krb5_copy_ccache(&min_status, 
216                                                client->creds, 
217                                                ccache))) {
218                 log("gss_krb5_copy_ccache() failed");
219                 krb5_cc_destroy(krb_context,ccache);
220                 return;
221         }
222         #endif
223         
224         krb5_cc_close(krb_context,ccache);
225
226 #ifdef USE_PAM
227         do_pam_putenv("KRB5CCNAME",name);
228 #endif
229
230         client->store.filename=strdup(ccname);
231         client->store.envvar="KRB5CCNAME";
232         client->store.envval=strdup(name);
233
234         return;
235 }
236
237 /* We've been using a wrongly encoded mechanism ID for yonks */
238
239 ssh_gssapi_mech gssapi_kerberos_mech_old = {
240         "Se3H81ismmOC3OE+FwYCiQ==",
241         "Kerberos",
242         {9, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02"},
243         &ssh_gssapi_krb5_init,
244         &ssh_gssapi_krb5_userok,
245         &ssh_gssapi_krb5_localname,
246         &ssh_gssapi_krb5_storecreds
247 };
248
249 ssh_gssapi_mech gssapi_kerberos_mech = {
250         "toWM5Slw5Ew8Mqkay+al2g==",
251         "Kerberos",
252         {9, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02"},
253         NULL,
254         &ssh_gssapi_krb5_userok,
255         &ssh_gssapi_krb5_localname,
256         &ssh_gssapi_krb5_storecreds
257 };
258         
259 #endif /* KRB5 */
260
261 #endif /* GSSAPI */
This page took 0.081673 seconds and 5 git commands to generate.