]> andersk Git - openssh.git/blob - auth-krb5.c
- (dtucker) [auth-krb5.c auth-pam.c] Still more errno.h
[openssh.git] / auth-krb5.c
1 /* $OpenBSD: auth-krb5.c,v 1.18 2006/05/06 08:35:40 dtucker Exp $ */
2 /*
3  *    Kerberos v5 authentication and ticket-passing routines.
4  *
5  * $FreeBSD: src/crypto/openssh/auth-krb5.c,v 1.6 2001/02/13 16:58:04 assar Exp $
6  */
7 /*
8  * Copyright (c) 2002 Daniel Kouril.  All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "includes.h"
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 <errno.h>
44 #include <krb5.h>
45
46 extern ServerOptions     options;
47
48 static int
49 krb5_init(void *context)
50 {
51         Authctxt *authctxt = (Authctxt *)context;
52         krb5_error_code problem;
53
54         if (authctxt->krb5_ctx == NULL) {
55                 problem = krb5_init_context(&authctxt->krb5_ctx);
56                 if (problem)
57                         return (problem);
58         }
59         return (0);
60 }
61
62 int
63 auth_krb5_password(Authctxt *authctxt, const char *password)
64 {
65 #ifndef HEIMDAL
66         krb5_creds creds;
67         krb5_principal server;
68 #endif
69         krb5_error_code problem;
70         krb5_ccache ccache = NULL;
71         int len;
72
73         temporarily_use_uid(authctxt->pw);
74
75         problem = krb5_init(authctxt);
76         if (problem)
77                 goto out;
78
79         problem = krb5_parse_name(authctxt->krb5_ctx, authctxt->pw->pw_name,
80                     &authctxt->krb5_user);
81         if (problem)
82                 goto out;
83
84 #ifdef HEIMDAL
85         problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_mcc_ops, &ccache);
86         if (problem)
87                 goto out;
88
89         problem = krb5_cc_initialize(authctxt->krb5_ctx, ccache,
90                 authctxt->krb5_user);
91         if (problem)
92                 goto out;
93
94         restore_uid();
95
96         problem = krb5_verify_user(authctxt->krb5_ctx, authctxt->krb5_user,
97             ccache, password, 1, NULL);
98
99         temporarily_use_uid(authctxt->pw);
100
101         if (problem)
102                 goto out;
103
104         problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_fcc_ops,
105             &authctxt->krb5_fwd_ccache);
106         if (problem)
107                 goto out;
108
109         problem = krb5_cc_copy_cache(authctxt->krb5_ctx, ccache,
110             authctxt->krb5_fwd_ccache);
111         krb5_cc_destroy(authctxt->krb5_ctx, ccache);
112         ccache = NULL;
113         if (problem)
114                 goto out;
115
116 #else
117         problem = krb5_get_init_creds_password(authctxt->krb5_ctx, &creds,
118             authctxt->krb5_user, (char *)password, NULL, NULL, 0, NULL, NULL);
119         if (problem)
120                 goto out;
121
122         problem = krb5_sname_to_principal(authctxt->krb5_ctx, NULL, NULL,
123             KRB5_NT_SRV_HST, &server);
124         if (problem)
125                 goto out;
126
127         restore_uid();
128         problem = krb5_verify_init_creds(authctxt->krb5_ctx, &creds, server,
129             NULL, NULL, NULL);
130         krb5_free_principal(authctxt->krb5_ctx, server);
131         temporarily_use_uid(authctxt->pw);
132         if (problem)
133                 goto out;
134
135         if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user,
136                           authctxt->pw->pw_name)) {
137                 problem = -1;
138                 goto out;
139         }
140
141         problem = ssh_krb5_cc_gen(authctxt->krb5_ctx, &authctxt->krb5_fwd_ccache);
142         if (problem)
143                 goto out;
144
145         problem = krb5_cc_initialize(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache,
146                                      authctxt->krb5_user);
147         if (problem)
148                 goto out;
149
150         problem= krb5_cc_store_cred(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache,
151                                  &creds);
152         if (problem)
153                 goto out;
154 #endif
155
156         authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
157
158         len = strlen(authctxt->krb5_ticket_file) + 6;
159         authctxt->krb5_ccname = xmalloc(len);
160         snprintf(authctxt->krb5_ccname, len, "FILE:%s",
161             authctxt->krb5_ticket_file);
162
163 #ifdef USE_PAM
164         if (options.use_pam)
165                 do_pam_putenv("KRB5CCNAME", authctxt->krb5_ccname);
166 #endif
167
168  out:
169         restore_uid();
170
171         if (problem) {
172                 if (ccache)
173                         krb5_cc_destroy(authctxt->krb5_ctx, ccache);
174
175                 if (authctxt->krb5_ctx != NULL && problem!=-1)
176                         debug("Kerberos password authentication failed: %s",
177                             krb5_get_err_text(authctxt->krb5_ctx, problem));
178                 else
179                         debug("Kerberos password authentication failed: %d",
180                             problem);
181
182                 krb5_cleanup_proc(authctxt);
183
184                 if (options.kerberos_or_local_passwd)
185                         return (-1);
186                 else
187                         return (0);
188         }
189         return (authctxt->valid ? 1 : 0);
190 }
191
192 void
193 krb5_cleanup_proc(Authctxt *authctxt)
194 {
195         debug("krb5_cleanup_proc called");
196         if (authctxt->krb5_fwd_ccache) {
197                 krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
198                 authctxt->krb5_fwd_ccache = NULL;
199         }
200         if (authctxt->krb5_user) {
201                 krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user);
202                 authctxt->krb5_user = NULL;
203         }
204         if (authctxt->krb5_ctx) {
205                 krb5_free_context(authctxt->krb5_ctx);
206                 authctxt->krb5_ctx = NULL;
207         }
208 }
209
210 #ifndef HEIMDAL
211 krb5_error_code
212 ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
213         int tmpfd, ret;
214         char ccname[40];
215         mode_t old_umask;
216
217         ret = snprintf(ccname, sizeof(ccname),
218             "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid());
219         if (ret < 0 || (size_t)ret >= sizeof(ccname))
220                 return ENOMEM;
221
222         old_umask = umask(0177);
223         tmpfd = mkstemp(ccname + strlen("FILE:"));
224         umask(old_umask);
225         if (tmpfd == -1) {
226                 logit("mkstemp(): %.100s", strerror(errno));
227                 return errno;
228         }
229
230         if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) {
231                 logit("fchmod(): %.100s", strerror(errno));
232                 close(tmpfd);
233                 return errno;
234         }
235         close(tmpfd);
236
237         return (krb5_cc_resolve(ctx, ccname, ccache));
238 }
239 #endif /* !HEIMDAL */
240 #endif /* KRB5 */
This page took 1.405155 seconds and 5 git commands to generate.