2 * Kerberos v5 authentication and ticket-passing routines.
4 * $FreeBSD: src/crypto/openssh/auth-krb5.c,v 1.6 2001/02/13 16:58:04 assar Exp $
8 RCSID("$OpenBSD: auth-krb5.c,v 1.6 2002/03/04 17:27:39 stevesk Exp $");
22 #define krb5_get_err_text(context,code) error_message(code)
25 extern ServerOptions options;
28 krb5_init(void *context)
30 Authctxt *authctxt = (Authctxt *)context;
31 krb5_error_code problem;
32 static int cleanup_registered = 0;
34 if (authctxt->krb5_ctx == NULL) {
35 problem = krb5_init_context(&authctxt->krb5_ctx);
38 krb5_init_ets(authctxt->krb5_ctx);
40 if (!cleanup_registered) {
41 fatal_add_cleanup(krb5_cleanup_proc, authctxt);
42 cleanup_registered = 1;
48 * Try krb5 authentication. server_user is passed for logging purposes
49 * only, in auth is received ticket, in client is returned principal
53 auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client)
55 krb5_error_code problem;
56 krb5_principal server;
66 problem = krb5_init(authctxt);
70 problem = krb5_auth_con_init(authctxt->krb5_ctx,
71 &authctxt->krb5_auth_ctx);
75 fd = packet_get_connection_in();
77 problem = krb5_auth_con_setaddrs_from_fd(authctxt->krb5_ctx,
78 authctxt->krb5_auth_ctx, &fd);
80 problem = krb5_auth_con_genaddrs(authctxt->krb5_ctx,
81 authctxt->krb5_auth_ctx,fd,
82 KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR |
83 KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR);
88 problem = krb5_sname_to_principal(authctxt->krb5_ctx, NULL, NULL ,
89 KRB5_NT_SRV_HST, &server);
93 problem = krb5_rd_req(authctxt->krb5_ctx, &authctxt->krb5_auth_ctx,
94 auth, server, NULL, NULL, &ticket);
99 problem = krb5_copy_principal(authctxt->krb5_ctx, ticket->client,
100 &authctxt->krb5_user);
102 problem = krb5_copy_principal(authctxt->krb5_ctx,
103 ticket->enc_part2->client,
104 &authctxt->krb5_user);
109 /* if client wants mutual auth */
110 problem = krb5_mk_rep(authctxt->krb5_ctx, authctxt->krb5_auth_ctx,
115 /* Check .k5login authorization now. */
116 if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user,
117 authctxt->pw->pw_name))
121 krb5_unparse_name(authctxt->krb5_ctx, authctxt->krb5_user,
124 packet_start(SSH_SMSG_AUTH_KERBEROS_RESPONSE);
125 packet_put_string((char *) reply.data, reply.length);
132 krb5_free_principal(authctxt->krb5_ctx, server);
134 krb5_free_ticket(authctxt->krb5_ctx, ticket);
139 if (authctxt->krb5_ctx != NULL)
140 debug("Kerberos v5 authentication failed: %s",
141 krb5_get_err_text(authctxt->krb5_ctx, problem));
143 debug("Kerberos v5 authentication failed: %d",
151 auth_krb5_tgt(Authctxt *authctxt, krb5_data *tgt)
153 krb5_error_code problem;
154 krb5_ccache ccache = NULL;
158 if (authctxt->pw == NULL || authctxt->krb5_user == NULL)
161 temporarily_use_uid(authctxt->pw);
164 problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_fcc_ops, &ccache);
170 snprintf(ccname,sizeof(ccname),"FILE:/tmp/krb5cc_%d_XXXXXX",geteuid());
172 if ((tmpfd = mkstemp(ccname))==-1) {
173 log("mkstemp(): %.100s", strerror(errno));
177 if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) {
178 log("fchmod(): %.100s", strerror(errno));
184 problem = krb5_cc_resolve(authctxt->krb5_ctx, ccname, &ccache);
190 problem = krb5_cc_initialize(authctxt->krb5_ctx, ccache,
191 authctxt->krb5_user);
196 problem = krb5_rd_cred2(authctxt->krb5_ctx, authctxt->krb5_auth_ctx,
201 problem = krb5_rd_cred(authctxt->krb5_ctx, authctxt->krb5_auth_ctx,
205 problem = krb5_cc_store_cred(authctxt->krb5_ctx, ccache, *creds);
210 authctxt->krb5_fwd_ccache = ccache;
213 authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
215 problem = krb5_unparse_name(authctxt->krb5_ctx, authctxt->krb5_user,
220 debug("Kerberos v5 TGT accepted (%s)", pname);
228 debug("Kerberos v5 TGT passing failed: %s",
229 krb5_get_err_text(authctxt->krb5_ctx, problem));
231 krb5_cc_destroy(authctxt->krb5_ctx, ccache);
239 auth_krb5_password(Authctxt *authctxt, const char *password)
243 krb5_principal server;
245 krb5_error_code problem;
247 if (authctxt->pw == NULL)
250 temporarily_use_uid(authctxt->pw);
252 problem = krb5_init(authctxt);
256 problem = krb5_parse_name(authctxt->krb5_ctx, authctxt->pw->pw_name,
257 &authctxt->krb5_user);
262 problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_mcc_ops,
263 &authctxt->krb5_fwd_ccache);
265 problem = krb5_cc_resolve(authctxt->krb5_ctx, "MEMORY:",
266 &authctxt->krb5_fwd_ccache);
271 problem = krb5_cc_initialize(authctxt->krb5_ctx,
272 authctxt->krb5_fwd_ccache, authctxt->krb5_user);
279 problem = krb5_verify_user(authctxt->krb5_ctx, authctxt->krb5_user,
280 authctxt->krb5_fwd_ccache, password, 1, NULL);
282 temporarily_use_uid(authctxt->pw);
286 problem = krb5_get_init_creds_password(authctxt->krb5_ctx, &creds,
287 authctxt->krb5_user, password, NULL, NULL, 0, NULL, NULL);
289 temporarily_use_uid(authctxt->pw);
293 problem = krb5_sname_to_principal(authctxt->krb5_ctx, NULL, NULL,
294 KRB5_NT_SRV_HST, &server);
296 temporarily_use_uid(authctxt->pw);
300 problem = krb5_verify_init_creds(authctxt->krb5_ctx, &creds, server,
303 krb5_free_principal(authctxt->krb5_ctx, server);
305 temporarily_use_uid(authctxt->pw);
310 problem= krb5_cc_store_cred(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache,
313 temporarily_use_uid(authctxt->pw);
317 temporarily_use_uid(authctxt->pw);
322 authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
328 if (authctxt->krb5_ctx != NULL)
329 debug("Kerberos password authentication failed: %s",
330 krb5_get_err_text(authctxt->krb5_ctx, problem));
332 debug("Kerberos password authentication failed: %d",
335 krb5_cleanup_proc(authctxt);
337 if (options.kerberos_or_local_passwd)
346 krb5_cleanup_proc(void *context)
348 Authctxt *authctxt = (Authctxt *)context;
350 debug("krb5_cleanup_proc called");
351 if (authctxt->krb5_fwd_ccache) {
352 krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
353 authctxt->krb5_fwd_ccache = NULL;
355 if (authctxt->krb5_user) {
356 krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user);
357 authctxt->krb5_user = NULL;
359 if (authctxt->krb5_auth_ctx) {
360 krb5_auth_con_free(authctxt->krb5_ctx,
361 authctxt->krb5_auth_ctx);
362 authctxt->krb5_auth_ctx = NULL;
364 if (authctxt->krb5_ctx) {
365 krb5_free_context(authctxt->krb5_ctx);
366 authctxt->krb5_ctx = NULL;