1/* 2 * Copyright (c) 1995-2004 Kungliga Tekniska H�gskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#ifdef HAVE_CONFIG_H 35#include <config.h> 36RCSID("$Id: verify.c 14203 2004-09-08 09:02:59Z joda $"); 37#endif 38#include <unistd.h> 39#include <sys/types.h> 40#include <pwd.h> 41#ifdef KRB5 42#include <krb5.h> 43#endif 44#ifdef KRB4 45#include <krb.h> 46#include <kafs.h> 47#endif 48#include <roken.h> 49 50#ifdef KRB5 51static char krb5ccname[128]; 52#endif 53#ifdef KRB4 54static char krbtkfile[128]; 55#endif 56 57/* 58 In some cases is afs_gettktstring called twice (once before 59 afs_verify and once after afs_verify). 60 In some cases (rlogin with access allowed via .rhosts) 61 afs_verify is not called! 62 So we can't rely on correct value in krbtkfile in some 63 cases! 64*/ 65 66static int correct_tkfilename=0; 67static int pag_set=0; 68 69#ifdef KRB4 70static void 71set_krbtkfile(uid_t uid) 72{ 73 snprintf (krbtkfile, sizeof(krbtkfile), "%s%d", TKT_ROOT, (unsigned)uid); 74 krb_set_tkt_string (krbtkfile); 75 correct_tkfilename = 1; 76} 77#endif 78 79/* XXX this has to be the default cache name, since the KRB5CCNAME 80 * environment variable isn't exported by login/xdm 81 */ 82 83#ifdef KRB5 84static void 85set_krb5ccname(uid_t uid) 86{ 87 snprintf (krb5ccname, sizeof(krb5ccname), "FILE:/tmp/krb5cc_%d", uid); 88#ifdef KRB4 89 snprintf (krbtkfile, sizeof(krbtkfile), "%s%d", TKT_ROOT, (unsigned)uid); 90#endif 91 correct_tkfilename = 1; 92} 93#endif 94 95static void 96set_spec_krbtkfile(void) 97{ 98 int fd; 99#ifdef KRB4 100 snprintf (krbtkfile, sizeof(krbtkfile), "%s_XXXXXX", TKT_ROOT); 101 fd = mkstemp(krbtkfile); 102 close(fd); 103 unlink(krbtkfile); 104 krb_set_tkt_string (krbtkfile); 105#endif 106#ifdef KRB5 107 snprintf(krb5ccname, sizeof(krb5ccname),"FILE:/tmp/krb5cc_XXXXXX"); 108 fd=mkstemp(krb5ccname+5); 109 close(fd); 110 unlink(krb5ccname+5); 111#endif 112} 113 114#ifdef KRB5 115static int 116verify_krb5(struct passwd *pwd, 117 char *password, 118 int32_t *exp, 119 int quiet) 120{ 121 krb5_context context; 122 krb5_error_code ret; 123 krb5_ccache ccache; 124 krb5_principal principal; 125 126 ret = krb5_init_context(&context); 127 if (ret) { 128 syslog(LOG_AUTH|LOG_DEBUG, "krb5_init_context failed: %d", ret); 129 goto out; 130 } 131 132 ret = krb5_parse_name (context, pwd->pw_name, &principal); 133 if (ret) { 134 syslog(LOG_AUTH|LOG_DEBUG, "krb5_parse_name: %s", 135 krb5_get_err_text(context, ret)); 136 goto out; 137 } 138 139 set_krb5ccname(pwd->pw_uid); 140 ret = krb5_cc_resolve(context, krb5ccname, &ccache); 141 if(ret) { 142 syslog(LOG_AUTH|LOG_DEBUG, "krb5_cc_resolve: %s", 143 krb5_get_err_text(context, ret)); 144 goto out; 145 } 146 147 ret = krb5_verify_user_lrealm(context, 148 principal, 149 ccache, 150 password, 151 TRUE, 152 NULL); 153 if(ret) { 154 syslog(LOG_AUTH|LOG_DEBUG, "krb5_verify_user: %s", 155 krb5_get_err_text(context, ret)); 156 goto out; 157 } 158 159 if(chown(krb5_cc_get_name(context, ccache), pwd->pw_uid, pwd->pw_gid)) { 160 syslog(LOG_AUTH|LOG_DEBUG, "chown: %s", 161 krb5_get_err_text(context, errno)); 162 goto out; 163 } 164 165#ifdef KRB4 166 { 167 krb5_realm realm = NULL; 168 krb5_boolean get_v4_tgt; 169 170 krb5_get_default_realm(context, &realm); 171 krb5_appdefault_boolean(context, "afskauthlib", 172 realm, 173 "krb4_get_tickets", FALSE, &get_v4_tgt); 174 if (get_v4_tgt) { 175 CREDENTIALS c; 176 krb5_creds mcred, cred; 177 178 krb5_cc_clear_mcred(&mcred); 179 180 krb5_make_principal(context, &mcred.server, realm, 181 "krbtgt", 182 realm, 183 NULL); 184 ret = krb5_cc_retrieve_cred(context, ccache, 0, &mcred, &cred); 185 if(ret == 0) { 186 ret = krb524_convert_creds_kdc_ccache(context, ccache, &cred, &c); 187 if(ret) 188 krb5_warn(context, ret, "converting creds"); 189 else { 190 set_krbtkfile(pwd->pw_uid); 191 tf_setup(&c, c.pname, c.pinst); 192 } 193 memset(&c, 0, sizeof(c)); 194 krb5_free_cred_contents(context, &cred); 195 } else 196 syslog(LOG_AUTH|LOG_DEBUG, "krb5_cc_retrieve_cred: %s", 197 krb5_get_err_text(context, ret)); 198 199 krb5_free_principal(context, mcred.server); 200 } 201 free (realm); 202 if (!pag_set && k_hasafs()) { 203 k_setpag(); 204 pag_set = 1; 205 } 206 207 if (pag_set) 208 krb5_afslog_uid_home(context, ccache, NULL, NULL, 209 pwd->pw_uid, pwd->pw_dir); 210 } 211#endif 212 out: 213 if(ret && !quiet) 214 printf ("%s\n", krb5_get_err_text (context, ret)); 215 return ret; 216} 217#endif 218 219#ifdef KRB4 220static int 221verify_krb4(struct passwd *pwd, 222 char *password, 223 int32_t *exp, 224 int quiet) 225{ 226 int ret = 1; 227 char lrealm[REALM_SZ]; 228 229 if (krb_get_lrealm (lrealm, 1) != KFAILURE) { 230 set_krbtkfile(pwd->pw_uid); 231 ret = krb_verify_user (pwd->pw_name, "", lrealm, password, 232 KRB_VERIFY_SECURE, NULL); 233 if (ret == KSUCCESS) { 234 if (!pag_set && k_hasafs()) { 235 k_setpag (); 236 pag_set = 1; 237 } 238 if (pag_set) 239 krb_afslog_uid_home (0, 0, pwd->pw_uid, pwd->pw_dir); 240 } else if (!quiet) 241 printf ("%s\n", krb_get_err_text (ret)); 242 } 243 return ret; 244} 245#endif 246 247int 248afs_verify(char *name, 249 char *password, 250 int32_t *exp, 251 int quiet) 252{ 253 int ret = 1; 254 struct passwd *pwd = k_getpwnam (name); 255 256 if(pwd == NULL) 257 return 1; 258 259 if (!pag_set && k_hasafs()) { 260 k_setpag(); 261 pag_set=1; 262 } 263 264 if (ret) 265 ret = unix_verify_user (name, password); 266#ifdef KRB5 267 if (ret) 268 ret = verify_krb5(pwd, password, exp, quiet); 269#endif 270#ifdef KRB4 271 if(ret) 272 ret = verify_krb4(pwd, password, exp, quiet); 273#endif 274 return ret; 275} 276 277char * 278afs_gettktstring (void) 279{ 280 char *ptr; 281 struct passwd *pwd; 282 283 if (!correct_tkfilename) { 284 ptr = getenv("LOGNAME"); 285 if (ptr != NULL && ((pwd = getpwnam(ptr)) != NULL)) { 286 set_krb5ccname(pwd->pw_uid); 287#ifdef KRB4 288 set_krbtkfile(pwd->pw_uid); 289 if (!pag_set && k_hasafs()) { 290 k_setpag(); 291 pag_set=1; 292 } 293#endif 294 } else { 295 set_spec_krbtkfile(); 296 } 297 } 298#ifdef KRB5 299 esetenv("KRB5CCNAME",krb5ccname,1); 300#endif 301#ifdef KRB4 302 esetenv("KRBTKFILE",krbtkfile,1); 303 return krbtkfile; 304#else 305 return ""; 306#endif 307} 308