source: trunk/third/openssh/auth-krb5.c @ 21602

Revision 21602, 9.8 KB checked in by zacheiss, 20 years ago (diff)
Remove krb5_init_ets(); it no longer exists.
Line 
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 $
5 */
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 */
29
30#include "includes.h"
31RCSID("$OpenBSD: auth-krb5.c,v 1.9 2002/09/09 06:48:06 itojun Exp $");
32
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#ifndef HEIMDAL
45#define krb5_get_err_text(context,code) error_message(code)
46#endif /* !HEIMDAL */
47
48extern ServerOptions     options;
49
50static int
51krb5_init(void *context)
52{
53        Authctxt *authctxt = (Authctxt *)context;
54        krb5_error_code problem;
55        static int cleanup_registered = 0;
56        int fd;
57#ifndef HEIMDAL
58        krb5_rcache rcache;
59        krb5_data host_data;
60#endif 
61
62        if (authctxt->krb5_ctx == NULL) {
63                problem = krb5_init_context(&authctxt->krb5_ctx);
64                if (problem)
65                        return (problem);
66               
67        }
68        if (authctxt->krb5_auth_ctx == NULL) {
69                problem = krb5_auth_con_init(authctxt->krb5_ctx,
70                    &authctxt->krb5_auth_ctx);
71                if (problem)
72                    return problem;
73
74                host_data.data = "host";
75                host_data.length = strlen(host_data.data);
76                krb5_get_server_rcache(authctxt->krb5_ctx,
77                                       &host_data, &rcache);
78                krb5_auth_con_setrcache(authctxt->krb5_ctx,
79                    authctxt->krb5_auth_ctx,
80                    rcache);
81       
82                fd = packet_get_connection_in();
83#ifdef HEIMDAL
84                problem = krb5_auth_con_setaddrs_from_fd(authctxt->krb5_ctx,
85                   authctxt->krb5_auth_ctx, &fd);
86#else
87                problem = krb5_auth_con_genaddrs(authctxt->krb5_ctx,
88                    authctxt->krb5_auth_ctx,fd,
89                    KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR |
90                    KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR);
91#endif
92                if (problem)
93                  return problem;
94        }
95
96        if (!cleanup_registered) {
97                fatal_add_cleanup(krb5_cleanup_proc, authctxt);
98                cleanup_registered = 1;
99        }
100        return (0);
101}
102
103/*
104 * Try krb5 authentication. server_user is passed for logging purposes
105 * only, in auth is received ticket, in client is returned principal
106 * from the ticket
107 */
108int
109auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client, krb5_data *reply)
110{
111        krb5_error_code problem;
112        krb5_principal server;
113        krb5_ticket *ticket;
114        int fd, ret;
115
116        ret = 0;
117        server = NULL;
118        ticket = NULL;
119        reply->length = 0;
120
121        problem = krb5_init(authctxt);
122        if (problem)
123                goto err;
124
125        problem = krb5_sname_to_principal(authctxt->krb5_ctx,  NULL, NULL ,
126            KRB5_NT_SRV_HST, &server);
127        if (problem)
128                goto err;
129
130        problem = krb5_rd_req(authctxt->krb5_ctx, &authctxt->krb5_auth_ctx,
131            auth, server, NULL, NULL, &ticket);
132        if (problem)
133                goto err;
134
135#ifdef HEIMDAL
136        problem = krb5_copy_principal(authctxt->krb5_ctx, ticket->client,
137            &authctxt->krb5_user);
138#else
139        problem = krb5_copy_principal(authctxt->krb5_ctx,
140                                      ticket->enc_part2->client,
141                                      &authctxt->krb5_user);
142#endif
143        if (problem)
144                goto err;
145
146        /* if client wants mutual auth */
147        problem = krb5_mk_rep(authctxt->krb5_ctx, authctxt->krb5_auth_ctx,
148            reply);
149        if (problem)
150                goto err;
151
152        /* Check .k5login authorization now. */
153        if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user,
154            authctxt->pw->pw_name))
155                goto err;
156
157        if (client)
158                krb5_unparse_name(authctxt->krb5_ctx, authctxt->krb5_user,
159                    client);
160
161        ret = 1;
162 err:
163        if (server)
164                krb5_free_principal(authctxt->krb5_ctx, server);
165        if (ticket)
166                krb5_free_ticket(authctxt->krb5_ctx, ticket);
167        if (!ret && reply->length) {
168                xfree(reply->data);
169                memset(reply, 0, sizeof(*reply));
170        }
171
172        if (problem) {
173                if (authctxt->krb5_ctx != NULL)
174                        debug("Kerberos v5 authentication failed: %s",
175                            krb5_get_err_text(authctxt->krb5_ctx, problem));
176                else
177                        debug("Kerberos v5 authentication failed: %d",
178                            problem);
179        }
180
181        return (ret);
182}
183
184int
185auth_krb5_tgt(Authctxt *authctxt, krb5_data *tgt)
186{
187        krb5_error_code problem;
188        krb5_ccache ccache = NULL;
189        char *pname;
190        krb5_creds **creds;
191
192        problem = krb5_init(authctxt);
193        if (problem)
194                goto fail;
195
196        if (authctxt->pw == NULL)
197                return (0);
198
199        temporarily_use_uid(authctxt->pw);
200
201        problem = krb5_rd_cred(authctxt->krb5_ctx, authctxt->krb5_auth_ctx,
202                               tgt, &creds, NULL);
203        if (problem)
204                goto fail;
205#ifdef HEIMDAL
206        problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_fcc_ops, &ccache);
207#else
208{
209        char ccname[40];
210       
211        snprintf(ccname,sizeof(ccname),"FILE:/tmp/krb5cc_p%d",getpid());
212        setenv("KRB5CCNAME", ccname, 1);
213       
214        problem = krb5_cc_resolve(authctxt->krb5_ctx, ccname, &ccache);
215}
216#endif
217        if (problem)
218                goto fail;
219
220        problem = krb5_copy_principal(authctxt->krb5_ctx, (*creds)->client,
221                                      &authctxt->krb5_user);
222        if (problem)
223                goto fail;
224
225        problem = krb5_cc_initialize(authctxt->krb5_ctx, ccache,
226            authctxt->krb5_user);
227        if (problem)
228                goto fail;
229
230#ifdef HEIMDAL
231        problem = krb5_rd_cred2(authctxt->krb5_ctx, authctxt->krb5_auth_ctx,
232            ccache, tgt);
233        if (problem)
234                goto fail;
235#else
236        problem = krb5_cc_store_cred(authctxt->krb5_ctx, ccache, *creds);
237        if (problem)
238                goto fail;
239#endif
240
241        authctxt->krb5_fwd_ccache = ccache;
242        ccache = NULL;
243
244        authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
245
246        problem = krb5_unparse_name(authctxt->krb5_ctx, authctxt->krb5_user,
247            &pname);
248        if (problem)
249                goto fail;
250
251        debug("Kerberos v5 TGT accepted (%s)", pname);
252
253        restore_uid();
254
255        return (1);
256
257 fail:
258        if (problem)
259                debug("Kerberos v5 TGT passing failed: %s",
260                    krb5_get_err_text(authctxt->krb5_ctx, problem));
261        if (ccache)
262                krb5_cc_destroy(authctxt->krb5_ctx, ccache);
263
264        restore_uid();
265
266        return (0);
267}
268
269int
270auth_krb5_password(Authctxt *authctxt, const char *password)
271{
272#ifndef HEIMDAL
273        krb5_creds creds;
274        krb5_principal server;
275        char ccname[40];
276#endif 
277        krb5_error_code problem;
278
279        if (authctxt->pw == NULL)
280                return (0);
281
282        temporarily_use_uid(authctxt->pw);
283
284        problem = krb5_init(authctxt);
285        if (problem)
286                goto out;
287
288        problem = krb5_parse_name(authctxt->krb5_ctx, authctxt->pw->pw_name,
289                    &authctxt->krb5_user);
290        if (problem)
291                goto out;
292
293#ifdef HEIMDAL
294        problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_mcc_ops,
295            &authctxt->krb5_fwd_ccache);
296        if (problem)
297                goto out;
298
299        problem = krb5_cc_initialize(authctxt->krb5_ctx,
300            authctxt->krb5_fwd_ccache, authctxt->krb5_user);
301        if (problem)
302                goto out;
303
304        restore_uid();
305        problem = krb5_verify_user(authctxt->krb5_ctx, authctxt->krb5_user,
306            authctxt->krb5_fwd_ccache, password, 1, NULL);
307        temporarily_use_uid(authctxt->pw);
308
309        if (problem)
310                goto out;
311
312#else
313        problem = krb5_get_init_creds_password(authctxt->krb5_ctx, &creds,
314            authctxt->krb5_user, (char *)password, NULL, NULL, 0, NULL, NULL);
315        if (problem)
316                goto out;
317
318        problem = krb5_sname_to_principal(authctxt->krb5_ctx, NULL, NULL,
319            KRB5_NT_SRV_HST, &server);
320        if (problem)
321                goto out;
322
323        restore_uid();
324        problem = krb5_verify_init_creds(authctxt->krb5_ctx, &creds, server,
325            NULL, NULL, NULL);
326        krb5_free_principal(authctxt->krb5_ctx, server);
327        temporarily_use_uid(authctxt->pw);
328        if (problem)
329                goto out;
330       
331        if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user,
332                          authctxt->pw->pw_name)) {
333                problem = -1;
334                goto out;
335        }
336
337        snprintf(ccname,sizeof(ccname),"FILE:/tmp/krb5cc_p%d",getpid());
338        setenv("KRB5CCNAME", ccname, 1);
339
340        problem = krb5_cc_resolve(authctxt->krb5_ctx, ccname, &authctxt->krb5_fwd_ccache);
341        if (problem)
342                goto out;
343
344        problem = krb5_cc_initialize(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache,
345                                     authctxt->krb5_user);
346        if (problem)
347                goto out;
348                               
349        problem= krb5_cc_store_cred(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache,
350                                 &creds);
351        if (problem)
352                goto out;
353#endif         
354
355        authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
356
357 out:
358        restore_uid();
359
360        if (problem) {
361                if (authctxt->krb5_ctx != NULL && problem!=-1)
362                        debug("Kerberos password authentication failed: %s",
363                            krb5_get_err_text(authctxt->krb5_ctx, problem));
364                else
365                        debug("Kerberos password authentication failed: %d",
366                            problem);
367
368                krb5_cleanup_proc(authctxt);
369
370                if (options.kerberos_or_local_passwd)
371                        return (-1);
372                else
373                        return (0);
374        }
375        return (1);
376}
377
378void
379krb5_cleanup_proc(void *context)
380{
381        Authctxt *authctxt = (Authctxt *)context;
382
383        debug("krb5_cleanup_proc called");
384        if (authctxt->krb5_fwd_ccache) {
385                krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
386                authctxt->krb5_fwd_ccache = NULL;
387        }
388        if (authctxt->krb5_user) {
389                krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user);
390                authctxt->krb5_user = NULL;
391        }
392        if (authctxt->krb5_auth_ctx) {
393                krb5_auth_con_free(authctxt->krb5_ctx,
394                    authctxt->krb5_auth_ctx);
395                authctxt->krb5_auth_ctx = NULL;
396        }
397        if (authctxt->krb5_ctx) {
398                krb5_free_context(authctxt->krb5_ctx);
399                authctxt->krb5_ctx = NULL;
400        }
401}
402
403#endif /* KRB5 */
Note: See TracBrowser for help on using the repository browser.