1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-11 05:18:09 +03:00
ldap and krb5 configure tests
libads/*.c and libcli/raw/clikrb5.c from 3.0

metze
(This used to be commit 64b5bfcd73)
This commit is contained in:
Stefan Metzmacher 2004-02-01 11:26:25 +00:00
parent 0d90f4b47b
commit 670ccc7d64
20 changed files with 1514 additions and 784 deletions

View File

@ -12,7 +12,7 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
LIBS=@LIBS@
LIBS=@LIBS@ @LDAP_LIBS@ @KRB5_LIBS@
CC=@CC@
SHLD=@SHLD@
CFLAGS=@CFLAGS@

107
source4/aclocal.m4 vendored
View File

@ -135,6 +135,113 @@ AC_DEFUN(AC_LIBTESTFUNC,
esac
])
# AC_CHECK_LIB_EXT(LIBRARY, [EXT_LIBS], [FUNCTION],
# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND],
# [ADD-ACTION-IF-FOUND],[OTHER-LIBRARIES])
# ------------------------------------------------------
#
# Use a cache variable name containing both the library and function name,
# because the test really is for library $1 defining function $3, not
# just for library $1. Separate tests with the same $1 and different $3s
# may have different results.
#
# Note that using directly AS_VAR_PUSHDEF([ac_Lib], [ac_cv_lib_$1_$3])
# is asking for trouble, since AC_CHECK_LIB($lib, fun) would give
# ac_cv_lib_$lib_fun, which is definitely not what was meant. Hence
# the AS_LITERAL_IF indirection.
#
# FIXME: This macro is extremely suspicious. It DEFINEs unconditionally,
# whatever the FUNCTION, in addition to not being a *S macro. Note
# that the cache does depend upon the function we are looking for.
#
# It is on purpose we used `ac_check_lib_ext_save_LIBS' and not just
# `ac_save_LIBS': there are many macros which don't want to see `LIBS'
# changed but still want to use AC_CHECK_LIB_EXT, so they save `LIBS'.
# And ``ac_save_LIBS' is too tempting a name, so let's leave them some
# freedom.
AC_DEFUN([AC_CHECK_LIB_EXT],
[
AH_CHECK_LIB_EXT([$1])
ac_check_lib_ext_save_LIBS=$LIBS
LIBS="-l$1 $$2 $7 $LIBS"
AS_LITERAL_IF([$1],
[AS_VAR_PUSHDEF([ac_Lib_ext], [ac_cv_lib_ext_$1])],
[AS_VAR_PUSHDEF([ac_Lib_ext], [ac_cv_lib_ext_$1''])])dnl
m4_ifval([$3],
[
AH_CHECK_FUNC_EXT([$3])
AS_LITERAL_IF([$1],
[AS_VAR_PUSHDEF([ac_Lib_func], [ac_cv_lib_ext_$1_$3])],
[AS_VAR_PUSHDEF([ac_Lib_func], [ac_cv_lib_ext_$1''_$3])])dnl
AC_CACHE_CHECK([for $3 in -l$1], ac_Lib_func,
[AC_TRY_LINK_FUNC($3,
[AS_VAR_SET(ac_Lib_func, yes);
AS_VAR_SET(ac_Lib_ext, yes)],
[AS_VAR_SET(ac_Lib_func, no);
AS_VAR_SET(ac_Lib_ext, no)])
])
AS_IF([test AS_VAR_GET(ac_Lib_func) = yes],
[AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_$3))])dnl
AS_VAR_POPDEF([ac_Lib_func])dnl
],[
AC_CACHE_CHECK([for -l$1], ac_Lib_ext,
[AC_TRY_LINK_FUNC([main],
[AS_VAR_SET(ac_Lib_ext, yes)],
[AS_VAR_SET(ac_Lib_ext, no)])
])
])
LIBS=$ac_check_lib_ext_save_LIBS
AS_IF([test AS_VAR_GET(ac_Lib_ext) = yes],
[m4_default([$4],
[AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_LIB$1))
case "$$2" in
*-l$1*)
;;
*)
$2="-l$1 $$2"
;;
esac])
[$6]
],
[$5])dnl
AS_VAR_POPDEF([ac_Lib_ext])dnl
])# AC_CHECK_LIB_EXT
# AH_CHECK_LIB_EXT(LIBNAME)
# ---------------------
m4_define([AH_CHECK_LIB_EXT],
[AH_TEMPLATE(AS_TR_CPP(HAVE_LIB$1),
[Define to 1 if you have the `]$1[' library (-l]$1[).])])
# AC_CHECK_FUNCS_EXT(FUNCTION, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
# -----------------------------------------------------------------
dnl check for a function in a $LIBS and $OTHER_LIBS libraries variable.
dnl AC_CHECK_FUNC_EXT(func,OTHER_LIBS,IF-TRUE,IF-FALSE)
AC_DEFUN([AC_CHECK_FUNC_EXT],
[
AH_CHECK_FUNC_EXT($1)
ac_check_func_ext_save_LIBS=$LIBS
LIBS="$2 $LIBS"
AS_VAR_PUSHDEF([ac_var], [ac_cv_func_ext_$1])dnl
AC_CACHE_CHECK([for $1], ac_var,
[AC_LINK_IFELSE([AC_LANG_FUNC_LINK_TRY([$1])],
[AS_VAR_SET(ac_var, yes)],
[AS_VAR_SET(ac_var, no)])])
LIBS=$ac_check_func_ext_save_LIBS
AS_IF([test AS_VAR_GET(ac_var) = yes],
[AC_DEFINE_UNQUOTED(AS_TR_CPP([HAVE_$1])) $3],
[$4])dnl
AS_VAR_POPDEF([ac_var])dnl
])# AC_CHECK_FUNC
# AH_CHECK_FUNC_EXT(FUNCNAME)
# ---------------------
m4_define([AH_CHECK_FUNC_EXT],
[AH_TEMPLATE(AS_TR_CPP(HAVE_$1),
[Define to 1 if you have the `]$1[' function.])])
dnl Define an AC_DEFINE with ifndef guard.
dnl AC_N_DEFINE(VARIABLE [, VALUE])
define(AC_N_DEFINE,

View File

@ -462,7 +462,7 @@ AC_CHECK_HEADERS(sys/param.h ctype.h sys/wait.h sys/resource.h sys/ioctl.h sys/i
AC_CHECK_HEADERS(sys/mman.h sys/filio.h sys/priv.h sys/shm.h string.h strings.h stdlib.h sys/socket.h)
AC_CHECK_HEADERS(sys/mount.h sys/vfs.h sys/fs/s5param.h sys/filsys.h termios.h termio.h)
AC_CHECK_HEADERS(sys/termio.h sys/statfs.h sys/dustat.h sys/statvfs.h stdarg.h sys/sockio.h)
AC_CHECK_HEADERS(security/pam_modules.h security/_pam_macros.h ldap.h lber.h dlfcn.h)
AC_CHECK_HEADERS(security/pam_modules.h security/_pam_macros.h dlfcn.h)
AC_CHECK_HEADERS(sys/syslog.h syslog.h)
#
@ -1815,7 +1815,7 @@ AC_SEARCH_LIBS(crypt, [crypt],
## check checking for truncated salt. Wrapped by the
## $with_pam_for_crypt variable as above --jerry
##
if test $with_pam_for_crypt = no; then
if test x"$with_pam_for_crypt" != x"yes"; then
AC_CACHE_CHECK([for a crypt that needs truncated salt],samba_cv_HAVE_TRUNCATED_SALT,[
crypt_LIBS="$LIBS"
LIBS="$AUTHLIBS $LIBS"

View File

@ -1,9 +1,28 @@
/*
header for ads (active directory) library routines
/*
Unix SMB/CIFS implementation.
header for ads (active directory) library routines
basically this is a wrapper around ldap
basically this is a wrapper around ldap
Copyright (C) Andrew Tridgell 2001-2003
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _ADS_H
#define _ADS_H
typedef struct {
void *ld; /* the active ldap structure */
struct in_addr ldap_ip; /* the ip of the active connection, if any */
@ -38,9 +57,9 @@ typedef struct {
} config;
} ADS_STRUCT;
/* there are 4 possible types of errors the ads subsystem can produce */
enum ads_error_type {ADS_ERROR_KRB5, ADS_ERROR_GSS,
ADS_ERROR_LDAP, ADS_ERROR_SYSTEM, ADS_ERROR_NT};
/* there are 5 possible types of errors the ads subsystem can produce */
enum ads_error_type {ENUM_ADS_ERROR_KRB5, ENUM_ADS_ERROR_GSS,
ENUM_ADS_ERROR_LDAP, ENUM_ADS_ERROR_SYSTEM, ENUM_ADS_ERROR_NT};
typedef struct {
enum ads_error_type error_type;
@ -48,7 +67,7 @@ typedef struct {
int rc;
NTSTATUS nt_status;
} err;
/* For error_type = ADS_ERROR_GSS minor_status describe GSS API error */
/* For error_type = ENUM_ADS_ERROR_GSS minor_status describe GSS API error */
/* Where rc represents major_status of GSS API error */
int minor_status;
} ADS_STATUS;
@ -61,13 +80,13 @@ typedef void **ADS_MODLIST;
/* macros to simplify error returning */
#define ADS_ERROR(rc) ADS_ERROR_LDAP(rc)
#define ADS_ERROR_LDAP(rc) ads_build_error(ADS_ERROR_LDAP, rc, 0)
#define ADS_ERROR_SYSTEM(rc) ads_build_error(ADS_ERROR_SYSTEM, rc?rc:EINVAL, 0)
#define ADS_ERROR_KRB5(rc) ads_build_error(ADS_ERROR_KRB5, rc, 0)
#define ADS_ERROR_GSS(rc, minor) ads_build_error(ADS_ERROR_GSS, rc, minor)
#define ADS_ERROR_NT(rc) ads_build_nt_error(ADS_ERROR_NT,rc)
#define ADS_ERROR_LDAP(rc) ads_build_error(ENUM_ADS_ERROR_LDAP, rc, 0)
#define ADS_ERROR_SYSTEM(rc) ads_build_error(ENUM_ADS_ERROR_SYSTEM, rc?rc:EINVAL, 0)
#define ADS_ERROR_KRB5(rc) ads_build_error(ENUM_ADS_ERROR_KRB5, rc, 0)
#define ADS_ERROR_GSS(rc, minor) ads_build_error(ENUM_ADS_ERROR_GSS, rc, minor)
#define ADS_ERROR_NT(rc) ads_build_nt_error(ENUM_ADS_ERROR_NT,rc)
#define ADS_ERR_OK(status) ((status.error_type == ADS_ERROR_NT) ? NT_STATUS_IS_OK(status.err.nt_status):(status.err.rc == 0))
#define ADS_ERR_OK(status) ((status.error_type == ENUM_ADS_ERROR_NT) ? NT_STATUS_IS_OK(status.err.nt_status):(status.err.rc == 0))
#define ADS_SUCCESS ADS_ERROR(0)
/* time between reconnect attempts */
@ -205,7 +224,11 @@ typedef void **ADS_MODLIST;
#define ADS_AUTH_NO_BIND 0x02
#define ADS_AUTH_ANON_BIND 0x04
#define ADS_AUTH_SIMPLE_BIND 0x08
#define ADS_AUTH_ALLOW_NTLMSSP 0x10
/***************************************
Some krb5 compat stuff
***************************************/
/* Kerberos environment variable names */
#define KRB5_ENV_CCNAME "KRB5CCNAME"
@ -213,3 +236,36 @@ typedef void **ADS_MODLIST;
#if defined(HAVE_ENCTYPE_ARCFOUR_HMAC_MD5)
#define ENCTYPE_ARCFOUR_HMAC ENCTYPE_ARCFOUR_HMAC_MD5
#endif
/* The older versions of heimdal that don't have this
define don't seem to use it anyway. I'm told they
always use a subkey */
#ifndef HAVE_AP_OPTS_USE_SUBKEY
#define AP_OPTS_USE_SUBKEY 0
#endif
#if defined(HAVE_KRB5)
#ifndef HAVE_KRB5_SET_REAL_TIME
krb5_error_code krb5_set_real_time(krb5_context context, int32_t seconds, int32_t microseconds);
#endif
#ifndef HAVE_KRB5_SET_DEFAULT_TGS_KTYPES
krb5_error_code krb5_set_default_tgs_ktypes(krb5_context ctx, const krb5_enctype *enc);
#endif
#if defined(HAVE_KRB5_AUTH_CON_SETKEY) && !defined(HAVE_KRB5_AUTH_CON_SETUSERUSERKEY)
krb5_error_code krb5_auth_con_setuseruserkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock *keyblock);
#endif
/* Samba wrapper function for krb5 functionality. */
void setup_kaddr( krb5_address *pkaddr, struct sockaddr *paddr);
int create_kerberos_key_from_string(krb5_context context, krb5_principal host_princ, krb5_data *password, krb5_keyblock *key, krb5_enctype enctype);
void get_auth_data_from_tkt(DATA_BLOB *auth_data, krb5_ticket *tkt);
krb5_const_principal get_principal_from_tkt(krb5_ticket *tkt);
krb5_error_code krb5_locate_kdc(krb5_context ctx, const krb5_data *realm, struct sockaddr **addr_pp, int *naddrs, int get_masters);
krb5_error_code get_kerberos_allowed_etypes(krb5_context context, krb5_enctype **enctypes);
void free_kerberos_etypes(krb5_context context, krb5_enctype *enctypes);
BOOL get_krb5_smb_session_key(krb5_context context, krb5_auth_context auth_context, DATA_BLOB *session_key, BOOL remote);
#endif /* HAVE_KRB5 */
#endif /* _ADS_H */

