diff options
Diffstat (limited to 'auth-krb5.c')
-rw-r--r-- | auth-krb5.c | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/auth-krb5.c b/auth-krb5.c new file mode 100644 index 000000000..08c917459 --- /dev/null +++ b/auth-krb5.c | |||
@@ -0,0 +1,259 @@ | |||
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 | * $OpenBSD: auth-krb5.c,v 1.1 2001/06/26 16:15:23 dugsong Exp $ | ||
6 | */ | ||
7 | |||
8 | #include "includes.h" | ||
9 | #include "ssh.h" | ||
10 | #include "ssh1.h" | ||
11 | #include "packet.h" | ||
12 | #include "xmalloc.h" | ||
13 | #include "log.h" | ||
14 | #include "servconf.h" | ||
15 | #include "uidswap.h" | ||
16 | #include "auth.h" | ||
17 | |||
18 | #ifdef KRB5 | ||
19 | #include <krb5.h> | ||
20 | |||
21 | extern ServerOptions options; | ||
22 | |||
23 | static int | ||
24 | krb5_init(void *context) | ||
25 | { | ||
26 | Authctxt *authctxt = (Authctxt *)context; | ||
27 | krb5_error_code problem; | ||
28 | static int cleanup_registered = 0; | ||
29 | |||
30 | if (authctxt->krb5_ctx == NULL) { | ||
31 | problem = krb5_init_context(&authctxt->krb5_ctx); | ||
32 | if (problem) | ||
33 | return (problem); | ||
34 | krb5_init_ets(authctxt->krb5_ctx); | ||
35 | } | ||
36 | if (!cleanup_registered) { | ||
37 | fatal_add_cleanup(krb5_cleanup_proc, authctxt); | ||
38 | cleanup_registered = 1; | ||
39 | } | ||
40 | return (0); | ||
41 | } | ||
42 | |||
43 | /* | ||
44 | * Try krb5 authentication. server_user is passed for logging purposes | ||
45 | * only, in auth is received ticket, in client is returned principal | ||
46 | * from the ticket | ||
47 | */ | ||
48 | int | ||
49 | auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client) | ||
50 | { | ||
51 | krb5_error_code problem; | ||
52 | krb5_principal server; | ||
53 | krb5_data reply; | ||
54 | krb5_ticket *ticket; | ||
55 | int fd; | ||
56 | |||
57 | server = NULL; | ||
58 | ticket = NULL; | ||
59 | reply.length = 0; | ||
60 | |||
61 | problem = krb5_init(authctxt); | ||
62 | if (problem) | ||
63 | goto err; | ||
64 | |||
65 | problem = krb5_auth_con_init(authctxt->krb5_ctx, | ||
66 | &authctxt->krb5_auth_ctx); | ||
67 | if (problem) | ||
68 | goto err; | ||
69 | |||
70 | fd = packet_get_connection_in(); | ||
71 | problem = krb5_auth_con_setaddrs_from_fd(authctxt->krb5_ctx, | ||
72 | authctxt->krb5_auth_ctx, &fd); | ||
73 | if (problem) | ||
74 | goto err; | ||
75 | |||
76 | problem = krb5_sname_to_principal(authctxt->krb5_ctx, NULL, NULL , | ||
77 | KRB5_NT_SRV_HST, &server); | ||
78 | if (problem) | ||
79 | goto err; | ||
80 | |||
81 | problem = krb5_rd_req(authctxt->krb5_ctx, &authctxt->krb5_auth_ctx, | ||
82 | auth, server, NULL, NULL, &ticket); | ||
83 | if (problem) | ||
84 | goto err; | ||
85 | |||
86 | problem = krb5_copy_principal(authctxt->krb5_ctx, ticket->client, | ||
87 | &authctxt->krb5_user); | ||
88 | if (problem) | ||
89 | goto err; | ||
90 | |||
91 | /* if client wants mutual auth */ | ||
92 | problem = krb5_mk_rep(authctxt->krb5_ctx, authctxt->krb5_auth_ctx, | ||
93 | &reply); | ||
94 | if (problem) | ||
95 | goto err; | ||
96 | |||
97 | /* Check .k5login authorization now. */ | ||
98 | if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user, | ||
99 | authctxt->pw->pw_name)) | ||
100 | goto err; | ||
101 | |||
102 | if (client) | ||
103 | krb5_unparse_name(authctxt->krb5_ctx, authctxt->krb5_user, | ||
104 | client); | ||
105 | |||
106 | packet_start(SSH_SMSG_AUTH_KERBEROS_RESPONSE); | ||
107 | packet_put_string((char *) reply.data, reply.length); | ||
108 | packet_send(); | ||
109 | packet_write_wait(); | ||
110 | |||
111 | err: | ||
112 | if (server) | ||
113 | krb5_free_principal(authctxt->krb5_ctx, server); | ||
114 | if (ticket) | ||
115 | krb5_free_ticket(authctxt->krb5_ctx, ticket); | ||
116 | if (reply.length) | ||
117 | xfree(reply.data); | ||
118 | |||
119 | if (problem) { | ||
120 | debug("Kerberos v5 authentication failed: %s", | ||
121 | krb5_get_err_text(authctxt->krb5_ctx, problem)); | ||
122 | return (0); | ||
123 | } | ||
124 | return (1); | ||
125 | } | ||
126 | |||
127 | int | ||
128 | auth_krb5_tgt(Authctxt *authctxt, krb5_data *tgt) | ||
129 | { | ||
130 | krb5_error_code problem; | ||
131 | krb5_ccache ccache = NULL; | ||
132 | char *pname; | ||
133 | |||
134 | if (authctxt->pw == NULL || authctxt->krb5_user == NULL) | ||
135 | return (0); | ||
136 | |||
137 | temporarily_use_uid(authctxt->pw); | ||
138 | |||
139 | problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_fcc_ops, &ccache); | ||
140 | if (problem) | ||
141 | goto fail; | ||
142 | |||
143 | problem = krb5_cc_initialize(authctxt->krb5_ctx, ccache, | ||
144 | authctxt->krb5_user); | ||
145 | if (problem) | ||
146 | goto fail; | ||
147 | |||
148 | problem = krb5_rd_cred2(authctxt->krb5_ctx, authctxt->krb5_auth_ctx, | ||
149 | ccache, tgt); | ||
150 | if (problem) | ||
151 | goto fail; | ||
152 | |||
153 | authctxt->krb5_fwd_ccache = ccache; | ||
154 | ccache = NULL; | ||
155 | |||
156 | authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); | ||
157 | |||
158 | problem = krb5_unparse_name(authctxt->krb5_ctx, authctxt->krb5_user, | ||
159 | &pname); | ||
160 | if (problem) | ||
161 | goto fail; | ||
162 | |||
163 | debug("Kerberos v5 TGT accepted (%s)", pname); | ||
164 | |||
165 | restore_uid(); | ||
166 | |||
167 | return (1); | ||
168 | |||
169 | fail: | ||
170 | if (problem) | ||
171 | debug("Kerberos v5 TGT passing failed: %s", | ||
172 | krb5_get_err_text(authctxt->krb5_ctx, problem)); | ||
173 | if (ccache) | ||
174 | krb5_cc_destroy(authctxt->krb5_ctx, ccache); | ||
175 | |||
176 | restore_uid(); | ||
177 | |||
178 | return (0); | ||
179 | } | ||
180 | |||
181 | int | ||
182 | auth_krb5_password(Authctxt *authctxt, const char *password) | ||
183 | { | ||
184 | krb5_error_code problem; | ||
185 | |||
186 | if (authctxt->pw == NULL) | ||
187 | return (0); | ||
188 | |||
189 | temporarily_use_uid(authctxt->pw); | ||
190 | |||
191 | problem = krb5_init(authctxt); | ||
192 | if (problem) | ||
193 | goto out; | ||
194 | |||
195 | problem = krb5_parse_name(authctxt->krb5_ctx, authctxt->pw->pw_name, | ||
196 | &authctxt->krb5_user); | ||
197 | if (problem) | ||
198 | goto out; | ||
199 | |||
200 | problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_mcc_ops, | ||
201 | &authctxt->krb5_fwd_ccache); | ||
202 | if (problem) | ||
203 | goto out; | ||
204 | |||
205 | problem = krb5_cc_initialize(authctxt->krb5_ctx, | ||
206 | authctxt->krb5_fwd_ccache, authctxt->krb5_user); | ||
207 | if (problem) | ||
208 | goto out; | ||
209 | |||
210 | problem = krb5_verify_user(authctxt->krb5_ctx, authctxt->krb5_user, | ||
211 | authctxt->krb5_fwd_ccache, password, 1, NULL); | ||
212 | if (problem) | ||
213 | goto out; | ||
214 | |||
215 | authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); | ||
216 | |||
217 | out: | ||
218 | restore_uid(); | ||
219 | |||
220 | if (problem) { | ||
221 | debug("Kerberos password authentication failed: %s", | ||
222 | krb5_get_err_text(authctxt->krb5_ctx, problem)); | ||
223 | |||
224 | krb5_cleanup_proc(authctxt); | ||
225 | |||
226 | if (options.kerberos_or_local_passwd) | ||
227 | return (-1); | ||
228 | else | ||
229 | return (0); | ||
230 | } | ||
231 | return (1); | ||
232 | } | ||
233 | |||
234 | void | ||
235 | krb5_cleanup_proc(void *context) | ||
236 | { | ||
237 | Authctxt *authctxt = (Authctxt *)context; | ||
238 | |||
239 | debug("krb5_cleanup_proc called"); | ||
240 | if (authctxt->krb5_fwd_ccache) { | ||
241 | krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); | ||
242 | authctxt->krb5_fwd_ccache = NULL; | ||
243 | } | ||
244 | if (authctxt->krb5_user) { | ||
245 | krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user); | ||
246 | authctxt->krb5_user = NULL; | ||
247 | } | ||
248 | if (authctxt->krb5_auth_ctx) { | ||
249 | krb5_auth_con_free(authctxt->krb5_ctx, | ||
250 | authctxt->krb5_auth_ctx); | ||
251 | authctxt->krb5_auth_ctx = NULL; | ||
252 | } | ||
253 | if (authctxt->krb5_ctx) { | ||
254 | krb5_free_context(authctxt->krb5_ctx); | ||
255 | authctxt->krb5_ctx = NULL; | ||
256 | } | ||
257 | } | ||
258 | |||
259 | #endif /* KRB5 */ | ||