auth-krb5.c revision 137019
1/* 2 * Kerberos v5 authentication and ticket-passing routines. 3 * 4 * $xFreeBSD: 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.15 2003/11/21 11:57:02 djm Exp $"); 32RCSID("$FreeBSD: head/crypto/openssh/auth-krb5.c 137019 2004-10-28 16:11:31Z des $"); 33 34#include "ssh.h" 35#include "ssh1.h" 36#include "packet.h" 37#include "xmalloc.h" 38#include "log.h" 39#include "servconf.h" 40#include "uidswap.h" 41#include "auth.h" 42 43#ifdef KRB5 44#include <krb5.h> 45 46extern ServerOptions options; 47 48static int 49krb5_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#ifdef KRB5_INIT_ETS 59 krb5_init_ets(authctxt->krb5_ctx); 60#endif 61 } 62 return (0); 63} 64 65int 66auth_krb5_password(Authctxt *authctxt, const char *password) 67{ 68#ifndef HEIMDAL 69 krb5_creds creds; 70 krb5_principal server; 71 char ccname[40]; 72 int tmpfd; 73 mode_t old_umask; 74#endif 75 krb5_error_code problem; 76 krb5_ccache ccache = NULL; 77 int len; 78 79 if (!authctxt->valid) 80 return (0); 81 82 temporarily_use_uid(authctxt->pw); 83 84 problem = krb5_init(authctxt); 85 if (problem) 86 goto out; 87 88 problem = krb5_parse_name(authctxt->krb5_ctx, authctxt->pw->pw_name, 89 &authctxt->krb5_user); 90 if (problem) 91 goto out; 92 93#ifdef HEIMDAL 94 problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_mcc_ops, &ccache); 95 if (problem) 96 goto out; 97 98 problem = krb5_cc_initialize(authctxt->krb5_ctx, ccache, 99 authctxt->krb5_user); 100 if (problem) 101 goto out; 102 103 restore_uid(); 104 105 problem = krb5_verify_user(authctxt->krb5_ctx, authctxt->krb5_user, 106 ccache, password, 1, NULL); 107 108 temporarily_use_uid(authctxt->pw); 109 110 if (problem) 111 goto out; 112 113 problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_fcc_ops, 114 &authctxt->krb5_fwd_ccache); 115 if (problem) 116 goto out; 117 118 problem = krb5_cc_copy_cache(authctxt->krb5_ctx, ccache, 119 authctxt->krb5_fwd_ccache); 120 krb5_cc_destroy(authctxt->krb5_ctx, ccache); 121 ccache = NULL; 122 if (problem) 123 goto out; 124 125#else 126 problem = krb5_get_init_creds_password(authctxt->krb5_ctx, &creds, 127 authctxt->krb5_user, (char *)password, NULL, NULL, 0, NULL, NULL); 128 if (problem) 129 goto out; 130 131 problem = krb5_sname_to_principal(authctxt->krb5_ctx, NULL, NULL, 132 KRB5_NT_SRV_HST, &server); 133 if (problem) 134 goto out; 135 136 restore_uid(); 137 problem = krb5_verify_init_creds(authctxt->krb5_ctx, &creds, server, 138 NULL, NULL, NULL); 139 krb5_free_principal(authctxt->krb5_ctx, server); 140 temporarily_use_uid(authctxt->pw); 141 if (problem) 142 goto out; 143 144 if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user, 145 authctxt->pw->pw_name)) { 146 problem = -1; 147 goto out; 148 } 149 150 snprintf(ccname,sizeof(ccname),"FILE:/tmp/krb5cc_%d_XXXXXX",geteuid()); 151 152 old_umask = umask(0177); 153 tmpfd = mkstemp(ccname + strlen("FILE:")); 154 umask(old_umask); 155 if (tmpfd == -1) { 156 logit("mkstemp(): %.100s", strerror(errno)); 157 problem = errno; 158 goto out; 159 } 160 161 if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) { 162 logit("fchmod(): %.100s", strerror(errno)); 163 close(tmpfd); 164 problem = errno; 165 goto out; 166 } 167 close(tmpfd); 168 169 problem = krb5_cc_resolve(authctxt->krb5_ctx, ccname, &authctxt->krb5_fwd_ccache); 170 if (problem) 171 goto out; 172 173 problem = krb5_cc_initialize(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache, 174 authctxt->krb5_user); 175 if (problem) 176 goto out; 177 178 problem= krb5_cc_store_cred(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache, 179 &creds); 180 if (problem) 181 goto out; 182#endif 183 184 authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); 185 186 len = strlen(authctxt->krb5_ticket_file) + 6; 187 authctxt->krb5_ccname = xmalloc(len); 188 snprintf(authctxt->krb5_ccname, len, "FILE:%s", 189 authctxt->krb5_ticket_file); 190 191 out: 192 restore_uid(); 193 194 if (problem) { 195 if (ccache) 196 krb5_cc_destroy(authctxt->krb5_ctx, ccache); 197 198 if (authctxt->krb5_ctx != NULL && problem!=-1) 199 debug("Kerberos password authentication failed: %s", 200 krb5_get_err_text(authctxt->krb5_ctx, problem)); 201 else 202 debug("Kerberos password authentication failed: %d", 203 problem); 204 205 krb5_cleanup_proc(authctxt); 206 207 if (options.kerberos_or_local_passwd) 208 return (-1); 209 else 210 return (0); 211 } 212 return (1); 213} 214 215void 216krb5_cleanup_proc(Authctxt *authctxt) 217{ 218 debug("krb5_cleanup_proc called"); 219 if (authctxt->krb5_fwd_ccache) { 220 krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); 221 authctxt->krb5_fwd_ccache = NULL; 222 } 223 if (authctxt->krb5_user) { 224 krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user); 225 authctxt->krb5_user = NULL; 226 } 227 if (authctxt->krb5_ctx) { 228 krb5_free_context(authctxt->krb5_ctx); 229 authctxt->krb5_ctx = NULL; 230 } 231} 232 233#endif /* KRB5 */ 234