View File

@ -339,10 +339,6 @@
#include <stropts.h>
#endif
#ifdef HAVE_POLL_H
#include <poll.h>
#endif
#ifdef HAVE_SYS_CAPABILITY_H
#if defined(BROKEN_REDHAT_7_SYSTEM_HEADERS) && !defined(_I386_STATFS_H)
@ -721,7 +717,6 @@ extern int errno;
#include "../tdb/tdbutil.h"
#include "talloc.h"
#include "nt_status.h"
#include "ads.h"
#include "interfaces.h"
#include "trans2.h"
#include "ioctl.h"
@ -734,6 +729,7 @@ extern int errno;
#include "version.h"
#include "smb.h"
#include "ads.h"
#include "nameserv.h"
#include "secrets.h"
@ -1147,30 +1143,5 @@ time_t timegm(struct tm *tm);
#define VXFS_QUOTA
#endif
#if defined(HAVE_KRB5)
#ifndef KRB5_SET_REAL_TIME
krb5_error_code krb5_set_real_time(krb5_context context, int32_t seconds, int32_t microseconds);
#endif
#ifndef HAVE_KRB5_SET_DEFAULT_TGS_KTYPES
krb5_error_code krb5_set_default_tgs_ktypes(krb5_context ctx, const krb5_enctype *enc);
#endif
#if defined(HAVE_KRB5_AUTH_CON_SETKEY) && !defined(HAVE_KRB5_AUTH_CON_SETUSERUSERKEY)
krb5_error_code krb5_auth_con_setuseruserkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock *keyblock);
#endif
/* Samba wrapper function for krb5 functionality. */
void setup_kaddr( krb5_address *pkaddr, struct sockaddr *paddr);
int create_kerberos_key_from_string(krb5_context context, krb5_principal host_princ, krb5_data *password, krb5_keyblock *key, krb5_enctype enctype);
void get_auth_data_from_tkt(DATA_BLOB *auth_data, krb5_ticket *tkt);
krb5_const_principal get_principal_from_tkt(krb5_ticket *tkt);
krb5_error_code krb5_locate_kdc(krb5_context ctx, const krb5_data *realm, struct sockaddr **addr_pp, int *naddrs, int get_masters);
krb5_error_code get_kerberos_allowed_etypes(krb5_context context, krb5_enctype **enctypes);
void free_kerberos_etypes(krb5_context context, krb5_enctype *enctypes);
BOOL krb5_get_smb_session_key(krb5_context context, krb5_auth_context auth_context, uint8 session_key[16]);
#endif /* HAVE_KRB5 */
#endif /* _INCLUDES_H */

View File

