/* MODULE: krbtf */
/*
* Copyright (c) 2001-2016 Carnegie Mellon University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any other legal
* details, please contact
* Carnegie Mellon University
* Center for Technology Transfer and Enterprise Creation
* 4615 Forbes Avenue
* Suite 302
* Pittsburgh, PA 15213
* (412) 268-7393, fax: (412) 268-7395
* innovation@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Dec 4, 2002 by Dave Eckhardt <davide+receptionist@cs.cmu.edu>
* This is inspired by code which was identical in both
* auth_krb4.c and auth_krb5.c. This code is shared
* between the two implementations, contains protection
* against a race condition, and, when possible, uses
* Heimdal krb5's memory-only credential caches to avoid
* needless disk i/o.
*/
/* PUBLIC DEPENDENCIES */
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#ifdef SASLAUTHD_THREADED /* is this really used??? */
#include <pthread.h>
#endif /* SASLAUTHD_THREADED */
#include "mechanisms.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <syslog.h>
#ifdef AUTH_KRB4
#include <auth_krb4.h>
#define WANT_KRBTF
#endif /* WANT_KRBTF */
#ifdef AUTH_KRB5
#include <auth_krb5.h>
#define WANT_KRBTF
#endif /* WANT_KRBTF */
#ifdef WANT_KRBTF
/* PRIVATE DEPENDENCIES */
/* globals */
/* privates */
static char tf_dir[] = PATH_SASLAUTHD_RUNDIR "/.tf";
static char *tfn_cookie = 0;
static int tfn_cookie_len = 0;
static char pidstring[80];
size_t pidstring_len = 0;
/* END PRIVATE DEPENDENCIES */
#endif /* WANT_KRBTF */
/* FUNCTION: krbtf_init */
/* SYNOPSIS
* Initialize the Kerberos IV/V ticket-file/credential-cache common code
*
* When possible, use Heimdal krb5's memory-only credential caches--
* this saves a whole bunch of useless disk i/o's to create and destroy
* a file which we don't want anybody to see anyway.
*
* If not, this function will create a private directory for ticket
* files and cache getpid() for later use. Therefore, we must be
* called AFTER main() does whatever fork()ing it wants.
*
* END SYNOPSIS */
int /* R: -1 on failure, else 0 */
krbtf_init (
/* PARAMETERS */
void /* no parameters */
/* END PARAMETERS */
)
{
#ifdef WANT_KRBTF
/* VARIABLES */
int rc; /* return code holder */
struct stat sb; /* stat() work area */
/* END VARIABLES */
authmech_t *authmech;
#ifdef AUTH_KRB5
for (authmech = mechanisms; authmech->name != NULL; authmech++ ) {
if (authmech->initialize != auth_krb5_init) continue;
/* This execution is using krb5 */
/* Both MIT krb5 and Heimdal support MEMORY: ccaches */
tfn_cookie = "MEMORY:0";
tfn_cookie_len = strlen(tfn_cookie);
return 0;
}
#endif /* AUTH_KRB5 */
if (((rc = mkdir(tf_dir, 0700)) == 0) || (errno == EEXIST)) {
if ((rc = lstat(tf_dir, &sb)) == 0) {
if (sb.st_mode & S_IFLNK) {
syslog(LOG_ERR, "krbtf_init: %s is a symbolic link", tf_dir);
return -1;
}
}
}
if (rc != 0) {
syslog(LOG_ERR, "krbtf_init %s: %m", tf_dir);
return -1;
}
/* cache getpid() for use in filenames */
if ((pidstring_len = snprintf(pidstring, sizeof (pidstring), "%d", getpid())) >= sizeof (pidstring)) {
syslog(LOG_ERR, "krbtf_init pidstring too long(!?)");
return -1;
}
return 0;
#else /* WANT_KRBTF */
syslog(LOG_ERR, "krbtf_init: not compiled!");
return -1;
#endif /* WANT_KRBTF */
}
/* END FUNCTION: krbtf_init */
/* FUNCTION: krbtf_name */
/* SYNOPSIS
* Spit a ticket-file/credentical-cache name into caller's array.
*
* If we can, emit the magic cookie for a memory-only krb5 ccname
* END SYNOPSIS */
int /* R: -1 on failure, else 0 */
krbtf_name (
/* PARAMETERS */
char *tfname, /* O: where caller wants name */
int len /* I: available length */
/* END PARAMETERS */
)
{
#ifdef WANT_KRBTF
if (tfn_cookie_len) {
if (tfn_cookie_len + 1 > len) {
syslog(LOG_ERR, "krbtf_name: cookie name (%s) too long", tfn_cookie);
return -1;
}
strcpy(tfname, tfn_cookie);
} else {
int dir_len = sizeof (tf_dir) - 1; /* don't count the null */
int want_len = dir_len + 1 + pidstring_len + 1;
if (want_len > len) {
syslog(LOG_ERR, "krbtf_name: need room for %d bytes, got %d", want_len, len);
return -1;
}
strcpy(tfname, tf_dir);
tfname += dir_len; len -= dir_len;
*tfname++ = '/'; len--;
strcpy(tfname, pidstring);
#ifdef SASLAUTHD_THREADED /* is this really used??? */
tfname += pidstring_len;
len -= pidstring_len;
if (snprintf(tfname, len, "_%d", pthread_self() >= len)) {
syslog(LOG_ERR, "krbtf_name: no room for thread id");
return -1;
}
#endif /* SASLAUTHD_THREADED */
}
return 0;
#else /* WANT_KRBTF */
syslog(LOG_ERR, "krbtf_name: not compiled!");
return -1;
#endif /* WANT_KRBTF */
}
/* END FUNCTION: krbtf_name */
/* END MODULE: krbtf */