auth-krb5.c revision 126277
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 126277 2004-02-26 10:52:33Z 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 krb5_init_ets(authctxt->krb5_ctx); 59 } 60 return (0); 61} 62 63int 64auth_krb5_password(Authctxt *authctxt, const char *password) 65{ 66#ifndef HEIMDAL 67 krb5_creds creds; 68 krb5_principal server; 69 char ccname[40]; 70 int tmpfd; 71#endif 72 krb5_error_code problem; 73 krb5_ccache ccache = NULL; 74 75 if (!authctxt->valid) 76 return (0); 77 78 temporarily_use_uid(authctxt->pw); 79 80 problem = krb5_init(authctxt); 81 if (problem) 82 goto out; 83 84 problem = krb5_parse_name(authctxt->krb5_ctx, authctxt->pw->pw_name, 85 &authctxt->krb5_user); 86 if (problem) 87 goto out; 88 89#ifdef HEIMDAL 90 problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_mcc_ops, &ccache); 91 if (problem) 92 goto out; 93 94 problem = krb5_cc_initialize(authctxt->krb5_ctx, ccache, 95 authctxt->krb5_user); 96 if (problem) 97 goto out; 98 99 restore_uid(); 100 101 problem = krb5_verify_user(authctxt->krb5_ctx, authctxt->krb5_user, 102 ccache, password, 1, NULL); 103 104 temporarily_use_uid(authctxt->pw); 105 106 if (problem) 107 goto out; 108 109 problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_fcc_ops, 110 &authctxt->krb5_fwd_ccache); 111 if (problem) 112 goto out; 113 114 problem = krb5_cc_copy_cache(authctxt->krb5_ctx, ccache, 115 authctxt->krb5_fwd_ccache); 116 krb5_cc_destroy(authctxt->krb5_ctx, ccache); 117 ccache = NULL; 118 if (problem) 119 goto out; 120 121#else 122 problem = krb5_get_init_creds_password(authctxt->krb5_ctx, &creds, 123 authctxt->krb5_user, (char *)password, NULL, NULL, 0, NULL, NULL); 124 if (problem) 125 goto out; 126 127 problem = krb5_sname_to_principal(authctxt->krb5_ctx, NULL, NULL, 128 KRB5_NT_SRV_HST, &server); 129 if (problem) 130 goto out; 131 132 restore_uid(); 133 problem = krb5_verify_init_creds(authctxt->krb5_ctx, &creds, server, 134 NULL, NULL, NULL); 135 krb5_free_principal(authctxt->krb5_ctx, server); 136 temporarily_use_uid(authctxt->pw); 137 if (problem) 138 goto out; 139 140 if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user, 141 authctxt->pw->pw_name)) { 142 problem = -1; 143 goto out; 144 } 145 146 snprintf(ccname,sizeof(ccname),"FILE:/tmp/krb5cc_%d_XXXXXX",geteuid()); 147 148 if ((tmpfd = mkstemp(ccname+strlen("FILE:")))==-1) { 149 logit("mkstemp(): %.100s", strerror(errno)); 150 problem = errno; 151 goto out; 152 } 153 154 if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) { 155 logit("fchmod(): %.100s", strerror(errno)); 156 close(tmpfd); 157 problem = errno; 158 goto out; 159 } 160 close(tmpfd); 161 162 problem = krb5_cc_resolve(authctxt->krb5_ctx, ccname, &authctxt->krb5_fwd_ccache); 163 if (problem) 164 goto out; 165 166 problem = krb5_cc_initialize(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache, 167 authctxt->krb5_user); 168 if (problem) 169 goto out; 170 171 problem= krb5_cc_store_cred(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache, 172 &creds); 173 if (problem) 174 goto out; 175#endif 176 177 authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); 178 179 out: 180 restore_uid(); 181 182 if (problem) { 183 if (ccache) 184 krb5_cc_destroy(authctxt->krb5_ctx, ccache); 185 186 if (authctxt->krb5_ctx != NULL && problem!=-1) 187 debug("Kerberos password authentication failed: %s", 188 krb5_get_err_text(authctxt->krb5_ctx, problem)); 189 else 190 debug("Kerberos password authentication failed: %d", 191 problem); 192 193 krb5_cleanup_proc(authctxt); 194 195 if (options.kerberos_or_local_passwd) 196 return (-1); 197 else 198 return (0); 199 } 200 return (1); 201} 202 203void 204krb5_cleanup_proc(Authctxt *authctxt) 205{ 206 debug("krb5_cleanup_proc called"); 207 if (authctxt->krb5_fwd_ccache) { 208 krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); 209 authctxt->krb5_fwd_ccache = NULL; 210 } 211 if (authctxt->krb5_user) { 212 krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user); 213 authctxt->krb5_user = NULL; 214 } 215 if (authctxt->krb5_ctx) { 216 krb5_free_context(authctxt->krb5_ctx); 217 authctxt->krb5_ctx = NULL; 218 } 219} 220 221#endif /* KRB5 */ 222