1/* MODULE: auth_krb4 */ 2 3/* COPYRIGHT 4 * Copyright (c) 1997 Messaging Direct Ltd. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY MESSAGING DIRECT LTD. ``AS IS'' AND ANY 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MESSAGING DIRECT LTD. OR 20 * ITS EMPLOYEES OR AGENTS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 23 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 25 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 26 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 27 * DAMAGE. 28 * END COPYRIGHT */ 29 30#ifdef __GNUC__ 31#ident "$Id: auth_krb4.c,v 1.9 2006/01/24 00:16:03 snsimon Exp $" 32#endif 33 34/* PUBLIC DEPENDENCIES */ 35#include <unistd.h> 36#include "mechanisms.h" 37#include "globals.h" 38#include "cfile.h" 39#include "krbtf.h" 40 41#ifdef AUTH_KRB4 42 43# include <krb.h> 44 45# ifdef WITH_DES 46# ifdef WITH_SSL_DES 47# include <openssl/des.h> 48# else 49# include <des.h> 50# endif /* WITH_SSL_DES */ 51# endif /* WITH_DES */ 52 53#endif /* AUTH_KRB4 */ 54 55#include <errno.h> 56#include <stdio.h> 57#include <stdlib.h> 58#include <string.h> 59#include <syslog.h> 60#include <sys/stat.h> 61#include "auth_krb4.h" 62 63#ifdef DEADCODE 64extern int swap_bytes; /* from libkrb.a */ 65#endif /* DEADCODE */ 66/* END PUBLIC DEPENDENCIES */ 67 68/* PRIVATE DEPENDENCIES */ 69#ifdef AUTH_KRB4 70static char default_realm[REALM_SZ]; 71static cfile config = 0; 72static char myhostname[BUFSIZ]; /* Is BUFSIZ right here? */ 73static char *srvtabname = ""; /* "" means "system default srvtab" */ 74static char *verify_principal = "rcmd"; /* A principal in the default srvtab */ 75#endif /* AUTH_KRB4 */ 76/* END PRIVATE DEPENDENCIES */ 77 78#define TF_NAME_LEN 128 79 80/* Kerberos for Macintosh doesn't define this, so we will. (Thanks Fink!) */ 81#ifndef KRB_TICKET_GRANTING_TICKET 82#define KRB_TICKET_GRANTING_TICKET "krbtgt" 83#endif /* !defined(KRB_TICKET_GRANTING_TICKET) */ 84 85 86/* FUNCTION: auth_krb4_init */ 87 88/* SYNOPSIS 89 * Initialize the Kerberos IV authentication environment. 90 * 91 * krb4 proxy authentication has a side effect of creating a ticket 92 * file for the user we are authenticating. We keep these in a private 93 * directory so as not to override a system ticket file that may be 94 * in use. 95 * 96 * This function tries to create the directory, and initializes the 97 * global variable tf_dir with the pathname of the directory. 98 * END SYNOPSIS */ 99 100int /* R: -1 on failure, else 0 */ 101auth_krb4_init ( 102 /* PARAMETERS */ 103 void /* no parameters */ 104 /* END PARAMETERS */ 105 ) 106{ 107#ifdef AUTH_KRB4 108 /* VARIABLES */ 109 int rc; /* return code holder */ 110 char *configname = 0; 111 /* END VARIABLES */ 112 113 if (mech_option) 114 configname = mech_option; 115 else if (access(SASLAUTHD_CONF_FILE_DEFAULT, F_OK) == 0) 116 configname = SASLAUTHD_CONF_FILE_DEFAULT; 117 118 if (configname) { 119 char complaint[1024]; 120 121 config = cfile_read(configname, complaint, sizeof(complaint)); 122 if (!config) { 123 syslog(LOG_ERR, "auth_krb4_init %s", complaint); 124 return -1; 125 } 126 } 127 128 if (config) { 129 srvtabname = cfile_getstring(config, "krb4_srvtab", srvtabname); 130 verify_principal = cfile_getstring(config, "krb4_verify_principal", 131 verify_principal); 132 } 133 134 if (krbtf_init() == -1) { 135 syslog(LOG_ERR, "auth_krb4_init krbtf_init failed"); 136 return -1; 137 } 138 139 rc = krb_get_lrealm(default_realm, 1); 140 if (rc) { 141 syslog(LOG_ERR, "auth_krb4: krb_get_lrealm: %s", 142 krb_get_err_text(rc)); 143 return -1; 144 } 145 146 if (gethostname(myhostname, sizeof(myhostname)) < 0) { 147 syslog(LOG_ERR, "auth_krb4: gethoanem(): %m"); 148 return -1; 149 } 150 myhostname[sizeof(myhostname) - 1] = '\0'; 151 152 return 0; 153#else /* ! AUTH_KRB4 */ 154 return -1; 155#endif /* ! AUTH_KRB4 */ 156} 157 158/* END FUNCTION: auth_krb4_init */ 159 160/* FUNCTION: auth_krb4 */ 161 162/* SYNOPSIS 163 * Authenticate against Kerberos IV. 164 * END SYNOPSIS */ 165 166#ifdef AUTH_KRB4 167 168char * /* R: allocated response string */ 169auth_krb4 ( 170 /* PARAMETERS */ 171 const char *login, /* I: plaintext authenticator */ 172 const char *password, /* I: plaintext password */ 173 const char *service, 174 const char *realm_in 175 /* END PARAMETERS */ 176 ) 177{ 178 /* VARIABLES */ 179 char aname[ANAME_SZ]; /* Kerberos principal */ 180 const char *realm; /* Kerberos realm to authenticate in */ 181 int rc; /* return code */ 182 char tf_name[TF_NAME_LEN]; /* Ticket file name */ 183 char *instance, *user_specified; 184 KTEXT_ST ticket; 185 AUTH_DAT kdata; 186 /* END VARIABLES */ 187 188 /* 189 * Make sure we have a password. If this is NULL the call 190 * to krb_get_pw_in_tkt below would try to prompt for 191 * one interactively. 192 */ 193 if (password == NULL) { 194 syslog(LOG_ERR, "auth_krb4: NULL password?"); 195 return strdup("NO saslauthd internal error"); 196 } 197 198 if (krbtf_name(tf_name, sizeof(tf_name)) != 0) { 199 syslog(LOG_ERR, "auth_krb4: could not generate ticket file name"); 200 return strdup("NO saslauthd internal error"); 201 } 202 krb_set_tkt_string(tf_name); 203 204 strncpy(aname, login, ANAME_SZ-1); 205 aname[ANAME_SZ-1] = '\0'; 206 207 instance = ""; 208 209 if (config) { 210 char keyname[1024]; 211 212 snprintf(keyname, sizeof(keyname), "krb4_%s_instance", service); 213 instance = cfile_getstring(config, keyname, ""); 214 } 215 216 user_specified = strchr(aname, '.'); 217 if (user_specified) { 218 if (instance && instance[0]) { 219 /* sysadmin specified a (mandatory) instance */ 220 if (strcmp(user_specified + 1, instance)) { 221 return strdup("NO saslauthd principal name error"); 222 } 223 /* nuke instance from "aname"-- matches what's already in "instance" */ 224 *user_specified = '\0'; 225 } else { 226 /* sysadmin has no preference, so we shift 227 * instance name from "aname" to "instance" 228 */ 229 *user_specified = '\0'; 230 instance = user_specified + 1; 231 } 232 } 233 234 if(realm_in && *realm_in != '\0') { 235 realm = realm_in; 236 } else { 237 realm = default_realm; 238 } 239 240 rc = krb_get_pw_in_tkt(aname, instance, realm, 241 KRB_TICKET_GRANTING_TICKET, 242 realm, 1, password); 243 244 if (rc == INTK_BADPW || rc == KDC_PR_UNKNOWN) { 245 return strdup("NO"); 246 } else if (rc != KSUCCESS) { 247 syslog(LOG_ERR, "ERROR: auth_krb4: krb_get_pw_in_tkt: %s", 248 krb_get_err_text(rc)); 249 250 return strdup("NO saslauthd internal error"); 251 } 252 253 /* if the TGT wasn't spoofed, it should entitle us to an rcmd ticket... */ 254 rc = krb_mk_req(&ticket, verify_principal, myhostname, default_realm, 0); 255 256 if (rc != KSUCCESS) { 257 syslog(LOG_ERR, "ERROR: auth_krb4: krb_get_pw_in_tkt: %s", 258 krb_get_err_text(rc)); 259 dest_tkt(); 260 return strdup("NO saslauthd internal error"); 261 } 262 263 /* .. and that ticket should match our secret host key */ 264 rc = krb_rd_req(&ticket, verify_principal, myhostname, 0, &kdata, srvtabname); 265 266 if (rc != RD_AP_OK) { 267 syslog(LOG_ERR, "ERROR: auth_krb4: krb_rd_req:%s", 268 krb_get_err_text(rc)); 269 dest_tkt(); 270 return strdup("NO saslauthd internal error"); 271 } 272 273 dest_tkt(); 274 275 return strdup("OK"); 276} 277 278#else /* ! AUTH_KRB4 */ 279 280char * 281auth_krb4 ( 282 const char *login __attribute__((unused)), 283 const char *password __attribute__((unused)), 284 const char *service __attribute__((unused)), 285 const char *realm __attribute__((unused)) 286 ) 287{ 288 return NULL; 289} 290 291#endif /* ! AUTH_KRB4 */ 292 293/* END FUNCTION: auth_krb4 */ 294 295/* END MODULE: auth_krb4 */ 296