@ -34,7 +34,7 @@ NTSTATUS ads_name_to_sid(ADS_STRUCT *ads,
int count;
ADS_STATUS rc;
void *res = NULL;
char *exp;
char *ldap_exp;
uint32 t;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
char *escaped_name = escape_ldap_string_alloc(name);
@ -45,15 +45,15 @@ NTSTATUS ads_name_to_sid(ADS_STRUCT *ads,
goto done;
}
if (asprintf(&exp, "(|(sAMAccountName=%s)(userPrincipalName=%s@%s))",
if (asprintf(&ldap_exp, "(|(sAMAccountName=%s)(userPrincipalName=%s@%s))",
escaped_name, escaped_name, escaped_realm) == -1) {
DEBUG(1,("ads_name_to_sid: asprintf failed!\n"));
status = NT_STATUS_NO_MEMORY;
goto done;
}
rc = ads_search_retry(ads, &res, exp, attrs);
free(exp);
rc = ads_search_retry(ads, &res, ldap_exp, attrs);
free(ldap_exp);
if (!ADS_ERR_OK(rc)) {
DEBUG(1,("name_to_sid ads_search: %s\n", ads_errstr(rc)));
goto done;
@ -102,7 +102,7 @@ NTSTATUS ads_sid_to_name(ADS_STRUCT *ads,
"sAMAccountType", NULL};
ADS_STATUS rc;
void *msg = NULL;
char *exp = NULL;
char *ldap_exp = NULL;
char *sidstr = NULL;
uint32 atype;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
@ -113,13 +113,13 @@ NTSTATUS ads_sid_to_name(ADS_STRUCT *ads,
goto done;
}
if (asprintf(&exp, "(objectSid=%s)", sidstr) == -1) {
if (asprintf(&ldap_exp, "(objectSid=%s)", sidstr) == -1) {
DEBUG(1,("ads_sid_to_name: asprintf failed!\n"));
status = NT_STATUS_NO_MEMORY;
goto done;
}
rc = ads_search_retry(ads, &msg, exp, attrs);
rc = ads_search_retry(ads, &msg, ldap_exp, attrs);
if (!ADS_ERR_OK(rc)) {
status = ads_ntstatus(rc);
DEBUG(1,("ads_sid_to_name ads_search: %s\n", ads_errstr(rc)));
@ -146,10 +146,89 @@ NTSTATUS ads_sid_to_name(ADS_STRUCT *ads,
done:
if (msg) ads_msgfree(ads, msg);
SAFE_FREE(exp);
SAFE_FREE(ldap_exp);
SAFE_FREE(sidstr);
return status;
}
/* convert a sid to a DN */
ADS_STATUS ads_sid_to_dn(ADS_STRUCT *ads,
TALLOC_CTX *mem_ctx,
const DOM_SID *sid,
char **dn)
{
ADS_STATUS rc;
LDAPMessage *msg = NULL;
LDAPMessage *entry = NULL;
char *ldap_exp;
char *sidstr = NULL;
int count;
char *dn2 = NULL;
const char *attr[] = {
"dn",
NULL
};
if (!(sidstr = sid_binstring(sid))) {
DEBUG(1,("ads_sid_to_dn: sid_binstring failed!\n"));
rc = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
goto done;
}
if(!(ldap_exp = talloc_asprintf(mem_ctx, "(objectSid=%s)", sidstr))) {
DEBUG(1,("ads_sid_to_dn: talloc_asprintf failed!\n"));
rc = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
goto done;
}
rc = ads_search_retry(ads, (void **)&msg, ldap_exp, attr);
if (!ADS_ERR_OK(rc)) {
DEBUG(1,("ads_sid_to_dn ads_search: %s\n", ads_errstr(rc)));
goto done;
}
if ((count = ads_count_replies(ads, msg)) != 1) {
fstring sid_string;
DEBUG(1,("ads_sid_to_dn (sid=%s): Not found (count=%d)\n",
sid_to_string(sid_string, sid), count));
rc = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
goto done;
}
entry = ads_first_entry(ads, msg);
dn2 = ads_get_dn(ads, entry);
if (!dn2) {
rc = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
goto done;
}
*dn = talloc_strdup(mem_ctx, dn2);
if (!*dn) {
ads_memfree(ads, dn2);
rc = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
goto done;
}
rc = ADS_ERROR_NT(NT_STATUS_OK);
DEBUG(3,("ads sid_to_dn mapped %s\n", dn2));
SAFE_FREE(dn2);
done:
if (msg) ads_msgfree(ads, msg);
if (dn2) ads_memfree(ads, dn2);
SAFE_FREE(sidstr);
return rc;
}
#endif

View File

@ -31,10 +31,10 @@ ADS_STATUS ads_build_error(enum ads_error_type etype,
{
ADS_STATUS ret;
if (etype == ADS_ERROR_NT) {
DEBUG(0,("don't use ads_build_error with ADS_ERROR_NT!\n"));
if (etype == ENUM_ADS_ERROR_NT) {
DEBUG(0,("don't use ads_build_error with ENUM_ADS_ERROR_NT!\n"));
ret.err.rc = -1;
ret.error_type = ADS_ERROR_SYSTEM;
ret.error_type = ENUM_ADS_ERROR_SYSTEM;
ret.minor_status = 0;
return ret;
}
@ -50,10 +50,10 @@ ADS_STATUS ads_build_nt_error(enum ads_error_type etype,
{
ADS_STATUS ret;
if (etype != ADS_ERROR_NT) {
DEBUG(0,("don't use ads_build_nt_error without ADS_ERROR_NT!\n"));
if (etype != ENUM_ADS_ERROR_NT) {
DEBUG(0,("don't use ads_build_nt_error without ENUM_ADS_ERROR_NT!\n"));
ret.err.rc = -1;
ret.error_type = ADS_ERROR_SYSTEM;
ret.error_type = ENUM_ADS_ERROR_SYSTEM;
ret.minor_status = 0;
return ret;
}
@ -69,14 +69,23 @@ ADS_STATUS ads_build_nt_error(enum ads_error_type etype,
*/
NTSTATUS ads_ntstatus(ADS_STATUS status)
{
if (status.error_type == ADS_ERROR_NT){
if (status.error_type == ENUM_ADS_ERROR_NT){
return status.err.nt_status;
}
#ifdef HAVE_LDAP
if ((status.error_type == ADS_ERROR_LDAP)
if ((status.error_type == ENUM_ADS_ERROR_LDAP)
&& (status.err.rc == LDAP_NO_MEMORY)) {
return NT_STATUS_NO_MEMORY;
}
#endif
#ifdef HAVE_KRB5
if (status.error_type == ENUM_ADS_ERROR_KRB5) {
if (status.err.rc == KRB5KDC_ERR_PREAUTH_FAILED) {
return NT_STATUS_LOGON_FAILURE;
} else if (status.err.rc == KRB5_KDC_UNREACH) {
return NT_STATUS_NO_LOGON_SERVERS;
}
}
#endif
if (ADS_ERR_OK(status)) return NT_STATUS_OK;
return NT_STATUS_UNSUCCESSFUL;
@ -87,25 +96,25 @@ NTSTATUS ads_ntstatus(ADS_STATUS status)
*/
const char *ads_errstr(ADS_STATUS status)
{
int msg_ctx;
uint32 msg_ctx;
static char *ret;
SAFE_FREE(ret);
msg_ctx = 0;
switch (status.error_type) {
case ADS_ERROR_SYSTEM:
case ENUM_ADS_ERROR_SYSTEM:
return strerror(status.err.rc);
#ifdef HAVE_LDAP
case ADS_ERROR_LDAP:
case ENUM_ADS_ERROR_LDAP:
return ldap_err2string(status.err.rc);
#endif
#ifdef HAVE_KRB5
case ADS_ERROR_KRB5:
case ENUM_ADS_ERROR_KRB5:
return error_message(status.err.rc);
#endif
#ifdef HAVE_GSSAPI
case ADS_ERROR_GSS:
case ENUM_ADS_ERROR_GSS:
{
uint32 minor;
@ -122,8 +131,8 @@ const char *ads_errstr(ADS_STATUS status)
return ret;
}
#endif
case ADS_ERROR_NT:
return nt_errstr(ads_ntstatus(status));
case ENUM_ADS_ERROR_NT:
return get_friendly_nt_error_msg(ads_ntstatus(status));
default:
return "Unknown ADS error type!? (not compiled in?)";
}

View File

@ -94,12 +94,11 @@ ADS_STRUCT *ads_init(const char *realm,
ads->server.workgroup = workgroup ? strdup(workgroup) : NULL;
ads->server.ldap_server = ldap_server? strdup(ldap_server) : NULL;
/* we need to know if this is a foreign realm to know if we can
use lp_ads_server() */
if (realm && *realm && strcasecmp(lp_realm(), realm) != 0) {
/* we need to know if this is a foreign realm */
if (realm && *realm && !strequal(lp_realm(), realm)) {
ads->server.foreign = 1;
}
if (workgroup && *workgroup && strcasecmp(lp_workgroup(), workgroup) != 0) {
if (workgroup && *workgroup && !strequal(lp_workgroup(), workgroup)) {
ads->server.foreign = 1;
}

View File

@ -88,52 +88,6 @@ uint32 ads_uf2atype(uint32 uf)
return atype;
}
/*
translated the GROUP_CTRL Flags to GroupType (groupType)
*/
uint32 ads_gcb2gtype(uint16 gcb)
{
uint32 gtype = 0x00000000;
if (gcb & GCB_ALIAS_GROUP) gtype |= GTYPE_SECURITY_BUILTIN_LOCAL_GROUP;
else if(gcb & GCB_LOCAL_GROUP) gtype |= GTYPE_SECURITY_DOMAIN_LOCAL_GROUP;
if (gcb & GCB_GLOBAL_GROUP) gtype |= GTYPE_SECURITY_GLOBAL_GROUP;
return gtype;
}
/*
translated the GroupType (groupType) to GROUP_CTRL Flags
*/
uint16 ads_gtype2gcb(uint32 gtype)
{
uint16 gcb = 0x0000;
switch(gtype) {
case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
gcb = GCB_ALIAS_GROUP;
break;
case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
gcb = GCB_LOCAL_GROUP;
break;
case GTYPE_SECURITY_GLOBAL_GROUP:
gcb = GCB_GLOBAL_GROUP;
break;
case GTYPE_DISTRIBUTION_GLOBAL_GROUP:
gcb = GCB_GLOBAL_GROUP;
break;
case GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP:
gcb = GCB_LOCAL_GROUP;
break;
case GTYPE_DISTRIBUTION_UNIVERSAL_GROUP:
gcb = GCB_GLOBAL_GROUP;
break;
}
return gcb;
}
/*
get the accountType from the groupType
*/
@ -172,6 +126,8 @@ enum SID_NAME_USE ads_atype_map(uint32 atype)
switch (atype & 0xF0000000) {
case ATYPE_GLOBAL_GROUP:
return SID_NAME_DOM_GRP;
case ATYPE_SECURITY_LOCAL_GROUP:
return SID_NAME_ALIAS;
case ATYPE_ACCOUNT:
return SID_NAME_USER;
default:

View File

@ -1,34 +1,139 @@
#################################################
# active directory support
########################################################
# Compile with LDAP support?
with_ads_support=yes
AC_MSG_CHECKING([whether to use Active Directory])
LDAP_LIBS=""
AC_SUBST(LDAP_LIBS)
with_ldap_support=auto
AC_MSG_CHECKING([for LDAP support])
AC_ARG_WITH(ads,
[ --with-ads Active Directory support (default yes)],
AC_ARG_WITH(ldap,
[ --with-ldap LDAP support (default yes)],
[ case "$withval" in
no)
with_ads_support=no
yes|no)
with_ldap_support=$withval
;;
esac ])
if test x"$with_ads_support" = x"yes"; then
AC_DEFINE(WITH_ADS,1,[Whether to include Active Directory support])
AC_MSG_RESULT($with_ldap_support)
if test x"$with_ldap_support" != x"no"; then
##################################################################
# first test for ldap.h and lber.h
# (ldap.h is required for this test)
AC_CHECK_HEADERS(ldap.h lber.h)
if test x"$ac_cv_header_ldap_h" != x"yes"; then
if test x"$with_ldap_support" = x"yes"; then
AC_MSG_ERROR(ldap.h is needed for LDAP support)
else
AC_MSG_WARN(ldap.h is needed for LDAP support)
fi
with_ldap_support=no
fi
fi
if test x"$with_ldap_support" != x"no"; then
ac_save_LIBS=$LIBS
##################################################################
# we might need the lber lib on some systems. To avoid link errors
# this test must be before the libldap test
AC_CHECK_LIB_EXT(lber, LDAP_LIBS, ber_scanf)
########################################################
# now see if we can find the ldap libs in standard paths
AC_CHECK_LIB_EXT(ldap, LDAP_LIBS, ldap_init)
AC_CHECK_FUNC_EXT(ldap_domain2hostlist,$LDAP_LIBS)
########################################################
# If we have LDAP, does it's rebind procedure take 2 or 3 arguments?
# Check found in pam_ldap 145.
AC_CHECK_FUNC_EXT(ldap_set_rebind_proc,$LDAP_LIBS)
LIBS="$LIBS $LDAP_LIBS"
AC_CACHE_CHECK(whether ldap_set_rebind_proc takes 3 arguments, smb_ldap_cv_ldap_set_rebind_proc, [
AC_TRY_COMPILE([
#include <lber.h>
#include <ldap.h>],
[ldap_set_rebind_proc(0, 0, 0);],
[smb_ldap_cv_ldap_set_rebind_proc=3],
[smb_ldap_cv_ldap_set_rebind_proc=2]
)
])
AC_DEFINE_UNQUOTED(LDAP_SET_REBIND_PROC_ARGS, $smb_ldap_cv_ldap_set_rebind_proc, [Number of arguments to ldap_set_rebind_proc])
AC_CHECK_FUNC_EXT(ldap_initialize,$LDAP_LIBS)
if test x"$ac_cv_lib_ext_ldap_ldap_init" = x"yes" -a x"$ac_cv_func_ext_ldap_domain2hostlist" = x"yes"; then
AC_DEFINE(HAVE_LDAP,1,[Whether ldap is available])
SMB_MODULE_DEFAULT(STATIC,pdb_ldap)
with_ldap_support=yes
AC_MSG_CHECKING(whether LDAP support is used)
AC_MSG_RESULT(yes)
else
if test x"$with_ldap_support" = x"yes"; then
AC_MSG_ERROR(libldap is needed for LDAP support)
else
AC_MSG_WARN(libldap is needed for LDAP support)
fi
LDAP_LIBS=""
with_ldap_support=no
fi
LIBS=$ac_save_LIBS
fi
#################################################
# active directory support
KRB5_LIBS=""
AC_SUBST(KRB5_LIBS)
with_ads_support=auto
AC_MSG_CHECKING([for Active Directory and krb5 support])
AC_ARG_WITH(ads,
[ --with-ads Active Directory support (default auto)],
[ case "$withval" in
yes|no)
with_ads_support="$withval"
;;
esac ])
AC_MSG_RESULT($with_ads_support)
FOUND_KRB5=no
if test x"$with_ads_support" = x"yes"; then
if test x"$with_ldap_support" != x"yes"; then
if test x"$with_ads_support" = x"yes"; then
AC_MSG_ERROR(Active Directory Support requires LDAP support)
elif test x"$with_ads_support" != x"no"; then
AC_MSG_WARN(Active Directory Support requires LDAP support)
fi
with_ads_support=no
fi
if test x"$with_ads_support" != x"no"; then
FOUND_KRB5=no
# Do no harm to the values of CFLAGS and LIBS while testing for
# Kerberos support.
#################################################
# check for krb5-config from recent MIT and Heimdal kerberos 5
AC_PATH_PROG(KRB5_CONFIG, krb5-config)
AC_MSG_CHECKING(for working krb5-config)
if test -x "$KRB5_CONFIG"; then
LIBS="$LIBS `$KRB5_CONFIG --libs`"
CFLAGS="$CFLAGS `$KRB5_CONFIG --cflags`"
CPPFLAGS="$CPPFLAGS `$KRB5_CONFIG --cflags`"
ac_save_CFLAGS=$CFLAGS
CFLAGS="";export CFLAGS
ac_save_LDFLAGS=$LDFLAGS
LDFLAGS="";export LDFLAGS
KRB5_LIBS="`$KRB5_CONFIG --libs gssapi`"
KRB5_CFLAGS="`$KRB5_CONFIG --cflags | sed s/@INCLUDE_des@//`"
KRB5_CPPFLAGS="`$KRB5_CONFIG --cflags | sed s/@INCLUDE_des@//`"
CFLAGS=$ac_save_CFLAGS;export CFLAGS
LDFLAGS=$ac_save_LDFLAGS;export LDFLAGS
FOUND_KRB5=yes
AC_MSG_RESULT(yes)
else
@ -36,193 +141,303 @@ if test x"$with_ads_support" = x"yes"; then
fi
if test x$FOUND_KRB5 = x"no"; then
#################################################
# check for location of Kerberos 5 install
AC_MSG_CHECKING(for kerberos 5 install path)
AC_ARG_WITH(krb5,
[ --with-krb5=base-dir Locate Kerberos 5 support (default=/usr)],
[ case "$withval" in
no)
AC_MSG_RESULT(no)
;;
*)
AC_MSG_RESULT(yes)
LIBS="$LIBS -lkrb5"
CFLAGS="$CFLAGS -I$withval/include"
CPPFLAGS="$CPPFLAGS -I$withval/include"
LDFLAGS="$LDFLAGS -L$withval/lib"
FOUND_KRB5=yes
;;
esac ],
AC_MSG_RESULT(no)
)
#################################################
# check for location of Kerberos 5 install
AC_MSG_CHECKING(for kerberos 5 install path)
AC_ARG_WITH(krb5,
[ --with-krb5=base-dir Locate Kerberos 5 support (default=/usr)],
[ case "$withval" in
no)
AC_MSG_RESULT(no krb5-path given)
;;
yes)
AC_MSG_RESULT(/usr)
FOUND_KRB5=yes
;;
*)
AC_MSG_RESULT($withval)
KRB5_CFLAGS="-I$withval/include"
KRB5_CPPFLAGS="-I$withval/include"
KRB5_LDFLAGS="-L$withval/lib"
FOUND_KRB5=yes
;;
esac ],
AC_MSG_RESULT(no krb5-path given)
)
fi
if test x$FOUND_KRB5 = x"no"; then
#################################################
# see if this box has the SuSE location for the heimdal kerberos implementation
AC_MSG_CHECKING(for /usr/include/heimdal)
if test -d /usr/include/heimdal; then
if test -f /usr/lib/heimdal/lib/libkrb5.a; then
LIBS="$LIBS -lkrb5"
CFLAGS="$CFLAGS -I/usr/include/heimdal"
CPPFLAGS="$CPPFLAGS -I/usr/include/heimdal"
LDFLAGS="$LDFLAGS -L/usr/lib/heimdal/lib"
AC_MSG_RESULT(yes)
if test x$FOUND_KRB5 = x"no"; then
#################################################
# see if this box has the SuSE location for the heimdal krb implementation
AC_MSG_CHECKING(for /usr/include/heimdal)
if test -d /usr/include/heimdal; then
if test -f /usr/lib/heimdal/lib/libkrb5.a; then
KRB5_CFLAGS="-I/usr/include/heimdal"
KRB5_CPPFLAGS="-I/usr/include/heimdal"
KRB5_LDFLAGS="-L/usr/lib/heimdal/lib"
AC_MSG_RESULT(yes)
else
KRB5_CFLAGS="-I/usr/include/heimdal"
KRB5_CPPFLAGS="-I/usr/include/heimdal"
AC_MSG_RESULT(yes)
fi
else
LIBS="$LIBS -lkrb5"
CFLAGS="$CFLAGS -I/usr/include/heimdal"
CPPFLAGS="$CPPFLAGS -I/usr/include/heimdal"
AC_MSG_RESULT(yes)
AC_MSG_RESULT(no)
fi
else
AC_MSG_RESULT(no)
fi
fi
fi
if test x$FOUND_KRB5 = x"no"; then
#################################################
# see if this box has the RedHat location for kerberos
AC_MSG_CHECKING(for /usr/kerberos)
if test -d /usr/kerberos -a -f /usr/kerberos/lib/libkrb5.a; then
KRB5_LDFLAGS="-L/usr/kerberos/lib"
KRB5_CFLAGS="-I/usr/kerberos/include"
KRB5_CPPFLAGS="-I/usr/kerberos/include"
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT(no)
fi
fi
if test x$FOUND_KRB5 = x"no"; then
#################################################
# see if this box has the RedHat location for kerberos
AC_MSG_CHECKING(for /usr/kerberos)
if test -d /usr/kerberos -a -f /usr/kerberos/lib/libkrb5.a; then
LIBS="$LIBS -lkrb5"
LDFLAGS="$LDFLAGS -L/usr/kerberos/lib"
CFLAGS="$CFLAGS -I/usr/kerberos/include"
CPPFLAGS="$CPPFLAGS -I/usr/kerberos/include"
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT(no)
fi
fi
ac_save_CFLAGS=$CFLAGS
ac_save_CPPFLAGS=$CPPFLAGS
ac_save_LDFLAGS=$LDFLAGS
CFLAGS="$CFLAGS $KRB5_CFLAGS"
CPPFLAGS="$CPPFLAGS $KRB5_CPPFLAGS"
LDFLAGS="$LDFLAGS $KRB5_LDFLAGS"
KRB5_LIBS="$KRB5_LDFLAGS $KRB5_LIBS"
# now check for krb5.h. Some systems have the libraries without the headers!
# note that this check is done here to allow for different kerberos
# include paths
AC_CHECK_HEADERS(krb5.h)
if test x"$ac_cv_header_krb5_h" = x"no"; then
# Give a warning if AD support was not explicitly requested,
# i.e with_ads_support = auto, otherwise die with an error.
if test x"$with_ads_support" = x"yes"; then
AC_MSG_ERROR([Active Directory cannot be supported without krb5.h])
else
AC_MSG_WARN([Active Directory cannot be supported without krb5.h])
fi
# Turn off AD support and restore CFLAGS and LIBS variables
with_ads_support="no"
CFLAGS=$ac_save_CFLAGS
CPPFLAGS=$ac_save_CPPFLAGS
LDFLAGS=$ac_save_LDFLAGS
fi
fi
# Now we have determined whether we really want ADS support
if test x"$with_ads_support" != x"no"; then
ac_save_LIBS=$LIBS
# now check for gssapi headers. This is also done here to allow for
# different kerberos include paths
AC_CHECK_HEADERS(gssapi.h gssapi/gssapi_generic.h gssapi/gssapi.h com_err.h)
##################################################################
# we might need the k5crypto and com_err libraries on some systems
AC_CHECK_LIB(com_err, _et_list, [LIBS="$LIBS -lcom_err"])
AC_CHECK_LIB(k5crypto, krb5_encrypt_data, [LIBS="$LIBS -lk5crypto"])
AC_CHECK_LIB_EXT(com_err, KRB5_LIBS, _et_list)
AC_CHECK_LIB_EXT(k5crypto, KRB5_LIBS, krb5_encrypt_data)
# Heimdal checks.
AC_CHECK_LIB(crypto, des_set_key, [LIBS="$LIBS -lcrypto"])
AC_CHECK_LIB(asn1, copy_Authenticator, [LIBS="$LIBS -lasn1 -lroken"])
AC_CHECK_LIB_EXT(crypto, KRB5_LIBS, des_set_key)
AC_CHECK_LIB_EXT(asn1, KRB5_LIBS, copy_Authenticator)
AC_CHECK_LIB_EXT(roken, KRB5_LIBS, roken_getaddrinfo_hostspec)
# Heimdal checks. On static Heimdal gssapi must be linked before krb5.
AC_CHECK_LIB(gssapi, gss_display_status, [LIBS="$LIBS -lgssapi -lkrb5 -lasn1";
AC_DEFINE(HAVE_GSSAPI,1,[Whether GSSAPI is available])])
AC_CHECK_LIB(krb5, krb5_set_real_time, [AC_DEFINE(HAVE_KRB5_SET_REAL_TIME,1,[Whether krb5_set_real_time is available])])
AC_CHECK_LIB(krb5, krb5_set_default_in_tkt_etypes, [AC_DEFINE(HAVE_KRB5_SET_DEFAULT_IN_TKT_ETYPES,1,[Whether krb5_set_default_in_tkt_etypes, is available])])
AC_CHECK_LIB(krb5, krb5_set_default_tgs_ktypes, [AC_DEFINE(HAVE_KRB5_SET_DEFAULT_TGS_KTYPES,1,[Whether krb5_set_default_tgs_ktypes is available])])
AC_CHECK_LIB(krb5, krb5_principal2salt, [AC_DEFINE(HAVE_KRB5_PRINCIPAL2SALT,1,[Whether krb5_principal2salt is available])])
AC_CHECK_LIB(krb5, krb5_use_enctype, [AC_DEFINE(HAVE_KRB5_USE_ENCTYPE,1,[Whether krb5_use_enctype is available])])
AC_CHECK_LIB(krb5, krb5_string_to_key, [AC_DEFINE(HAVE_KRB5_STRING_TO_KEY,1,[Whether krb5_string_to_key is available])])
AC_CHECK_LIB(krb5, krb5_get_pw_salt, [AC_DEFINE(HAVE_KRB5_GET_PW_SALT,1,[Whether krb5_get_pw_salt is available])])
AC_CHECK_LIB(krb5, krb5_string_to_key_salt, [AC_DEFINE(HAVE_KRB5_STRING_TO_KEY_SALT,1,[Whether krb5_string_to_key_salt is available])])
AC_CHECK_LIB(krb5, krb5_auth_con_setkey, [AC_DEFINE(HAVE_KRB5_AUTH_CON_SETKEY,1,[Whether krb5_auth_con_setkey is available])])
AC_CHECK_LIB(krb5, krb5_auth_con_setuseruserkey, [AC_DEFINE(HAVE_KRB5_AUTH_CON_SETUSERUSERKEY,1,[Whether krb5_auth_con_setuseruserkey is available])])
AC_CHECK_LIB(krb5, krb5_locate_kdc, [AC_DEFINE(HAVE_KRB5_LOCATE_KDC,1,[Whether krb5_locate_kdc is available])])
AC_CHECK_LIB(krb5, krb5_get_permitted_enctypes, [AC_DEFINE(HAVE_KRB5_GET_PERMITTED_ENCTYPES,1,[Whether krb5_get_permitted_enctypes is available])])
AC_CHECK_LIB(krb5, krb5_get_default_in_tkt_etypes, [AC_DEFINE(HAVE_KRB5_GET_DEFAULT_IN_TKT_ETYPES,1,[Whether krb5_get_default_in_tkt_etypes is available])])
AC_CHECK_LIB(krb5, krb5_free_ktypes, [AC_DEFINE(HAVE_KRB5_FREE_KTYPES,1,[Whether krb5_free_ktypes is available])])
AC_CACHE_CHECK([for addrtype in krb5_address],samba_cv_HAVE_ADDRTYPE_IN_KRB5_ADDRESS,[
AC_TRY_COMPILE([#include <krb5.h>],
[krb5_address kaddr; kaddr.addrtype = ADDRTYPE_INET;],
samba_cv_HAVE_ADDRTYPE_IN_KRB5_ADDRESS=yes,samba_cv_HAVE_ADDRTYPE_IN_KRB5_ADDRESS=no)])
if test x"$samba_cv_HAVE_ADDRTYPE_IN_KRB5_ADDRESS" = x"yes"; then
AC_DEFINE(HAVE_ADDRTYPE_IN_KRB5_ADDRESS,1,[Whether the krb5_address struct has a addrtype property])
fi
AC_CACHE_CHECK([for addr_type in krb5_address],samba_cv_HAVE_ADDR_TYPE_IN_KRB5_ADDRESS,[
AC_TRY_COMPILE([#include <krb5.h>],
[krb5_address kaddr; kaddr.addr_type = KRB5_ADDRESS_INET;],
samba_cv_HAVE_ADDR_TYPE_IN_KRB5_ADDRESS=yes,samba_cv_HAVE_ADDR_TYPE_IN_KRB5_ADDRESS=no)])
if test x"$samba_cv_HAVE_ADDR_TYPE_IN_KRB5_ADDRESS" = x"yes"; then
AC_DEFINE(HAVE_ADDR_TYPE_IN_KRB5_ADDRESS,1,[Whether the krb5_address struct has a addr_type property])
fi
AC_CACHE_CHECK([for enc_part2 in krb5_ticket],samba_cv_HAVE_KRB5_TKT_ENC_PART2,[
AC_TRY_COMPILE([#include <krb5.h>],
[krb5_ticket tkt; tkt.enc_part2->authorization_data[0]->contents = NULL;],
samba_cv_HAVE_KRB5_TKT_ENC_PART2=yes,samba_cv_HAVE_KRB5_TKT_ENC_PART2=no)])
if test x"$samba_cv_HAVE_KRB5_TKT_ENC_PART2" = x"yes"; then
AC_DEFINE(HAVE_KRB5_TKT_ENC_PART2,1,[Whether the krb5_ticket struct has a enc_part2 property])
fi
AC_CACHE_CHECK([for keyvalue in krb5_keyblock],samba_cv_HAVE_KRB5_KEYBLOCK_KEYVALUE,[
AC_TRY_COMPILE([#include <krb5.h>],
[krb5_keyblock key; key.keyvalue.data = NULL;],
samba_cv_HAVE_KRB5_KEYBLOCK_KEYVALUE=yes,samba_cv_HAVE_KRB5_KEYBLOCK_KEYVALUE=no)])
if test x"$samba_cv_HAVE_KRB5_KEYBLOCK_KEYVALUE" = x"yes"; then
AC_DEFINE(HAVE_KRB5_KEYBLOCK_KEYVALUE,1,[Whether the krb5_keyblock struct has a keyvalue property])
fi
AC_CACHE_CHECK([for ENCTYPE_ARCFOUR_HMAC_MD5],samba_cv_HAVE_ENCTYPE_ARCFOUR_HMAC_MD5,[
AC_TRY_COMPILE([#include <krb5.h>],
[krb5_enctype enctype; enctype = ENCTYPE_ARCFOUR_HMAC_MD5;],
samba_cv_HAVE_ENCTYPE_ARCFOUR_HMAC_MD5=yes,samba_cv_HAVE_ENCTYPE_ARCFOUR_HMAC_MD5=no)])
if test x"$samba_cv_HAVE_ENCTYPE_ARCFOUR_HMAC_MD5" = x"yes"; then
AC_DEFINE(HAVE_ENCTYPE_ARCFOUR_HMAC_MD5,1,[Whether the ENCTYPE_ARCFOUR_HMAC_MD5 key type is available])
fi
AC_CHECK_LIB_EXT(gssapi, KRB5_LIBS, gss_display_status,[],[],
AC_DEFINE(HAVE_GSSAPI,1,[Whether GSSAPI is available]))
########################################################
# now see if we can find the krb5 libs in standard paths
# or as specified above
AC_CHECK_LIB(krb5, krb5_mk_req_extended, [LIBS="$LIBS -lkrb5";
AC_DEFINE(HAVE_KRB5,1,[Whether KRB5 is available])])
AC_CHECK_LIB_EXT(krb5, KRB5_LIBS, krb5_mk_req_extended)
########################################################
# now see if we can find the gssapi libs in standard paths
AC_CHECK_LIB(gssapi_krb5, gss_display_status, [LIBS="$LIBS -lgssapi_krb5";
AC_DEFINE(HAVE_GSSAPI,1,[Whether GSSAPI is available])])
AC_CHECK_LIB_EXT(gssapi_krb5, KRB5_LIBS,gss_display_status,[],[],
AC_DEFINE(HAVE_GSSAPI,1,[Whether GSSAPI is available]))
fi
AC_CHECK_FUNC_EXT(krb5_set_real_time, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_set_default_in_tkt_etypes, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_set_default_tgs_ktypes, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_principal2salt, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_use_enctype, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_string_to_key, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_get_pw_salt, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_string_to_key_salt, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_auth_con_setkey, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_auth_con_setuseruserkey, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_locate_kdc, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_get_permitted_enctypes, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_get_default_in_tkt_etypes, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_free_ktypes, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_free_data_contents, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_principal_get_comp_string, $KRB5_LIBS)
########################################################
# Compile with LDAP support?
LIBS="$LIBS $KRB5_LIBS"
AC_CACHE_CHECK([for addrtype in krb5_address],
samba_cv_HAVE_ADDRTYPE_IN_KRB5_ADDRESS,[
AC_TRY_COMPILE([#include <krb5.h>],
[krb5_address kaddr; kaddr.addrtype = ADDRTYPE_INET;],
samba_cv_HAVE_ADDRTYPE_IN_KRB5_ADDRESS=yes,
samba_cv_HAVE_ADDRTYPE_IN_KRB5_ADDRESS=no)])
with_ldap_support=yes
AC_MSG_CHECKING([whether to use LDAP])
AC_ARG_WITH(ldap,
[ --with-ldap LDAP support (default yes)],
[ case "$withval" in
no)
with_ldap_support=no
;;
esac ])
AC_MSG_RESULT($with_ldap_support)
if test x"$with_ldap_support" = x"yes"; then
##################################################################
# we might need the lber lib on some systems. To avoid link errors
# this test must be before the libldap test
AC_CHECK_LIB(lber, ber_scanf, [LIBS="$LIBS -llber"])
########################################################
# now see if we can find the ldap libs in standard paths
if test x$have_ldap != xyes; then
AC_CHECK_LIB(ldap, ldap_domain2hostlist, [LIBS="$LIBS -lldap";
AC_DEFINE(HAVE_LDAP,1,[Whether ldap is available])])
########################################################
# If we have LDAP, does it's rebind procedure take 2 or 3 arguments?
# Check found in pam_ldap 145.
AC_CHECK_FUNCS(ldap_set_rebind_proc)
AC_CACHE_CHECK(whether ldap_set_rebind_proc takes 3 arguments, pam_ldap_cv_ldap_set_rebind_proc, [
AC_TRY_COMPILE([
#include <lber.h>
#include <ldap.h>], [ldap_set_rebind_proc(0, 0, 0);], [pam_ldap_cv_ldap_set_rebind_proc=3], [pam_ldap_cv_ldap_set_rebind_proc=2]) ])
AC_DEFINE_UNQUOTED(LDAP_SET_REBIND_PROC_ARGS, $pam_ldap_cv_ldap_set_rebind_proc, [Number of arguments to ldap_set_rebind_proc])
if test x"$samba_cv_HAVE_ADDRTYPE_IN_KRB5_ADDRESS" = x"yes"; then
AC_DEFINE(HAVE_ADDRTYPE_IN_KRB5_ADDRESS,1,
[Whether the krb5_address struct has a addrtype property])
fi
AC_CACHE_CHECK([for addr_type in krb5_address],
samba_cv_HAVE_ADDR_TYPE_IN_KRB5_ADDRESS,[
AC_TRY_COMPILE([#include <krb5.h>],
[krb5_address kaddr; kaddr.addr_type = KRB5_ADDRESS_INET;],
samba_cv_HAVE_ADDR_TYPE_IN_KRB5_ADDRESS=yes,
samba_cv_HAVE_ADDR_TYPE_IN_KRB5_ADDRESS=no)])
if test x"$samba_cv_HAVE_ADDR_TYPE_IN_KRB5_ADDRESS" = x"yes"; then
AC_DEFINE(HAVE_ADDR_TYPE_IN_KRB5_ADDRESS,1,
[Whether the krb5_address struct has a addr_type property])
fi
AC_CACHE_CHECK([for enc_part2 in krb5_ticket],
samba_cv_HAVE_KRB5_TKT_ENC_PART2,
[AC_TRY_COMPILE([#include <krb5.h>],
[krb5_ticket tkt; tkt.enc_part2->authorization_data[0]->contents = NULL;],
samba_cv_HAVE_KRB5_TKT_ENC_PART2=yes,samba_cv_HAVE_KRB5_TKT_ENC_PART2=no)])
if test x"$samba_cv_HAVE_KRB5_TKT_ENC_PART2" = x"yes"; then
AC_DEFINE(HAVE_KRB5_TKT_ENC_PART2,1,
[Whether the krb5_ticket struct has a enc_part2 property])
fi
AC_CACHE_CHECK([for keyvalue in krb5_keyblock],
samba_cv_HAVE_KRB5_KEYBLOCK_KEYVALUE,[
AC_TRY_COMPILE([#include <krb5.h>],
[krb5_keyblock key; key.keyvalue.data = NULL;],
samba_cv_HAVE_KRB5_KEYBLOCK_KEYVALUE=yes,
samba_cv_HAVE_KRB5_KEYBLOCK_KEYVALUE=no)])
if test x"$samba_cv_HAVE_KRB5_KEYBLOCK_KEYVALUE" = x"yes"; then
AC_DEFINE(HAVE_KRB5_KEYBLOCK_KEYVALUE,1,
[Whether the krb5_keyblock struct has a keyvalue property])
fi
AC_CACHE_CHECK([for ENCTYPE_ARCFOUR_HMAC_MD5],
samba_cv_HAVE_ENCTYPE_ARCFOUR_HMAC_MD5,[
AC_TRY_COMPILE([#include <krb5.h>],
[krb5_enctype enctype; enctype = ENCTYPE_ARCFOUR_HMAC_MD5;],
samba_cv_HAVE_ENCTYPE_ARCFOUR_HMAC_MD5=yes,
samba_cv_HAVE_ENCTYPE_ARCFOUR_HMAC_MD5=no)])
AC_CACHE_CHECK([for KEYTYPE_ARCFOUR_56],
samba_cv_HAVE_KEYTYPE_ARCFOUR_56,[
AC_TRY_COMPILE([#include <krb5.h>],
[krb5_keytype keytype; keytype = KEYTYPE_ARCFOUR_56;],
samba_cv_HAVE_KEYTYPE_ARCFOUR_56=yes,
samba_cv_HAVE_KEYTYPE_ARCFOUR_56=no)])
# Heimdals with KEYTYPE_ARCFOUR but not KEYTYPE_ARCFOUR_56 are broken
# w.r.t. arcfour and windows, so we must not enable it here
if test x"$samba_cv_HAVE_ENCTYPE_ARCFOUR_HMAC_MD5" = x"yes" -a\
x"$samba_cv_HAVE_KEYTYPE_ARCFOUR_56" = x"yes"; then
AC_DEFINE(HAVE_ENCTYPE_ARCFOUR_HMAC_MD5,1,
[Whether the ENCTYPE_ARCFOUR_HMAC_MD5 key type is available])
fi
AC_CACHE_CHECK([for AP_OPTS_USE_SUBKEY],
samba_cv_HAVE_AP_OPTS_USE_SUBKEY,[
AC_TRY_COMPILE([#include <krb5.h>],
[krb5_flags ap_options; ap_options = AP_OPTS_USE_SUBKEY;],
samba_cv_HAVE_AP_OPTS_USE_SUBKEY=yes,
samba_cv_HAVE_AP_OPTS_USE_SUBKEY=no)])
if test x"$samba_cv_HAVE_AP_OPTS_USE_SUBKEY" = x"yes"; then
AC_DEFINE(HAVE_AP_OPTS_USE_SUBKEY,1,
[Whether the AP_OPTS_USE_SUBKEY ap option is available])
fi
AC_CACHE_CHECK([for the krb5_princ_component macro],
samba_cv_HAVE_KRB5_PRINC_COMPONENT,[
AC_TRY_LINK([#include <krb5.h>],
[const krb5_data *pkdata; krb5_context context; krb5_principal principal; pkdata = krb5_princ_component(context, principal, 0);],
samba_cv_HAVE_KRB5_PRINC_COMPONENT=yes,
samba_cv_HAVE_KRB5_PRINC_COMPONENT=no)])
if test x"$samba_cv_HAVE_KRB5_PRINC_COMPONENT" = x"yes"; then
AC_DEFINE(HAVE_KRB5_PRINC_COMPONENT,1,
[Whether krb5_princ_component is available])
fi
AC_CACHE_CHECK([for memory keytab support],
samba_cv_HAVE_MEMORY_KEYTAB,[
AC_TRY_RUN([
#include<krb5.h>
main()
{
krb5_context context;
krb5_keytab keytab;
krb5_init_context(&context);
if (krb5_kt_resolve(context, "MEMORY:", &keytab))
exit(1);
exit(0);
}],
samba_cv_HAVE_MEMORY_KEYTAB=yes,
samba_cv_HAVE_MEMORY_KEYTAB=no)])
if test x"$samba_cv_HAVE_MEMORY_KEYTAB" = x"yes"; then
AC_DEFINE(HAVE_MEMORY_KEYTAB,1,
[Whether in-memory keytabs are supported])
fi
AC_CACHE_CHECK([for key in krb5_keytab_entry],
samba_cv_HAVE_KRB5_KEYTAB_ENTRY_KEY,[
AC_TRY_COMPILE([#include <krb5.h>],
[krb5_keytab_entry entry; krb5_keyblock e; entry.key = e;],
samba_cv_HAVE_KRB5_KEYTAB_ENTRY_KEY=yes,
samba_cv_HAVE_KRB5_KEYTAB_ENTRY_KEY=no)])
if test x"$samba_cv_HAVE_KRB5_KEYTAB_ENTRY_KEY" = x"yes"; then
AC_DEFINE(HAVE_KRB5_KEYTAB_ENTRY_KEY,1,
[Whether krb5_keytab_entry has key member])
fi
AC_CACHE_CHECK([for keyblock in krb5_keytab_entry],
samba_cv_HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK,[
AC_TRY_COMPILE([#include <krb5.h>],
[krb5_keytab_entry entry; entry.keyblock.keytype = 0;],
samba_cv_HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK=yes,
samba_cv_HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK=no)])
if test x"$samba_cv_HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK" = x"yes"; then
AC_DEFINE(HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK,1,
[Whether krb5_keytab_entry has keyblock member])
fi
if test x"$ac_cv_lib_ext_krb5_krb5_mk_req_extended" = x"yes"; then
AC_DEFINE(HAVE_KRB5,1,[Whether to have KRB5 support])
AC_DEFINE(WITH_ADS,1,[Whether to include Active Directory support])
AC_MSG_CHECKING(whether Active Directory and KRB5 support is used)
AC_MSG_RESULT(yes)
else
if test x"$with_ads_support" = x"yes"; then
AC_MSG_ERROR(libkrb5 is needed for Active Directory support)
else
AC_MSG_WARN(libkrb5 is needed for Active Directory support)
fi
KRB5_LIBS=""
with_ads_support=no
fi
LIBS="$ac_save_LIBS"
fi

View File

@ -4,6 +4,8 @@
Copyright (C) Andrew Tridgell 2001
Copyright (C) Remus Koos 2001
Copyright (C) Luke Howard 2003
Copyright (C) Guenther Deschner 2003
Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -24,38 +26,181 @@
#ifdef HAVE_KRB5
static void free_keytab(krb5_context context, krb5_keytab keytab)
{
int ret=0;
if (keytab)
ret = krb5_kt_close(context, keytab);
if (ret) {
DEBUG(3, ("krb5_kt_close failed (%s)\n",
error_message(ret)));
}
}
#ifdef HAVE_MEMORY_KEYTAB
static krb5_error_code create_keytab(krb5_context context,
krb5_principal host_princ,
char *host_princ_s,
krb5_data password,
krb5_enctype *enctypes,
krb5_keytab *keytab,
char *keytab_name)
{
krb5_keytab_entry entry;
krb5_kvno kvno = 1;
krb5_error_code ret;
krb5_keyblock *key;
int i;
DEBUG(10,("creating keytab: %s\n", keytab_name));
ret = krb5_kt_resolve(context, keytab_name, keytab);
if (ret)
return ret;
if (!(key = (krb5_keyblock *)malloc(sizeof(*key)))) {
return ENOMEM;
}
/* add keytab entries for all encryption types */
for ( i=0; enctypes[i]; i++ ) {
if (create_kerberos_key_from_string(context, host_princ, &password, key, enctypes[i])) {
continue;
}
entry.principal = host_princ;
entry.vno = kvno;
#if !defined(HAVE_KRB5_KEYTAB_ENTRY_KEY) && !defined(HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK)
#error krb5_keytab_entry has no key or keyblock member
#endif
#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEY /* MIT */
entry.key = *key;
#endif
#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK /* Heimdal */
entry.keyblock = *key;
#endif
DEBUG(10,("adding keytab-entry for (%s) with encryption type (%d)\n",
host_princ_s, enctypes[i]));
ret = krb5_kt_add_entry(context, *keytab, &entry);
if (ret) {
DEBUG(1,("adding entry to keytab failed (%s)\n",
error_message(ret)));
free_keytab(context, *keytab);
return ret;
}
}
krb5_free_keyblock(context, key);
return 0;
}
#endif
static BOOL setup_keytab(krb5_context context,
krb5_principal host_princ,
char *host_princ_s,
krb5_data password,
krb5_enctype *enctypes,
krb5_keytab *keytab)
{
char *keytab_name = NULL;
krb5_error_code ret;
/* check if we have to setup a keytab - not currently enabled
I've put this in so that the else block below functions
the same way that it will when this code is turned on */
if (0 /* will later be *lp_keytab() */) {
/* use a file-keytab */
asprintf(&keytab_name, "%s:%s",
""
/* KRB5_KT_FILE_PREFIX, "FILE" or
"WRFILE" depending on HEeimdal or MIT */,
"" /* will later be lp_keytab() */);
DEBUG(10,("will use filebased keytab: %s\n", keytab_name));
ret = krb5_kt_resolve(context, keytab_name, keytab);
if (ret) {
DEBUG(3,("cannot resolve keytab name %s (%s)\n",
keytab_name,
error_message(ret)));
SAFE_FREE(keytab_name);
return False;
}
}
#if defined(HAVE_MEMORY_KEYTAB)
else {
/* setup a in-memory-keytab */
asprintf(&keytab_name, "MEMORY:");
ret = create_keytab(context, host_princ, host_princ_s, password, enctypes,
keytab, keytab_name);
if (ret) {
DEBUG(3,("unable to create MEMORY: keytab (%s)\n",
error_message(ret)));
SAFE_FREE(keytab_name);
return False;
}
}
#endif
SAFE_FREE(keytab_name);
return True;
}
/*
verify an incoming ticket and parse out the principal name and
authorization_data if available
*/
NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket,
NTSTATUS ads_verify_ticket(const char *realm, const DATA_BLOB *ticket,
char **principal, DATA_BLOB *auth_data,
DATA_BLOB *ap_rep,
uint8 session_key[16])
DATA_BLOB *session_key)
{
krb5_context context;
NTSTATUS sret = NT_STATUS_LOGON_FAILURE;
krb5_context context = NULL;
krb5_auth_context auth_context = NULL;
krb5_keytab keytab = NULL;
krb5_data packet;
krb5_ticket *tkt = NULL;
krb5_rcache rcache = NULL;
int ret, i;
krb5_keyblock * key;
krb5_keyblock *key = NULL;
krb5_principal host_princ;
char *host_princ_s;
char *host_princ_s = NULL;
BOOL free_host_princ = False;
fstring myname;
char *password_s;
char *password_s = NULL;
krb5_data password;
krb5_enctype *enctypes = NULL;
#if 0
krb5_address local_addr;
krb5_address remote_addr;
#endif
BOOL auth_ok = False;
ZERO_STRUCT(packet);
ZERO_STRUCT(password);
ZERO_STRUCTP(auth_data);
ZERO_STRUCTP(ap_rep);
if (!secrets_init()) {
DEBUG(1,("secrets_init failed\n"));
DEBUG(1,("ads_verify_ticket: secrets_init failed\n"));
return NT_STATUS_LOGON_FAILURE;
}
password_s = secrets_fetch_machine_password();
password_s = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
if (!password_s) {
DEBUG(1,("failed to fetch machine password\n"));
DEBUG(1,("ads_verify_ticket: failed to fetch machine password\n"));
return NT_STATUS_LOGON_FAILURE;
}
@ -64,83 +209,142 @@ NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket,
ret = krb5_init_context(&context);
if (ret) {
DEBUG(1,("krb5_init_context failed (%s)\n", error_message(ret)));
DEBUG(1,("ads_verify_ticket: krb5_init_context failed (%s)\n", error_message(ret)));
return NT_STATUS_LOGON_FAILURE;
}
ret = krb5_set_default_realm(context, ads->auth.realm);
ret = krb5_set_default_realm(context, realm);
if (ret) {
DEBUG(1,("krb5_set_default_realm failed (%s)\n", error_message(ret)));
return NT_STATUS_LOGON_FAILURE;
DEBUG(1,("ads_verify_ticket: krb5_set_default_realm failed (%s)\n", error_message(ret)));
sret = NT_STATUS_LOGON_FAILURE;
goto out;
}
/* this whole process is far more complex than I would
/* This whole process is far more complex than I would
like. We have to go through all this to allow us to store
the secret internally, instead of using /etc/krb5.keytab */
ret = krb5_auth_con_init(context, &auth_context);
if (ret) {
DEBUG(1,("krb5_auth_con_init failed (%s)\n", error_message(ret)));
return NT_STATUS_LOGON_FAILURE;
DEBUG(1,("ads_verify_ticket: krb5_auth_con_init failed (%s)\n", error_message(ret)));
sret = NT_STATUS_LOGON_FAILURE;
goto out;
}
fstrcpy(myname, lp_netbios_name());
strlower(myname);
fstrcpy(myname, global_myname());
strlower_m(myname);
asprintf(&host_princ_s, "HOST/%s@%s", myname, lp_realm());
ret = krb5_parse_name(context, host_princ_s, &host_princ);
if (ret) {
DEBUG(1,("krb5_parse_name(%s) failed (%s)\n", host_princ_s, error_message(ret)));
return NT_STATUS_LOGON_FAILURE;
DEBUG(1,("ads_verify_ticket: krb5_parse_name(%s) failed (%s)\n",
host_princ_s, error_message(ret)));
sret = NT_STATUS_LOGON_FAILURE;
goto out;
}
if (!(key = (krb5_keyblock *)malloc(sizeof(*key)))) {
return NT_STATUS_NO_MEMORY;
free_host_princ = True;
/*
* JRA. We must set the rcache here. This will prevent replay attacks.
*/
ret = krb5_get_server_rcache(context, krb5_princ_component(context, host_princ, 0), &rcache);
if (ret) {
DEBUG(1,("ads_verify_ticket: krb5_get_server_rcache failed (%s)\n", error_message(ret)));
sret = NT_STATUS_LOGON_FAILURE;
goto out;
}
ret = krb5_auth_con_setrcache(context, auth_context, rcache);
if (ret) {
DEBUG(1,("ads_verify_ticket: krb5_auth_con_setrcache failed (%s)\n", error_message(ret)));
sret = NT_STATUS_LOGON_FAILURE;
goto out;
}
/* CIFS doesn't use addresses in tickets. This would breat NAT. JRA */
if ((ret = get_kerberos_allowed_etypes(context, &enctypes))) {
DEBUG(1,("ads_verify_ticket: krb5_get_permitted_enctypes failed (%s)\n",
error_message(ret)));
sret = NT_STATUS_LOGON_FAILURE;
goto out;
}
/* Lock a mutex surrounding the replay as there is no locking in the MIT krb5
* code surrounding the replay cache... */
if (!grab_server_mutex("replay cache mutex")) {
DEBUG(1,("ads_verify_ticket: unable to protect replay cache with mutex.\n"));
sret = NT_STATUS_LOGON_FAILURE;
goto out;
}
if (!setup_keytab(context, host_princ, host_princ_s, password,
enctypes, &keytab)) {
DEBUG(3,("ads_verify_ticket: unable to setup keytab\n"));
sret = NT_STATUS_LOGON_FAILURE;
goto out;
}
if ((ret = get_kerberos_allowed_etypes(context, &enctypes))) {
DEBUG(1,("krb5_get_permitted_enctypes failed (%s)\n",
error_message(ret)));
return NT_STATUS_LOGON_FAILURE;
}
/* we need to setup a auth context with each possible encoding type in turn */
/* We need to setup a auth context with each possible encoding type in turn. */
for (i=0;enctypes[i];i++) {
if (!(key = (krb5_keyblock *)malloc(sizeof(*key)))) {
sret = NT_STATUS_NO_MEMORY;
goto out;
}
if (create_kerberos_key_from_string(context, host_princ, &password, key, enctypes[i])) {
continue;
}
krb5_auth_con_setuseruserkey(context, auth_context, key);
krb5_free_keyblock(context, key);
packet.length = ticket->length;
packet.data = (krb5_pointer)ticket->data;
if (!(ret = krb5_rd_req(context, &auth_context, &packet,
NULL, keytab, NULL, &tkt))) {
free_kerberos_etypes(context, enctypes);
#ifdef HAVE_MEMORY_KEYTAB
host_princ,
#else
NULL,
#endif
keytab, NULL, &tkt))) {
DEBUG(10,("ads_verify_ticket: enc type [%u] decrypted message !\n",
(unsigned int)enctypes[i] ));
auth_ok = True;
break;
}
DEBUG((ret != KRB5_BAD_ENCTYPE) ? 3 : 10,
("ads_verify_ticket: enc type [%u] failed to decrypt with error %s\n",
(unsigned int)enctypes[i], error_message(ret)));
}
release_server_mutex();
if (!auth_ok) {
DEBUG(3,("krb5_rd_req with auth failed (%s)\n",
DEBUG(3,("ads_verify_ticket: krb5_rd_req with auth failed (%s)\n",
error_message(ret)));
return NT_STATUS_LOGON_FAILURE;
sret = NT_STATUS_LOGON_FAILURE;
goto out;
}
ret = krb5_mk_rep(context, auth_context, &packet);
if (ret) {
DEBUG(3,("Failed to generate mutual authentication reply (%s)\n",
DEBUG(3,("ads_verify_ticket: Failed to generate mutual authentication reply (%s)\n",
error_message(ret)));
krb5_auth_con_free(context, auth_context);
return NT_STATUS_LOGON_FAILURE;
sret = NT_STATUS_LOGON_FAILURE;
goto out;
}
*ap_rep = data_blob(packet.data, packet.length);
free(packet.data);
krb5_get_smb_session_key(context, auth_context, session_key);
DEBUG(0,("SMB session key (from ticket) follows:\n"));
dump_data(0, session_key, 16);
get_krb5_smb_session_key(context, auth_context, session_key, True);
dump_data_pw("SMB session key (from ticket)\n", session_key->data, session_key->length);
#if 0
file_save("/tmp/ticket.dat", ticket->data, ticket->length);
@ -148,26 +352,60 @@ NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket,
get_auth_data_from_tkt(auth_data, tkt);
#if 0
{
TALLOC_CTX *ctx = talloc_init("pac data");
decode_pac_data(auth_data, ctx);
talloc_destroy(ctx);
}
#endif
#if 0
if (tkt->enc_part2) {
file_save("/tmp/authdata.dat",
tkt->enc_part2->authorization_data[0]->contents,
tkt->enc_part2->authorization_data[0]->length);
}
#endif
/* get rid of all resources associated with the keytab */
if (keytab) free_keytab(context, keytab);
if ((ret = krb5_unparse_name(context, get_principal_from_tkt(tkt),
principal))) {
DEBUG(3,("krb5_unparse_name failed (%s)\n",
DEBUG(3,("ads_verify_ticket: krb5_unparse_name failed (%s)\n",
error_message(ret)));
data_blob_free(auth_data);
data_blob_free(ap_rep);
krb5_auth_con_free(context, auth_context);
return NT_STATUS_LOGON_FAILURE;
sret = NT_STATUS_LOGON_FAILURE;
goto out;
}
krb5_auth_con_free(context, auth_context);
sret = NT_STATUS_OK;
return NT_STATUS_OK;
out:
if (!NT_STATUS_IS_OK(sret))
data_blob_free(auth_data);
if (!NT_STATUS_IS_OK(sret))
data_blob_free(ap_rep);
if (free_host_princ)
krb5_free_principal(context, host_princ);
if (tkt != NULL)
krb5_free_ticket(context, tkt);
free_kerberos_etypes(context, enctypes);
SAFE_FREE(password_s);
SAFE_FREE(host_princ_s);
if (auth_context)
krb5_auth_con_free(context, auth_context);
if (context)
krb5_free_context(context);
return sret;
}
#endif /* HAVE_KRB5 */

View File

@ -143,7 +143,7 @@ static krb5_error_code build_kpasswd_request(uint16 pversion,
else
return EINVAL;
encoded_setpw.data = setpw.data;
encoded_setpw.data = (char *)setpw.data;
encoded_setpw.length = setpw.length;
ret = krb5_mk_priv(context, auth_context,
@ -178,47 +178,39 @@ static krb5_error_code build_kpasswd_request(uint16 pversion,
return 0;
}
static krb5_error_code krb5_setpw_result_code_string(krb5_context context,
int result_code,
char **code_string)
{
switch (result_code) {
case KRB5_KPASSWD_MALFORMED:
*code_string = "Malformed request error";
break;
case KRB5_KPASSWD_HARDERROR:
*code_string = "Server error";
break;
case KRB5_KPASSWD_AUTHERROR:
*code_string = "Authentication error";
break;
case KRB5_KPASSWD_SOFTERROR:
*code_string = "Password change rejected";
break;
case KRB5_KPASSWD_ACCESSDENIED:
*code_string = "Client does not have proper authorization";
break;
case KRB5_KPASSWD_BAD_VERSION:
*code_string = "Protocol version not supported";
break;
case KRB5_KPASSWD_INITIAL_FLAG_NEEDED:
*code_string = "Authorization ticket must have initial flag set";
break;
case KRB5_KPASSWD_POLICY_REJECT:
*code_string = "Password rejected due to policy requirements";
break;
case KRB5_KPASSWD_BAD_PRINCIPAL:
*code_string = "Target principal does not exist";
break;
case KRB5_KPASSWD_ETYPE_NOSUPP:
*code_string = "Unsupported encryption type";
break;
default:
*code_string = "Password change failed";
break;
}
static const struct kpasswd_errors {
int result_code;
const char *error_string;
} kpasswd_errors[] = {
{KRB5_KPASSWD_MALFORMED, "Malformed request error"},
{KRB5_KPASSWD_HARDERROR, "Server error"},
{KRB5_KPASSWD_AUTHERROR, "Authentication error"},
{KRB5_KPASSWD_SOFTERROR, "Password change rejected"},
{KRB5_KPASSWD_ACCESSDENIED, "Client does not have proper authorization"},
{KRB5_KPASSWD_BAD_VERSION, "Protocol version not supported"},
{KRB5_KPASSWD_INITIAL_FLAG_NEEDED, "Authorization ticket must have initial flag set"},
{KRB5_KPASSWD_POLICY_REJECT, "Password rejected due to policy requirements"},
{KRB5_KPASSWD_BAD_PRINCIPAL, "Target principal does not exist"},
{KRB5_KPASSWD_ETYPE_NOSUPP, "Unsupported encryption type"},
{0, NULL}
};
return(0);
static krb5_error_code setpw_result_code_string(krb5_context context,
int result_code,
const char **code_string)
{
unsigned int idx = 0;
while (kpasswd_errors[idx].error_string != NULL) {
if (kpasswd_errors[idx].result_code ==
result_code) {
*code_string = kpasswd_errors[idx].error_string;
return 0;
}
idx++;
}
*code_string = "Password change failed";
return (0);
}
static krb5_error_code parse_setpw_reply(krb5_context context,
@ -318,8 +310,8 @@ static krb5_error_code parse_setpw_reply(krb5_context context,
if(res_code == KRB5_KPASSWD_SUCCESS)
return 0;
else {
char *errstr;
krb5_setpw_result_code_string(context, res_code, &errstr);
const char *errstr;
setpw_result_code_string(context, res_code, &errstr);
DEBUG(1, ("Error changing password: %s\n", errstr));
switch(res_code) {
@ -465,8 +457,8 @@ static ADS_STATUS do_krb5_kpasswd_request(krb5_context context,
return ADS_SUCCESS;
}
ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char *newpw,
int time_offset)
ADS_STATUS ads_krb5_set_password(const char *kdc_host, const char *princ,
const char *newpw, int time_offset)
{
ADS_STATUS aret;
@ -546,7 +538,6 @@ ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char
krb5_free_creds(context, credsp);
krb5_free_principal(context, creds.client);
krb5_free_principal(context, creds.server);
krb5_free_principal(context, principal);
krb5_free_context(context);
@ -579,11 +570,11 @@ kerb_prompter(krb5_context ctx, void *data,
return 0;
}
ADS_STATUS krb5_chg_password(const char *kdc_host,
const char *principal,
const char *oldpw,
const char *newpw,
int time_offset)
static ADS_STATUS ads_krb5_chg_password(const char *kdc_host,
const char *principal,
const char *oldpw,
const char *newpw,
int time_offset)
{
ADS_STATUS aret;
krb5_error_code ret;
@ -657,11 +648,11 @@ ADS_STATUS kerberos_set_password(const char *kpasswd_server,
}
if (!strcmp(auth_principal, target_principal))
return krb5_chg_password(kpasswd_server, target_principal,
auth_password, new_password, time_offset);
return ads_krb5_chg_password(kpasswd_server, target_principal,
auth_password, new_password, time_offset);
else
return krb5_set_password(kpasswd_server, target_principal,
new_password, time_offset);
return ads_krb5_set_password(kpasswd_server, target_principal,
new_password, time_offset);
}
@ -673,24 +664,22 @@ ADS_STATUS kerberos_set_password(const char *kpasswd_server,
* @return status of password change
**/
ADS_STATUS ads_set_machine_password(ADS_STRUCT *ads,
const char *hostname,
const char *machine_account,
const char *password)
{
ADS_STATUS status;
char *host = strdup(hostname);
char *principal;
strlower(host);
char *principal = NULL;
/*
we need to use the '$' form of the name here, as otherwise the
server might end up setting the password for a user instead
we need to use the '$' form of the name here (the machine account name),
as otherwise the server might end up setting the password for a user
instead
*/
asprintf(&principal, "%s$@%s", host, ads->auth.realm);
asprintf(&principal, "%s@%s", machine_account, ads->config.realm);
status = krb5_set_password(ads->auth.kdc_server, principal, password, ads->auth.time_offset);
status = ads_krb5_set_password(ads->auth.kdc_server, principal,
password, ads->auth.time_offset);
free(host);
free(principal);
return status;

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/*
Unix SMB/CIFS implementation.
ads (active directory) printer utility library
Copyright (C) Jim McDonough 2002
Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -31,7 +31,7 @@ ADS_STATUS ads_find_printer_on_server(ADS_STRUCT *ads, void **res,
const char *printer, const char *servername)
{
ADS_STATUS status;
char *srv_dn, **srv_cn, *exp;
char *srv_dn, **srv_cn, *s;
const char *attrs[] = {"*", "nTSecurityDescriptor", NULL};
status = ads_find_machine_acct(ads, res, servername);
@ -44,15 +44,29 @@ ADS_STATUS ads_find_printer_on_server(ADS_STRUCT *ads, void **res,
srv_cn = ldap_explode_dn(srv_dn, 1);
ads_msgfree(ads, *res);
asprintf(&exp, "(cn=%s-%s)", srv_cn[0], printer);
status = ads_search(ads, res, exp, attrs);
asprintf(&s, "(cn=%s-%s)", srv_cn[0], printer);
status = ads_search(ads, res, s, attrs);
ldap_memfree(srv_dn);
ldap_value_free(srv_cn);
free(exp);
free(s);
return status;
}
ADS_STATUS ads_find_printers(ADS_STRUCT *ads, void **res)
{
char *ldap_expr;
const char *attrs[] = { "objectClass", "printerName", "location", "driverName",
"serverName", "description", NULL };
/* For the moment only display all printers */
ldap_expr = "(&(!(showInAdvancedViewOnly=TRUE))(uncName=*)"
"(objectCategory=printQueue))";
return ads_search(ads, res, ldap_expr, attrs);
}
/*
modify a printer entry in the directory
*/
@ -338,4 +352,3 @@ BOOL get_local_printer_publishing_data(TALLOC_CTX *mem_ctx,
}
#endif

View File

@ -1,7 +1,7 @@
/*
Unix SMB/CIFS implementation.
ads (active directory) utility library
Copyright (C) Jim McDonough 2002
Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -28,16 +28,16 @@
ADS_STATUS ads_find_user_acct(ADS_STRUCT *ads, void **res, const char *user)
{
ADS_STATUS status;
char *exp;
char *ldap_exp;
const char *attrs[] = {"*", NULL};
char *escaped_user = escape_ldap_string_alloc(user);
if (!escaped_user) {
return ADS_ERROR(LDAP_NO_MEMORY);
}
asprintf(&exp, "(samAccountName=%s)", escaped_user);
status = ads_search(ads, res, exp, attrs);
SAFE_FREE(exp);
asprintf(&ldap_exp, "(samAccountName=%s)", escaped_user);
status = ads_search(ads, res, ldap_exp, attrs);
SAFE_FREE(ldap_exp);
SAFE_FREE(escaped_user);
return status;
}

View File

@ -28,13 +28,15 @@
this is supposed to catch dropped connections and auto-reconnect
*/
ADS_STATUS ads_do_search_retry(ADS_STRUCT *ads, const char *bind_path, int scope,
const char *exp,
const char *expr,
const char **attrs, void **res)
{
ADS_STATUS status;
int count = 3;
char *bp;
*res = NULL;
if (!ads->ld &&
time(NULL) - ads->last_attempt < ADS_RECONNECT_TIME) {
return ADS_ERROR(LDAP_SERVER_DOWN);
@ -42,48 +44,58 @@ ADS_STATUS ads_do_search_retry(ADS_STRUCT *ads, const char *bind_path, int scope
bp = strdup(bind_path);
if (!bp)
if (!bp) {
return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
}
while (count--) {
status = ads_do_search_all(ads, bp, scope, exp, attrs, res);
*res = NULL;
status = ads_do_search_all(ads, bp, scope, expr, attrs, res);
if (ADS_ERR_OK(status)) {
DEBUG(5,("Search for %s gave %d replies\n",
exp, ads_count_replies(ads, *res)));
free(bp);
expr, ads_count_replies(ads, *res)));
SAFE_FREE(bp);
return status;
}
if (*res) ads_msgfree(ads, *res);
if (*res)
ads_msgfree(ads, *res);
*res = NULL;
DEBUG(3,("Reopening ads connection to realm '%s' after error %s\n",
ads->config.realm, ads_errstr(status)));
if (ads->ld) {
ldap_unbind(ads->ld);
}
ads->ld = NULL;
status = ads_connect(ads);
if (!ADS_ERR_OK(status)) {
DEBUG(1,("ads_search_retry: failed to reconnect (%s)\n",
ads_errstr(status)));
ads_destroy(&ads);
free(bp);
SAFE_FREE(bp);
return status;
}
}
free(bp);
SAFE_FREE(bp);
if (!ADS_ERR_OK(status))
DEBUG(1,("ads reopen failed after error %s\n",
ads_errstr(status)));
DEBUG(1,("ads reopen failed after error %s\n", ads_errstr(status)));
return status;
}
ADS_STATUS ads_search_retry(ADS_STRUCT *ads, void **res,
const char *exp,
const char *expr,
const char **attrs)
{
return ads_do_search_retry(ads, ads->config.bind_path, LDAP_SCOPE_SUBTREE,
exp, attrs, res);
expr, attrs, res);
}
ADS_STATUS ads_search_retry_dn(ADS_STRUCT *ads, void **res,

View File

@ -60,7 +60,7 @@ static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads)
msg1 = gen_negTokenTarg(mechs, blob);
data_blob_free(&blob);
cred.bv_val = msg1.data;
cred.bv_val = (char *)msg1.data;
cred.bv_len = msg1.length;
rc = ldap_sasl_bind_s(ads->ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred);
@ -96,7 +96,7 @@ static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads)
nthash, 24,
lp_workgroup(),
ads->auth.user_name,
lp_netbios_name(),
global_myname(),
sess_key, 16,
neg_flags);
@ -106,7 +106,7 @@ static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads)
data_blob_free(&blob);
/* now send the auth packet and we should be done */
cred.bv_val = auth.data;
cred.bv_val = (char *)auth.data;
cred.bv_len = auth.length;
rc = ldap_sasl_bind_s(ads->ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred);
@ -124,21 +124,23 @@ static ADS_STATUS ads_sasl_spnego_krb5_bind(ADS_STRUCT *ads, const char *princip
{
DATA_BLOB blob;
struct berval cred, *scred;
DATA_BLOB session_key;
int rc;
blob = spnego_gen_negTokenTarg(principal, ads->auth.time_offset);
rc = spnego_gen_negTokenTarg(principal, ads->auth.time_offset, &blob, &session_key);
if (!blob.data) {
return ADS_ERROR(LDAP_OPERATIONS_ERROR);
if (rc) {
return ADS_ERROR_KRB5(rc);
}
/* now send the auth packet and we should be done */
cred.bv_val = blob.data;
cred.bv_val = (char *)blob.data;
cred.bv_len = blob.length;
rc = ldap_sasl_bind_s(ads->ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred);
data_blob_free(&blob);
data_blob_free(&session_key);
return ADS_ERROR(rc);
}
@ -165,6 +167,8 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
blob = data_blob(scred->bv_val, scred->bv_len);
ber_bvfree(scred);
#if 0
file_save("sasl_spnego.dat", blob.data, blob.length);
#endif
@ -195,11 +199,18 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
status = ads_sasl_spnego_krb5_bind(ads, principal);
if (ADS_ERR_OK(status))
return status;
if (ads_kinit_password(ads) == 0) {
status = ADS_ERROR_KRB5(ads_kinit_password(ads));
if (ADS_ERR_OK(status)) {
status = ads_sasl_spnego_krb5_bind(ads, principal);
}
if (ADS_ERR_OK(status))
/* only fallback to NTLMSSP if allowed */
if (ADS_ERR_OK(status) ||
!(ads->auth.flags & ADS_AUTH_ALLOW_NTLMSSP)) {
return status;
}
}
#endif
@ -223,13 +234,13 @@ failed:
*/
static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
{
int minor_status;
uint32 minor_status;
gss_name_t serv_name;
gss_buffer_desc input_name;
gss_ctx_id_t context_handle;
gss_OID mech_type = GSS_C_NULL_OID;
gss_buffer_desc output_token, input_token;
OM_uint32 ret_flags, conf_state;
uint32 ret_flags, conf_state;
struct berval cred;
struct berval *scred;
int i=0;
@ -324,7 +335,7 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
gss_release_name(&minor_status, &serv_name);
gss_rc = gss_unwrap(&minor_status,context_handle,&input_token,&output_token,
&conf_state,NULL);
(int *)&conf_state,NULL);
if (gss_rc) {
status = ADS_ERROR_GSS(gss_rc, minor_status);
goto failed;
@ -349,13 +360,13 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
*p++ = max_msg_size>>16;
*p++ = max_msg_size>>8;
*p++ = max_msg_size;
snprintf(p, strlen(ads->config.bind_path)+4, "dn:%s", ads->config.bind_path);
p += strlen(p);
snprintf((char *)p, strlen(ads->config.bind_path)+4, "dn:%s", ads->config.bind_path);
p += strlen((const char *)p);
output_token.length = PTR_DIFF(p, output_token.value);
gss_rc = gss_wrap(&minor_status, context_handle,0,GSS_C_QOP_DEFAULT,
&output_token, &conf_state,
&output_token, (int *)&conf_state,
&input_token);
if (gss_rc) {
status = ADS_ERROR_GSS(gss_rc, minor_status);

View File

@ -24,35 +24,42 @@
ADS_STATUS ads_change_trust_account_password(ADS_STRUCT *ads, char *host_principal)
{
char *tmp_password;
char *password;
char *new_password;
char *service_principal;
ADS_STATUS ret;
char *tmp_password;
char *password;
char *new_password;
char *service_principal = NULL;
ADS_STATUS ret;
uint32 sec_channel_type;
if ((password = secrets_fetch_machine_password()) == NULL) {
DEBUG(1,("Failed to retrieve password for principal %s\n", host_principal));
return ADS_ERROR_SYSTEM(ENOENT);
}
if ((password = secrets_fetch_machine_password(lp_workgroup(), NULL, &sec_channel_type)) == NULL) {
DEBUG(1,("Failed to retrieve password for principal %s\n", host_principal));
return ADS_ERROR_SYSTEM(ENOENT);
}
tmp_password = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
new_password = strdup(tmp_password);
asprintf(&service_principal, "HOST/%s", host_principal);
tmp_password = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
new_password = strdup(tmp_password);
ret = kerberos_set_password(ads->auth.kdc_server, service_principal, password, service_principal, new_password, ads->auth.time_offset);
asprintf(&service_principal, "HOST/%s", host_principal);
if (!ADS_ERR_OK(ret)) goto failed;
if (!service_principal) {
DEBUG(1,("asprintf() failed principal %s\n", host_principal));
return ADS_ERROR_SYSTEM(ENOMEM);
}
if (!secrets_store_machine_password(new_password)) {
DEBUG(1,("Failed to save machine password\n"));
return ADS_ERROR_SYSTEM(EACCES);
}
ret = kerberos_set_password(ads->auth.kdc_server, service_principal, password, service_principal, new_password, ads->auth.time_offset);
if (!ADS_ERR_OK(ret)) goto failed;
if (!secrets_store_machine_password(new_password, lp_workgroup(), sec_channel_type)) {
DEBUG(1,("Failed to save machine password\n"));
return ADS_ERROR_SYSTEM(EACCES);
}
failed:
SAFE_FREE(service_principal);
SAFE_FREE(new_password);
SAFE_FREE(service_principal);
SAFE_FREE(new_password);
return ret;
return ret;
}

View File

@ -97,7 +97,9 @@
return ret;
}
krb5_use_enctype(context, &eblock, enctype);
return krb5_string_to_key(context, &eblock, key, password, &salt);
ret = krb5_string_to_key(context, &eblock, key, password, &salt);
SAFE_FREE(salt.data);
return ret;
}
#elif defined(HAVE_KRB5_GET_PW_SALT) && defined(HAVE_KRB5_STRING_TO_KEY_SALT)
int create_kerberos_key_from_string(krb5_context context,
@ -235,12 +237,12 @@ krb5_error_code get_kerberos_allowed_etypes(krb5_context context,
/*
we can't use krb5_mk_req because w2k wants the service to be in a particular format
*/
static krb5_error_code krb5_mk_req2(krb5_context context,
krb5_auth_context *auth_context,
const krb5_flags ap_req_options,
const char *principal,
krb5_ccache ccache,
krb5_data *outbuf)
static krb5_error_code ads_krb5_mk_req(krb5_context context,
krb5_auth_context *auth_context,
const krb5_flags ap_req_options,
const char *principal,
krb5_ccache ccache,
krb5_data *outbuf)
{
krb5_error_code retval;
krb5_principal server;
@ -255,7 +257,7 @@ static krb5_error_code krb5_mk_req2(krb5_context context,
}
/* obtain ticket & session key */
memset((char *)&creds, 0, sizeof(creds));
ZERO_STRUCT(creds);
if ((retval = krb5_copy_principal(context, server, &creds.server))) {
DEBUG(1,("krb5_copy_principal failed (%s)\n",
error_message(retval)));
@ -305,14 +307,14 @@ cleanup_princ:
/*
get a kerberos5 ticket for the given service
*/
DATA_BLOB krb5_get_ticket(const char *principal, time_t time_offset)
int cli_krb5_get_ticket(const char *principal, time_t time_offset,
DATA_BLOB *ticket, DATA_BLOB *session_key_krb5)
{
krb5_error_code retval;
krb5_data packet;
krb5_ccache ccdef;
krb5_context context;
krb5_auth_context auth_context = NULL;
DATA_BLOB ret;
krb5_enctype enc_types[] = {
#ifdef ENCTYPE_ARCFOUR_HMAC
ENCTYPE_ARCFOUR_HMAC,
@ -344,56 +346,76 @@ DATA_BLOB krb5_get_ticket(const char *principal, time_t time_offset)
goto failed;
}
if ((retval = krb5_mk_req2(context,
&auth_context,
0,
principal,
ccdef, &packet))) {
if ((retval = ads_krb5_mk_req(context,
&auth_context,
AP_OPTS_USE_SUBKEY,
principal,
ccdef, &packet))) {
goto failed;
}
ret = data_blob(packet.data, packet.length);
get_krb5_smb_session_key(context, auth_context, session_key_krb5, False);
*ticket = data_blob(packet.data, packet.length);
/* Hmm, heimdal dooesn't have this - what's the correct call? */
/* krb5_free_data_contents(context, &packet); */
krb5_free_context(context);
return ret;
#ifdef HAVE_KRB5_FREE_DATA_CONTENTS
krb5_free_data_contents(context, &packet);
#endif
failed:
if ( context )
krb5_free_context(context);
return data_blob(NULL, 0);
return retval;
}
BOOL krb5_get_smb_session_key(krb5_context context, krb5_auth_context auth_context, uint8 session_key[16])
BOOL get_krb5_smb_session_key(krb5_context context, krb5_auth_context auth_context, DATA_BLOB *session_key, BOOL remote)
{
#ifdef ENCTYPE_ARCFOUR_HMAC
krb5_keyblock *skey;
#endif
krb5_error_code err;
BOOL ret = False;
memset(session_key, 0, 16);
#ifdef ENCTYPE_ARCFOUR_HMAC
if (krb5_auth_con_getremotesubkey(context, auth_context, &skey) == 0 && skey != NULL) {
if (KRB5_KEY_TYPE(skey) ==
ENCTYPE_ARCFOUR_HMAC
&& KRB5_KEY_LENGTH(skey) == 16) {
memcpy(session_key, KRB5_KEY_DATA(skey), KRB5_KEY_LENGTH(skey));
ret = True;
}
if (remote)
err = krb5_auth_con_getremotesubkey(context, auth_context, &skey);
else
err = krb5_auth_con_getlocalsubkey(context, auth_context, &skey);
if (err == 0 && skey != NULL) {
DEBUG(10, ("Got KRB5 session key of length %d\n", KRB5_KEY_LENGTH(skey)));
*session_key = data_blob(KRB5_KEY_DATA(skey), KRB5_KEY_LENGTH(skey));
dump_data_pw("KRB5 Session Key:\n", session_key->data, session_key->length);
ret = True;
krb5_free_keyblock(context, skey);
} else {
DEBUG(10, ("KRB5 error getting session key %d\n", err));
}
#endif /* ENCTYPE_ARCFOUR_HMAC */
return ret;
}
#if defined(HAVE_KRB5_PRINCIPAL_GET_COMP_STRING) && !defined(HAVE_KRB5_PRINC_COMPONENT)
const krb5_data *krb5_princ_component(krb5_context context, krb5_principal principal, int i )
{
static krb5_data kdata;
kdata.data = krb5_principal_get_comp_string(context, principal, i);
kdata.length = strlen(kdata.data);
return &kdata;
}
#endif
#else /* HAVE_KRB5 */
/* this saves a few linking headaches */
DATA_BLOB krb5_get_ticket(const char *principal, time_t time_offset)
{
/* this saves a few linking headaches */
int cli_krb5_get_ticket(const char *principal, time_t time_offset,
DATA_BLOB *ticket, DATA_BLOB *session_key_krb5)
{
DEBUG(0,("NO KERBEROS SUPPORT\n"));
return data_blob(NULL, 0);
}
return 1;
}
#endif

View File

@ -2,7 +2,7 @@
Unix SMB/CIFS implementation.
simple kerberos5/SPNEGO routines
Copyright (C) Andrew Tridgell 2001
Copyright (C) Jim McDonough 2002
Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
Copyright (C) Luke Howard 2003
This program is free software; you can redistribute it and/or modify
@ -323,24 +323,30 @@ BOOL spnego_parse_krb5_wrap(DATA_BLOB blob, DATA_BLOB *ticket, uint8 tok_id[2])
generate a SPNEGO negTokenTarg packet, ready for a EXTENDED_SECURITY
kerberos session setup
*/
DATA_BLOB spnego_gen_negTokenTarg(const char *principal, int time_offset)
int spnego_gen_negTokenTarg(const char *principal, int time_offset,
DATA_BLOB *targ,
DATA_BLOB *session_key_krb5)
{
DATA_BLOB tkt, tkt_wrapped, targ;
int retval;
DATA_BLOB tkt, tkt_wrapped;
const char *krb_mechs[] = {OID_KERBEROS5_OLD, OID_NTLMSSP, NULL};
/* get a kerberos ticket for the service */
tkt = krb5_get_ticket(principal, time_offset);
/* get a kerberos ticket for the service and extract the session key */
retval = cli_krb5_get_ticket(principal, time_offset, &tkt, session_key_krb5);
if (retval)
return retval;
/* wrap that up in a nice GSS-API wrapping */
tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
/* and wrap that in a shiny SPNEGO wrapper */
targ = gen_negTokenTarg(krb_mechs, tkt_wrapped);
*targ = gen_negTokenTarg(krb_mechs, tkt_wrapped);
data_blob_free(&tkt_wrapped);
data_blob_free(&tkt);
return targ;
return retval;
}