1 /* MODULE: auth_krb4 */
4 * Copyright (c) 1997 Messaging Direct Ltd.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
31 #ident "$Id: auth_krb4.c,v 1.12 2005/02/01 12:26:34 mel Exp $"
34 /* PUBLIC DEPENDENCIES */
36 #include "mechanisms.h"
47 # include <openssl/des.h>
50 # endif /* WITH_SSL_DES */
51 # endif /* WITH_DES */
53 #endif /* AUTH_KRB4 */
61 #include "auth_krb4.h"
64 extern int swap_bytes; /* from libkrb.a */
66 /* END PUBLIC DEPENDENCIES */
68 /* PRIVATE DEPENDENCIES */
70 static char default_realm[REALM_SZ];
71 static cfile config = 0;
72 static char myhostname[BUFSIZ]; /* Is BUFSIZ right here? */
73 static char *srvtabname = ""; /* "" means "system default srvtab" */
74 static char *verify_principal = "rcmd"; /* A principal in the default srvtab */
75 #endif /* AUTH_KRB4 */
76 /* END PRIVATE DEPENDENCIES */
78 #define TF_NAME_LEN 128
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) */
86 /* FUNCTION: auth_krb4_init */
89 * Initialize the Kerberos IV authentication environment.
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
96 * This function tries to create the directory, and initializes the
97 * global variable tf_dir with the pathname of the directory.
100 int /* R: -1 on failure, else 0 */
103 void /* no parameters */
109 int rc; /* return code holder */
110 char *configname = 0;
114 configname = mech_option;
115 else if (access(SASLAUTHD_CONF_FILE_DEFAULT, F_OK) == 0)
116 configname = SASLAUTHD_CONF_FILE_DEFAULT;
119 char complaint[1024];
121 config = cfile_read(configname, complaint, sizeof(complaint));
123 syslog(LOG_ERR, "auth_krb4_init %s", complaint);
129 srvtabname = cfile_getstring(config, "krb4_srvtab", srvtabname);
130 verify_principal = cfile_getstring(config, "krb4_verify_principal",
134 if (krbtf_init() == -1) {
135 syslog(LOG_ERR, "auth_krb4_init krbtf_init failed");
139 rc = krb_get_lrealm(default_realm, 1);
141 syslog(LOG_ERR, "auth_krb4: krb_get_lrealm: %s",
142 krb_get_err_text(rc));
146 if (gethostname(myhostname, sizeof(myhostname)) < 0) {
147 syslog(LOG_ERR, "auth_krb4: gethoanem(): %m");
150 myhostname[sizeof(myhostname) - 1] = '\0';
153 #else /* ! AUTH_KRB4 */
155 #endif /* ! AUTH_KRB4 */
158 /* END FUNCTION: auth_krb4_init */
160 /* FUNCTION: auth_krb4 */
163 * Authenticate against Kerberos IV.
168 char * /* R: allocated response string */
171 const char *login, /* I: plaintext authenticator */
172 const char *password, /* I: plaintext password */
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;
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
193 if (password == NULL) {
194 syslog(LOG_ERR, "auth_krb4: NULL password?");
195 return strdup("NO saslauthd internal error");
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");
202 krb_set_tkt_string(tf_name);
204 strncpy(aname, login, ANAME_SZ-1);
205 aname[ANAME_SZ-1] = '\0';
212 snprintf(keyname, sizeof(keyname), "krb4_%s_instance", service);
213 instance = cfile_getstring(config, keyname, "");
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");
223 /* nuke instance from "aname"-- matches what's already in "instance" */
224 *user_specified = '\0';
226 /* sysadmin has no preference, so we shift
227 * instance name from "aname" to "instance"
229 *user_specified = '\0';
230 instance = user_specified + 1;
234 if(realm_in && *realm_in != '\0') {
237 realm = default_realm;
240 rc = krb_get_pw_in_tkt(aname, instance, realm,
241 KRB_TICKET_GRANTING_TICKET,
244 if (rc == INTK_BADPW || rc == KDC_PR_UNKNOWN) {
246 } else if (rc != KSUCCESS) {
247 syslog(LOG_ERR, "ERROR: auth_krb4: krb_get_pw_in_tkt: %s",
248 krb_get_err_text(rc));
250 return strdup("NO saslauthd internal error");
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);
256 if (rc != KSUCCESS) {
257 syslog(LOG_ERR, "ERROR: auth_krb4: krb_get_pw_in_tkt: %s",
258 krb_get_err_text(rc));
260 return strdup("NO saslauthd internal error");
263 /* .. and that ticket should match our secret host key */
264 rc = krb_rd_req(&ticket, verify_principal, myhostname, 0, &kdata, srvtabname);
266 if (rc != RD_AP_OK) {
267 syslog(LOG_ERR, "ERROR: auth_krb4: krb_rd_req:%s",
268 krb_get_err_text(rc));
270 return strdup("NO saslauthd internal error");
278 #else /* ! AUTH_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))
291 #endif /* ! AUTH_KRB4 */
293 /* END FUNCTION: auth_krb4 */
295 /* END MODULE: auth_krb4 */