sss_krb5.c revision f2999e1d624d45e0142f39317461a6a1c996efb2
/*
Authors:
Sumit Bose <sbose@redhat.com>
Copyright (C) 2009-2010 Red Hat
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <errno.h>
#include <talloc.h>
#include "config.h"
#include "util/sss_krb5.h"
const char *hostname,
const char *desired_realm,
const char *keytab_name,
char **_principal,
char **_primary,
char **_realm)
{
krb5_error_code kerr = 0;
int i = 0;
char *principal_string;
const char *realm_name;
int realm_len;
/**
* Priority of lookup:
* - our.hostname@REALM or host/our.hostname@REALM depending on the input
* - our.hostname$@REALM (AD domain)
* - foobar$@REALM (AD domain)
* - host/our.hostname@REALM
* - pick the first principal in the keytab
*/
"host/*", NULL};
if (!tmp_ctx) {
return ENOMEM;
}
if (kerr) {
goto done;
}
if (keytab_name != NULL) {
} else {
}
if (kerr) {
("Failed to read keytab [%s]: %s\n",
goto done;
}
if (!desired_realm) {
desired_realm = "*";
}
if (!hostname) {
hostname = "*";
}
do {
if (primary_patterns[i]) {
goto done;
}
} else {
}
if (realm_patterns[i]) {
goto done;
}
} else {
}
&client_princ);
if (kerr == 0) {
break;
}
if (client_princ != NULL) {
client_princ = NULL;
}
i++;
if (kerr == 0) {
if (_principal) {
if (kerr) {
goto done;
}
if (!*_principal) {
goto done;
}
}
if (_primary) {
if (kerr) {
goto done;
}
if (!*_primary) {
goto done;
}
}
if (_realm) {
&realm_len);
if (!*_realm) {
goto done;
}
}
} else {
}
done:
if (client_princ != NULL) {
client_princ = NULL;
}
return ret;
}
{
bool found;
char *kt_principal;
if (krberr) {
("Cannot read keytab [%s].\n", KEYTAB_CLEAN_NAME));
"Unable to create GSSAPI-encrypted LDAP "
"connection.",
return EIO;
}
found = false;
if (krberr) {
("Could not parse keytab entry\n"));
return EIO;
}
found = true;
}
if (krberr) {
/* This should never happen. The API docs for this function
* specify only success for this function
*/
/* This is non-fatal, so we'll continue here */
}
if (found) {
break;
}
}
if (krberr) {
DEBUG(0, ("Could not close keytab.\n"));
return EIO;
}
if (!found) {
("Principal [%s] not found in keytab [%s]\n",
"Principal [%s] was not found. "
"Unable to create GSSAPI-encrypted LDAP connection.",
return EFAULT;
}
return EOK;
}
/**
* We only have primary and instances stored separately, we need to
* join them to one string and compare that string.
*
* @param ctx kerberos context
* @param principal principal we want to match
* @param pattern_primary primary part of the principal we want to
* perform matching against. It is possible to use * wildcard
* at the beginning or at the end of the string. If NULL, it
* will act as "*"
* @param pattern_realm realm part of the principal we want to perform
* the matching against. If NULL, it will act as "*"
*/
const char *pattern_primary,
const char *pattern_realm)
{
char *primary_str = NULL;
int primary_str_len = 0;
int tmp_len;
int len_diff;
const char *realm_name;
int realm_len;
bool ret = false;
if (!tmp_ctx) {
return false;
}
if (pattern_primary) {
mode = MODE_PREFIX;
} else if (pattern_primary[0] == '*') {
mode = MODE_POSTFIX;
}
&primary);
if ((mode == MODE_NORMAL &&
(mode == MODE_PREFIX &&
(mode == MODE_POSTFIX &&
goto done;
}
}
ret = true;
}
done:
return ret;
}
const char *pattern_primary,
const char *pattern_realm,
{
bool principal_found = false;
if (kerr != 0) {
return kerr;
}
if (principal_found) {
break;
}
if (kerr != 0) {
}
}
/* Close the keytab here. Even though we're using cursors, the file
* handle is stored in the krb5_keytab structure, and it gets
* overwritten by other keytab calls, creating a leak. */
if (kerr != 0) {
goto done;
}
if (!principal_found) {
("No principal matching %s@%s found in keytab.\n",
goto done;
}
/* check if we got any errors from krb5_kt_next_entry */
goto done;
}
if (kerr != 0) {
goto done;
}
kerr = 0;
done:
if (kerr_d != 0) {
}
return kerr;
}
{
#ifdef HAVE_KRB5_GET_ERROR_MESSAGE
#else
int ret;
char *s = NULL;
int size = sizeof("Kerberos error [XXXXXXXXXXXX]");
if (s == NULL) {
return NULL;
}
return NULL;
}
return s;
#endif
}
{
#ifdef HAVE_KRB5_GET_ERROR_MESSAGE
#else
free(s);
#endif
return;
}
{
#else
return ENOMEM;
}
return 0;
#endif
}
{
#else
#endif
return;
}
{
#ifdef HAVE_KRB5_FREE_UNPARSED_NAME
#else
}
#endif
}
const char *client_princ_str, bool *result)
{
char *server_name = NULL;
*result = false;
return ENOMEM;
}
if (server_name == NULL) {
goto done;
}
if (krberr != 0) {
goto done;
}
if (krberr != 0) {
goto done;
}
if (krberr != 0) {
krberr = 0;
goto done;
}
*result = true;
}
krberr = 0;
done:
if (client_principal != NULL) {
}
if (server_principal != NULL) {
}
return krberr;
}
void *data)
{
#else
return 0;
#endif
}
{
*use_fast = false;
*use_fast = true;
} else {
"please use never, try, or demand.\n");
return EINVAL;
}
return EOK;
#else
"Please remove option krb5_use_fast.\n");
return EINVAL;
#endif
}
const char *fast_ccache_name)
{
#else
return 0;
#endif
}
{
#else
return 0;
#endif
}
#ifndef HAVE_KRB5_UNPARSE_NAME_FLAGS
#ifndef REALM_SEP
#define REALM_SEP '@'
#endif
#ifndef COMPONENT_SEP
#define COMPONENT_SEP '/'
#endif
static int
{
int j;
char *q = dest;
if (flags & KRB5_PRINCIPAL_UNPARSE_DISPLAY) {
}
switch (*cp) {
case REALM_SEP:
if (no_realm) {
*q++ = *cp;
break;
}
case COMPONENT_SEP:
case '\\':
*q++ = '\\';
*q++ = *cp;
break;
case '\t':
*q++ = '\\';
*q++ = 't';
break;
case '\n':
*q++ = '\\';
*q++ = 'n';
break;
case '\b':
*q++ = '\\';
*q++ = 'b';
break;
case '\0':
*q++ = '\\';
*q++ = '0';
break;
default:
*q++ = *cp;
}
}
return q - dest;
}
static int
{
int j;
if ((flags & KRB5_PRINCIPAL_UNPARSE_DISPLAY) == 0) {
*cp == COMPONENT_SEP ||
size++;
}
return size;
}
#endif /* HAVE_KRB5_UNPARSE_NAME_FLAGS */
{
#ifdef HAVE_KRB5_UNPARSE_NAME_FLAGS
#else
char *cp, *q;
int i;
int length;
unsigned int totalsize = 0;
char *default_realm = NULL;
krb5_error_code ret = 0;
return KRB5_PARSE_MALFORMED;
if (flags & KRB5_PRINCIPAL_UNPARSE_SHORT) {
/* omit realm if local realm */
if (ret != 0)
goto cleanup;
}
if ((flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) == 0) {
flags);
totalsize++;
}
for (i = 0; i < (int) nelem; i++) {
totalsize++;
}
if (nelem == 0)
totalsize++;
if (!*name) {
goto cleanup;
}
q = *name;
for (i = 0; i < (int) nelem; i++) {
q += sss_krb5_copy_component_quoting(q,
i),
flags);
*q++ = COMPONENT_SEP;
}
if (i > 0)
q--;
if ((flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) == 0) {
*q++ = REALM_SEP;
}
*q++ = '\0';
return ret;
#endif /* HAVE_KRB5_UNPARSE_NAME_FLAGS */
}
int canonicalize)
{
/* FIXME: The extra check for HAVE_KRB5_TICKET_TIMES is a workaround due to Heimdal
* defining krb5_get_init_creds_opt_set_canonicalize() with a different set of
* arguments. We should use a better configure check in the future.
*/
#if defined(HAVE_KRB5_GET_INIT_CREDS_OPT_SET_CANONICALIZE) && defined(HAVE_KRB5_TICKET_TIMES)
#else
#endif
}
{
}
#else
{
if (data) {
} else {
*len = 0;
}
}
#endif
{
}
#else
{
}
#endif
#define SSS_KRB5_FILE "FILE:"
#define SSS_KRB5_DIR "DIR:"
enum sss_krb5_cc_type
sss_krb5_get_type(const char *full_location)
{
if (!full_location) {
return SSS_KRB5_TYPE_UNKNOWN;
}
sizeof(SSS_KRB5_FILE)-1) == 0) {
return SSS_KRB5_TYPE_FILE;
}
#ifdef HAVE_KRB5_DIRCACHE
sizeof(SSS_KRB5_DIR)-1) == 0) {
return SSS_KRB5_TYPE_DIR;
}
#endif /* HAVE_KRB5_DIRCACHE */
else if (full_location[0] == '/') {
return SSS_KRB5_TYPE_FILE;
}
return SSS_KRB5_TYPE_UNKNOWN;
}
const char *
sss_krb5_residual_by_type(const char *full_location,
enum sss_krb5_cc_type type)
{
switch (type) {
case SSS_KRB5_TYPE_FILE:
if (full_location[0] == '/') {
offset = 0;
} else {
}
break;
#ifdef HAVE_KRB5_DIRCACHE
case SSS_KRB5_TYPE_DIR:
break;
#endif /* HAVE_KRB5_DIRCACHE */
default:
return NULL;
}
return full_location + offset;
}
const char *
sss_krb5_cc_file_path(const char *full_location)
{
enum sss_krb5_cc_type cc_type;
const char *residual;
switch(cc_type) {
case SSS_KRB5_TYPE_FILE:
return residual;
#ifdef HAVE_KRB5_DIRCACHE
case SSS_KRB5_TYPE_DIR:
#endif
case SSS_KRB5_TYPE_UNKNOWN:
break;
}
return NULL;
}
const char *
sss_krb5_residual_check_type(const char *full_location,
{
enum sss_krb5_cc_type type;
if (type != expected_type) {
return NULL;
}
}
#ifdef HAVE_KRB5_SET_TRACE_CALLBACK
static void
{
/* Null info means destroy the callback data. */
return;
}
}
{
}
#else /* HAVE_KRB5_SET_TRACE_CALLBACK */
{
return 0;
}
#endif /* HAVE_KRB5_SET_TRACE_CALLBACK */
krb5_authdata *const *ticket_authdata,
krb5_authdata *const *ap_req_authdata,
krb5_authdata ***results)
{
#ifdef HAVE_KRB5_FIND_AUTHDATA
#else
return ENOTSUP;
#endif
}
{
#ifdef HAVE_PAC_RESPONDER
int ret;
if (kerr != 0) {
goto done;
}
if (kerr != 0) {
goto done;
}
if (kerr != 0) {
goto done;
}
if (kerr != 0) {
goto done;
}
goto done;
}
goto done;
}
if (kerr != 0) {
goto done;
}
&entry);
if (kerr != 0) {
goto done;
}
if (kerr != 0) {
goto done;
}
"sss_pac_make_request will most certainly fail.\n"));
}
kerr = 0;
done:
if (kerr != 0) {
}
}
}
return kerr;
#else
return ENOTSUP;
#endif
}