1
0
mirror of https://github.com/samba-team/samba.git synced 2025-12-03 04:23:50 +03:00
ldap and krb5 configure tests
libads/*.c and libcli/raw/clikrb5.c from 3.0

metze
This commit is contained in:
Stefan Metzmacher
-
parent 9bf405dd40
commit 64b5bfcd73
20 changed files with 1514 additions and 784 deletions

View File

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

107
source/aclocal.m4 vendored
View File

@@ -135,6 +135,113 @@ AC_DEFUN(AC_LIBTESTFUNC,
esac 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 Define an AC_DEFINE with ifndef guard.
dnl AC_N_DEFINE(VARIABLE [, VALUE]) dnl AC_N_DEFINE(VARIABLE [, VALUE])
define(AC_N_DEFINE, 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/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/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(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) 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 ## check checking for truncated salt. Wrapped by the
## $with_pam_for_crypt variable as above --jerry ## $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,[ AC_CACHE_CHECK([for a crypt that needs truncated salt],samba_cv_HAVE_TRUNCATED_SALT,[
crypt_LIBS="$LIBS" crypt_LIBS="$LIBS"
LIBS="$AUTHLIBS $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 { typedef struct {
void *ld; /* the active ldap structure */ void *ld; /* the active ldap structure */
struct in_addr ldap_ip; /* the ip of the active connection, if any */ struct in_addr ldap_ip; /* the ip of the active connection, if any */
@@ -38,9 +57,9 @@ typedef struct {
} config; } config;
} ADS_STRUCT; } ADS_STRUCT;
/* there are 4 possible types of errors the ads subsystem can produce */ /* there are 5 possible types of errors the ads subsystem can produce */
enum ads_error_type {ADS_ERROR_KRB5, ADS_ERROR_GSS, enum ads_error_type {ENUM_ADS_ERROR_KRB5, ENUM_ADS_ERROR_GSS,
ADS_ERROR_LDAP, ADS_ERROR_SYSTEM, ADS_ERROR_NT}; ENUM_ADS_ERROR_LDAP, ENUM_ADS_ERROR_SYSTEM, ENUM_ADS_ERROR_NT};
typedef struct { typedef struct {
enum ads_error_type error_type; enum ads_error_type error_type;
@@ -48,7 +67,7 @@ typedef struct {
int rc; int rc;
NTSTATUS nt_status; NTSTATUS nt_status;
} err; } 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 */ /* Where rc represents major_status of GSS API error */
int minor_status; int minor_status;
} ADS_STATUS; } ADS_STATUS;
@@ -61,13 +80,13 @@ typedef void **ADS_MODLIST;
/* macros to simplify error returning */ /* macros to simplify error returning */
#define ADS_ERROR(rc) ADS_ERROR_LDAP(rc) #define ADS_ERROR(rc) ADS_ERROR_LDAP(rc)
#define ADS_ERROR_LDAP(rc) ads_build_error(ADS_ERROR_LDAP, rc, 0) #define ADS_ERROR_LDAP(rc) ads_build_error(ENUM_ADS_ERROR_LDAP, rc, 0)
#define ADS_ERROR_SYSTEM(rc) ads_build_error(ADS_ERROR_SYSTEM, rc?rc:EINVAL, 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(ADS_ERROR_KRB5, rc, 0) #define ADS_ERROR_KRB5(rc) ads_build_error(ENUM_ADS_ERROR_KRB5, rc, 0)
#define ADS_ERROR_GSS(rc, minor) ads_build_error(ADS_ERROR_GSS, rc, minor) #define ADS_ERROR_GSS(rc, minor) ads_build_error(ENUM_ADS_ERROR_GSS, rc, minor)
#define ADS_ERROR_NT(rc) ads_build_nt_error(ADS_ERROR_NT,rc) #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) #define ADS_SUCCESS ADS_ERROR(0)
/* time between reconnect attempts */ /* time between reconnect attempts */
@@ -205,7 +224,11 @@ typedef void **ADS_MODLIST;
#define ADS_AUTH_NO_BIND 0x02 #define ADS_AUTH_NO_BIND 0x02
#define ADS_AUTH_ANON_BIND 0x04 #define ADS_AUTH_ANON_BIND 0x04
#define ADS_AUTH_SIMPLE_BIND 0x08 #define ADS_AUTH_SIMPLE_BIND 0x08
#define ADS_AUTH_ALLOW_NTLMSSP 0x10
/***************************************
Some krb5 compat stuff
***************************************/
/* Kerberos environment variable names */ /* Kerberos environment variable names */
#define KRB5_ENV_CCNAME "KRB5CCNAME" #define KRB5_ENV_CCNAME "KRB5CCNAME"
@@ -213,3 +236,36 @@ typedef void **ADS_MODLIST;
#if defined(HAVE_ENCTYPE_ARCFOUR_HMAC_MD5) #if defined(HAVE_ENCTYPE_ARCFOUR_HMAC_MD5)
#define ENCTYPE_ARCFOUR_HMAC ENCTYPE_ARCFOUR_HMAC_MD5 #define ENCTYPE_ARCFOUR_HMAC ENCTYPE_ARCFOUR_HMAC_MD5
#endif #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> #include <stropts.h>
#endif #endif
#ifdef HAVE_POLL_H
#include <poll.h>
#endif
#ifdef HAVE_SYS_CAPABILITY_H #ifdef HAVE_SYS_CAPABILITY_H
#if defined(BROKEN_REDHAT_7_SYSTEM_HEADERS) && !defined(_I386_STATFS_H) #if defined(BROKEN_REDHAT_7_SYSTEM_HEADERS) && !defined(_I386_STATFS_H)
@@ -721,7 +717,6 @@ extern int errno;
#include "../tdb/tdbutil.h" #include "../tdb/tdbutil.h"
#include "talloc.h" #include "talloc.h"
#include "nt_status.h" #include "nt_status.h"
#include "ads.h"
#include "interfaces.h" #include "interfaces.h"
#include "trans2.h" #include "trans2.h"
#include "ioctl.h" #include "ioctl.h"
@@ -734,6 +729,7 @@ extern int errno;
#include "version.h" #include "version.h"
#include "smb.h" #include "smb.h"
#include "ads.h"
#include "nameserv.h" #include "nameserv.h"
#include "secrets.h" #include "secrets.h"
@@ -1147,30 +1143,5 @@ time_t timegm(struct tm *tm);
#define VXFS_QUOTA #define VXFS_QUOTA
#endif #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 */ #endif /* _INCLUDES_H */

View File

@@ -34,7 +34,7 @@ NTSTATUS ads_name_to_sid(ADS_STRUCT *ads,
int count; int count;
ADS_STATUS rc; ADS_STATUS rc;
void *res = NULL; void *res = NULL;
char *exp; char *ldap_exp;
uint32 t; uint32 t;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL; NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
char *escaped_name = escape_ldap_string_alloc(name); char *escaped_name = escape_ldap_string_alloc(name);
@@ -45,15 +45,15 @@ NTSTATUS ads_name_to_sid(ADS_STRUCT *ads,
goto done; 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) { escaped_name, escaped_name, escaped_realm) == -1) {
DEBUG(1,("ads_name_to_sid: asprintf failed!\n")); DEBUG(1,("ads_name_to_sid: asprintf failed!\n"));
status = NT_STATUS_NO_MEMORY; status = NT_STATUS_NO_MEMORY;
goto done; goto done;
} }
rc = ads_search_retry(ads, &res, exp, attrs); rc = ads_search_retry(ads, &res, ldap_exp, attrs);
free(exp); free(ldap_exp);
if (!ADS_ERR_OK(rc)) { if (!ADS_ERR_OK(rc)) {
DEBUG(1,("name_to_sid ads_search: %s\n", ads_errstr(rc))); DEBUG(1,("name_to_sid ads_search: %s\n", ads_errstr(rc)));
goto done; goto done;
@@ -102,7 +102,7 @@ NTSTATUS ads_sid_to_name(ADS_STRUCT *ads,
"sAMAccountType", NULL}; "sAMAccountType", NULL};
ADS_STATUS rc; ADS_STATUS rc;
void *msg = NULL; void *msg = NULL;
char *exp = NULL; char *ldap_exp = NULL;
char *sidstr = NULL; char *sidstr = NULL;
uint32 atype; uint32 atype;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL; NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
@@ -113,13 +113,13 @@ NTSTATUS ads_sid_to_name(ADS_STRUCT *ads,
goto done; 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")); DEBUG(1,("ads_sid_to_name: asprintf failed!\n"));
status = NT_STATUS_NO_MEMORY; status = NT_STATUS_NO_MEMORY;
goto done; goto done;
} }
rc = ads_search_retry(ads, &msg, exp, attrs); rc = ads_search_retry(ads, &msg, ldap_exp, attrs);
if (!ADS_ERR_OK(rc)) { if (!ADS_ERR_OK(rc)) {
status = ads_ntstatus(rc); status = ads_ntstatus(rc);
DEBUG(1,("ads_sid_to_name ads_search: %s\n", ads_errstr(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: done:
if (msg) ads_msgfree(ads, msg); if (msg) ads_msgfree(ads, msg);
SAFE_FREE(exp); SAFE_FREE(ldap_exp);
SAFE_FREE(sidstr); SAFE_FREE(sidstr);
return status; 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 #endif

View File

@@ -31,10 +31,10 @@ ADS_STATUS ads_build_error(enum ads_error_type etype,
{ {
ADS_STATUS ret; ADS_STATUS ret;
if (etype == ADS_ERROR_NT) { if (etype == ENUM_ADS_ERROR_NT) {
DEBUG(0,("don't use ads_build_error with ADS_ERROR_NT!\n")); DEBUG(0,("don't use ads_build_error with ENUM_ADS_ERROR_NT!\n"));
ret.err.rc = -1; ret.err.rc = -1;
ret.error_type = ADS_ERROR_SYSTEM; ret.error_type = ENUM_ADS_ERROR_SYSTEM;
ret.minor_status = 0; ret.minor_status = 0;
return ret; return ret;
} }
@@ -50,10 +50,10 @@ ADS_STATUS ads_build_nt_error(enum ads_error_type etype,
{ {
ADS_STATUS ret; ADS_STATUS ret;
if (etype != ADS_ERROR_NT) { if (etype != ENUM_ADS_ERROR_NT) {
DEBUG(0,("don't use ads_build_nt_error without ADS_ERROR_NT!\n")); DEBUG(0,("don't use ads_build_nt_error without ENUM_ADS_ERROR_NT!\n"));
ret.err.rc = -1; ret.err.rc = -1;
ret.error_type = ADS_ERROR_SYSTEM; ret.error_type = ENUM_ADS_ERROR_SYSTEM;
ret.minor_status = 0; ret.minor_status = 0;
return ret; return ret;
} }
@@ -69,14 +69,23 @@ ADS_STATUS ads_build_nt_error(enum ads_error_type etype,
*/ */
NTSTATUS ads_ntstatus(ADS_STATUS status) 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; return status.err.nt_status;
} }
#ifdef HAVE_LDAP #ifdef HAVE_LDAP
if ((status.error_type == ADS_ERROR_LDAP) if ((status.error_type == ENUM_ADS_ERROR_LDAP)
&& (status.err.rc == LDAP_NO_MEMORY)) { && (status.err.rc == LDAP_NO_MEMORY)) {
return NT_STATUS_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 #endif
if (ADS_ERR_OK(status)) return NT_STATUS_OK; if (ADS_ERR_OK(status)) return NT_STATUS_OK;
return NT_STATUS_UNSUCCESSFUL; return NT_STATUS_UNSUCCESSFUL;
@@ -87,25 +96,25 @@ NTSTATUS ads_ntstatus(ADS_STATUS status)
*/ */
const char *ads_errstr(ADS_STATUS status) const char *ads_errstr(ADS_STATUS status)
{ {
int msg_ctx; uint32 msg_ctx;
static char *ret; static char *ret;
SAFE_FREE(ret); SAFE_FREE(ret);
msg_ctx = 0; msg_ctx = 0;
switch (status.error_type) { switch (status.error_type) {
case ADS_ERROR_SYSTEM: case ENUM_ADS_ERROR_SYSTEM:
return strerror(status.err.rc); return strerror(status.err.rc);
#ifdef HAVE_LDAP #ifdef HAVE_LDAP
case ADS_ERROR_LDAP: case ENUM_ADS_ERROR_LDAP:
return ldap_err2string(status.err.rc); return ldap_err2string(status.err.rc);
#endif #endif
#ifdef HAVE_KRB5 #ifdef HAVE_KRB5
case ADS_ERROR_KRB5: case ENUM_ADS_ERROR_KRB5:
return error_message(status.err.rc); return error_message(status.err.rc);
#endif #endif
#ifdef HAVE_GSSAPI #ifdef HAVE_GSSAPI
case ADS_ERROR_GSS: case ENUM_ADS_ERROR_GSS:
{ {
uint32 minor; uint32 minor;
@@ -122,8 +131,8 @@ const char *ads_errstr(ADS_STATUS status)
return ret; return ret;
} }
#endif #endif
case ADS_ERROR_NT: case ENUM_ADS_ERROR_NT:
return nt_errstr(ads_ntstatus(status)); return get_friendly_nt_error_msg(ads_ntstatus(status));
default: default:
return "Unknown ADS error type!? (not compiled in?)"; 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.workgroup = workgroup ? strdup(workgroup) : NULL;
ads->server.ldap_server = ldap_server? strdup(ldap_server) : 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 /* we need to know if this is a foreign realm */
use lp_ads_server() */ if (realm && *realm && !strequal(lp_realm(), realm)) {
if (realm && *realm && strcasecmp(lp_realm(), realm) != 0) {
ads->server.foreign = 1; ads->server.foreign = 1;
} }
if (workgroup && *workgroup && strcasecmp(lp_workgroup(), workgroup) != 0) { if (workgroup && *workgroup && !strequal(lp_workgroup(), workgroup)) {
ads->server.foreign = 1; ads->server.foreign = 1;
} }

View File

@@ -88,52 +88,6 @@ uint32 ads_uf2atype(uint32 uf)
return atype; 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 get the accountType from the groupType
*/ */
@@ -172,6 +126,8 @@ enum SID_NAME_USE ads_atype_map(uint32 atype)
switch (atype & 0xF0000000) { switch (atype & 0xF0000000) {
case ATYPE_GLOBAL_GROUP: case ATYPE_GLOBAL_GROUP:
return SID_NAME_DOM_GRP; return SID_NAME_DOM_GRP;
case ATYPE_SECURITY_LOCAL_GROUP:
return SID_NAME_ALIAS;
case ATYPE_ACCOUNT: case ATYPE_ACCOUNT:
return SID_NAME_USER; return SID_NAME_USER;
default: default:

View File

@@ -1,34 +1,139 @@
################################################# ########################################################
# active directory support # Compile with LDAP support?
with_ads_support=yes LDAP_LIBS=""
AC_MSG_CHECKING([whether to use Active Directory]) AC_SUBST(LDAP_LIBS)
with_ldap_support=auto
AC_MSG_CHECKING([for LDAP support])
AC_ARG_WITH(ads, AC_ARG_WITH(ldap,
[ --with-ads Active Directory support (default yes)], [ --with-ldap LDAP support (default yes)],
[ case "$withval" in [ case "$withval" in
no) yes|no)
with_ads_support=no with_ldap_support=$withval
;; ;;
esac ]) esac ])
if test x"$with_ads_support" = x"yes"; then AC_MSG_RESULT($with_ldap_support)
AC_DEFINE(WITH_ADS,1,[Whether to include Active Directory 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 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) AC_MSG_RESULT($with_ads_support)
FOUND_KRB5=no if test x"$with_ldap_support" != x"yes"; then
if test x"$with_ads_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 # check for krb5-config from recent MIT and Heimdal kerberos 5
AC_PATH_PROG(KRB5_CONFIG, krb5-config) AC_PATH_PROG(KRB5_CONFIG, krb5-config)
AC_MSG_CHECKING(for working krb5-config) AC_MSG_CHECKING(for working krb5-config)
if test -x "$KRB5_CONFIG"; then if test -x "$KRB5_CONFIG"; then
LIBS="$LIBS `$KRB5_CONFIG --libs`" ac_save_CFLAGS=$CFLAGS
CFLAGS="$CFLAGS `$KRB5_CONFIG --cflags`" CFLAGS="";export CFLAGS
CPPFLAGS="$CPPFLAGS `$KRB5_CONFIG --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 FOUND_KRB5=yes
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
else else
@@ -36,193 +141,303 @@ if test x"$with_ads_support" = x"yes"; then
fi fi
if test x$FOUND_KRB5 = x"no"; then if test x$FOUND_KRB5 = x"no"; then
################################################# #################################################
# check for location of Kerberos 5 install # check for location of Kerberos 5 install
AC_MSG_CHECKING(for kerberos 5 install path) AC_MSG_CHECKING(for kerberos 5 install path)
AC_ARG_WITH(krb5, AC_ARG_WITH(krb5,
[ --with-krb5=base-dir Locate Kerberos 5 support (default=/usr)], [ --with-krb5=base-dir Locate Kerberos 5 support (default=/usr)],
[ case "$withval" in [ case "$withval" in
no) no)
AC_MSG_RESULT(no) AC_MSG_RESULT(no krb5-path given)
;; ;;
*) yes)
AC_MSG_RESULT(yes) AC_MSG_RESULT(/usr)
LIBS="$LIBS -lkrb5" FOUND_KRB5=yes
CFLAGS="$CFLAGS -I$withval/include" ;;
CPPFLAGS="$CPPFLAGS -I$withval/include" *)
LDFLAGS="$LDFLAGS -L$withval/lib" AC_MSG_RESULT($withval)
FOUND_KRB5=yes KRB5_CFLAGS="-I$withval/include"
;; KRB5_CPPFLAGS="-I$withval/include"
esac ], KRB5_LDFLAGS="-L$withval/lib"
AC_MSG_RESULT(no) FOUND_KRB5=yes
) ;;
esac ],
AC_MSG_RESULT(no krb5-path given)
)
fi fi
if test x$FOUND_KRB5 = x"no"; then if test x$FOUND_KRB5 = x"no"; then
################################################# #################################################
# see if this box has the SuSE location for the heimdal kerberos implementation # see if this box has the SuSE location for the heimdal krb implementation
AC_MSG_CHECKING(for /usr/include/heimdal) AC_MSG_CHECKING(for /usr/include/heimdal)
if test -d /usr/include/heimdal; then if test -d /usr/include/heimdal; then
if test -f /usr/lib/heimdal/lib/libkrb5.a; then if test -f /usr/lib/heimdal/lib/libkrb5.a; then
LIBS="$LIBS -lkrb5" KRB5_CFLAGS="-I/usr/include/heimdal"
CFLAGS="$CFLAGS -I/usr/include/heimdal" KRB5_CPPFLAGS="-I/usr/include/heimdal"
CPPFLAGS="$CPPFLAGS -I/usr/include/heimdal" KRB5_LDFLAGS="-L/usr/lib/heimdal/lib"
LDFLAGS="$LDFLAGS -L/usr/lib/heimdal/lib" AC_MSG_RESULT(yes)
AC_MSG_RESULT(yes) else
KRB5_CFLAGS="-I/usr/include/heimdal"
KRB5_CPPFLAGS="-I/usr/include/heimdal"
AC_MSG_RESULT(yes)
fi
else else
LIBS="$LIBS -lkrb5" AC_MSG_RESULT(no)
CFLAGS="$CFLAGS -I/usr/include/heimdal"
CPPFLAGS="$CPPFLAGS -I/usr/include/heimdal"
AC_MSG_RESULT(yes)
fi fi
else fi
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
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 ac_save_CFLAGS=$CFLAGS
################################################# ac_save_CPPFLAGS=$CPPFLAGS
# see if this box has the RedHat location for kerberos ac_save_LDFLAGS=$LDFLAGS
AC_MSG_CHECKING(for /usr/kerberos)
if test -d /usr/kerberos -a -f /usr/kerberos/lib/libkrb5.a; then CFLAGS="$CFLAGS $KRB5_CFLAGS"
LIBS="$LIBS -lkrb5" CPPFLAGS="$CPPFLAGS $KRB5_CPPFLAGS"
LDFLAGS="$LDFLAGS -L/usr/kerberos/lib" LDFLAGS="$LDFLAGS $KRB5_LDFLAGS"
CFLAGS="$CFLAGS -I/usr/kerberos/include"
CPPFLAGS="$CPPFLAGS -I/usr/kerberos/include" KRB5_LIBS="$KRB5_LDFLAGS $KRB5_LIBS"
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT(no)
fi
fi
# now check for krb5.h. Some systems have the libraries without the headers! # 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 # note that this check is done here to allow for different kerberos
# include paths # include paths
AC_CHECK_HEADERS(krb5.h) 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 # now check for gssapi headers. This is also done here to allow for
# different kerberos include paths # different kerberos include paths
AC_CHECK_HEADERS(gssapi.h gssapi/gssapi_generic.h gssapi/gssapi.h com_err.h) 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 # 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_EXT(com_err, KRB5_LIBS, _et_list)
AC_CHECK_LIB(k5crypto, krb5_encrypt_data, [LIBS="$LIBS -lk5crypto"]) AC_CHECK_LIB_EXT(k5crypto, KRB5_LIBS, krb5_encrypt_data)
# Heimdal checks. # Heimdal checks.
AC_CHECK_LIB(crypto, des_set_key, [LIBS="$LIBS -lcrypto"]) AC_CHECK_LIB_EXT(crypto, KRB5_LIBS, des_set_key)
AC_CHECK_LIB(asn1, copy_Authenticator, [LIBS="$LIBS -lasn1 -lroken"]) 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. # Heimdal checks. On static Heimdal gssapi must be linked before krb5.
AC_CHECK_LIB(gssapi, gss_display_status, [LIBS="$LIBS -lgssapi -lkrb5 -lasn1"; AC_CHECK_LIB_EXT(gssapi, KRB5_LIBS, gss_display_status,[],[],
AC_DEFINE(HAVE_GSSAPI,1,[Whether GSSAPI is available])]) 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
######################################################## ########################################################
# now see if we can find the krb5 libs in standard paths # now see if we can find the krb5 libs in standard paths
# or as specified above # or as specified above
AC_CHECK_LIB(krb5, krb5_mk_req_extended, [LIBS="$LIBS -lkrb5"; AC_CHECK_LIB_EXT(krb5, KRB5_LIBS, krb5_mk_req_extended)
AC_DEFINE(HAVE_KRB5,1,[Whether KRB5 is available])])
######################################################## ########################################################
# now see if we can find the gssapi libs in standard paths # 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_CHECK_LIB_EXT(gssapi_krb5, KRB5_LIBS,gss_display_status,[],[],
AC_DEFINE(HAVE_GSSAPI,1,[Whether GSSAPI is available])]) 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)
######################################################## LIBS="$LIBS $KRB5_LIBS"
# Compile with LDAP support?
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 if test x"$samba_cv_HAVE_ADDRTYPE_IN_KRB5_ADDRESS" = x"yes"; then
AC_MSG_CHECKING([whether to use LDAP]) AC_DEFINE(HAVE_ADDRTYPE_IN_KRB5_ADDRESS,1,
[Whether the krb5_address struct has a addrtype property])
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])
fi 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 fi

View File

@@ -4,6 +4,8 @@
Copyright (C) Andrew Tridgell 2001 Copyright (C) Andrew Tridgell 2001
Copyright (C) Remus Koos 2001 Copyright (C) Remus Koos 2001
Copyright (C) Luke Howard 2003 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 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 it under the terms of the GNU General Public License as published by
@@ -24,38 +26,181 @@
#ifdef HAVE_KRB5 #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 verify an incoming ticket and parse out the principal name and
authorization_data if available 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, char **principal, DATA_BLOB *auth_data,
DATA_BLOB *ap_rep, 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_auth_context auth_context = NULL;
krb5_keytab keytab = NULL; krb5_keytab keytab = NULL;
krb5_data packet; krb5_data packet;
krb5_ticket *tkt = NULL; krb5_ticket *tkt = NULL;
krb5_rcache rcache = NULL;
int ret, i; int ret, i;
krb5_keyblock * key; krb5_keyblock *key = NULL;
krb5_principal host_princ; krb5_principal host_princ;
char *host_princ_s; char *host_princ_s = NULL;
BOOL free_host_princ = False;
fstring myname; fstring myname;
char *password_s; char *password_s = NULL;
krb5_data password; krb5_data password;
krb5_enctype *enctypes = NULL; krb5_enctype *enctypes = NULL;
#if 0
krb5_address local_addr;
krb5_address remote_addr;
#endif
BOOL auth_ok = False; BOOL auth_ok = False;
ZERO_STRUCT(packet);
ZERO_STRUCT(password);
ZERO_STRUCTP(auth_data);
ZERO_STRUCTP(ap_rep);
if (!secrets_init()) { if (!secrets_init()) {
DEBUG(1,("secrets_init failed\n")); DEBUG(1,("ads_verify_ticket: secrets_init failed\n"));
return NT_STATUS_LOGON_FAILURE; return NT_STATUS_LOGON_FAILURE;
} }
password_s = secrets_fetch_machine_password(); password_s = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
if (!password_s) { 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; 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); ret = krb5_init_context(&context);
if (ret) { 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; return NT_STATUS_LOGON_FAILURE;
} }
ret = krb5_set_default_realm(context, ads->auth.realm); ret = krb5_set_default_realm(context, realm);
if (ret) { if (ret) {
DEBUG(1,("krb5_set_default_realm failed (%s)\n", error_message(ret))); DEBUG(1,("ads_verify_ticket: krb5_set_default_realm failed (%s)\n", error_message(ret)));
return NT_STATUS_LOGON_FAILURE; 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 like. We have to go through all this to allow us to store
the secret internally, instead of using /etc/krb5.keytab */ the secret internally, instead of using /etc/krb5.keytab */
ret = krb5_auth_con_init(context, &auth_context); ret = krb5_auth_con_init(context, &auth_context);
if (ret) { if (ret) {
DEBUG(1,("krb5_auth_con_init failed (%s)\n", error_message(ret))); DEBUG(1,("ads_verify_ticket: krb5_auth_con_init failed (%s)\n", error_message(ret)));
return NT_STATUS_LOGON_FAILURE; sret = NT_STATUS_LOGON_FAILURE;
goto out;
} }
fstrcpy(myname, lp_netbios_name()); fstrcpy(myname, global_myname());
strlower(myname); strlower_m(myname);
asprintf(&host_princ_s, "HOST/%s@%s", myname, lp_realm()); asprintf(&host_princ_s, "HOST/%s@%s", myname, lp_realm());
ret = krb5_parse_name(context, host_princ_s, &host_princ); ret = krb5_parse_name(context, host_princ_s, &host_princ);
if (ret) { if (ret) {
DEBUG(1,("krb5_parse_name(%s) failed (%s)\n", host_princ_s, error_message(ret))); DEBUG(1,("ads_verify_ticket: krb5_parse_name(%s) failed (%s)\n",
return NT_STATUS_LOGON_FAILURE; host_princ_s, error_message(ret)));
sret = NT_STATUS_LOGON_FAILURE;
goto out;
} }
if (!(key = (krb5_keyblock *)malloc(sizeof(*key)))) { free_host_princ = True;
return NT_STATUS_NO_MEMORY;
/*
* 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))) { /* We need to setup a auth context with each possible encoding type in turn. */
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 */
for (i=0;enctypes[i];i++) { 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])) { if (create_kerberos_key_from_string(context, host_princ, &password, key, enctypes[i])) {
continue; continue;
} }
krb5_auth_con_setuseruserkey(context, auth_context, key); krb5_auth_con_setuseruserkey(context, auth_context, key);
krb5_free_keyblock(context, key);
packet.length = ticket->length; packet.length = ticket->length;
packet.data = (krb5_pointer)ticket->data; packet.data = (krb5_pointer)ticket->data;
if (!(ret = krb5_rd_req(context, &auth_context, &packet, if (!(ret = krb5_rd_req(context, &auth_context, &packet,
NULL, keytab, NULL, &tkt))) { #ifdef HAVE_MEMORY_KEYTAB
free_kerberos_etypes(context, enctypes); 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; auth_ok = True;
break; 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) { 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))); error_message(ret)));
return NT_STATUS_LOGON_FAILURE; sret = NT_STATUS_LOGON_FAILURE;
goto out;
} }
ret = krb5_mk_rep(context, auth_context, &packet); ret = krb5_mk_rep(context, auth_context, &packet);
if (ret) { 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))); error_message(ret)));
krb5_auth_con_free(context, auth_context); sret = NT_STATUS_LOGON_FAILURE;
return NT_STATUS_LOGON_FAILURE; goto out;
} }
*ap_rep = data_blob(packet.data, packet.length); *ap_rep = data_blob(packet.data, packet.length);
free(packet.data); free(packet.data);
krb5_get_smb_session_key(context, auth_context, session_key); get_krb5_smb_session_key(context, auth_context, session_key, True);
DEBUG(0,("SMB session key (from ticket) follows:\n")); dump_data_pw("SMB session key (from ticket)\n", session_key->data, session_key->length);
dump_data(0, session_key, 16);
#if 0 #if 0
file_save("/tmp/ticket.dat", ticket->data, ticket->length); 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); 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 0
if (tkt->enc_part2) { if (tkt->enc_part2) {
file_save("/tmp/authdata.dat", file_save("/tmp/authdata.dat",
tkt->enc_part2->authorization_data[0]->contents, tkt->enc_part2->authorization_data[0]->contents,
tkt->enc_part2->authorization_data[0]->length); tkt->enc_part2->authorization_data[0]->length);
}
#endif #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), if ((ret = krb5_unparse_name(context, get_principal_from_tkt(tkt),
principal))) { principal))) {
DEBUG(3,("krb5_unparse_name failed (%s)\n", DEBUG(3,("ads_verify_ticket: krb5_unparse_name failed (%s)\n",
error_message(ret))); error_message(ret)));
data_blob_free(auth_data); sret = NT_STATUS_LOGON_FAILURE;
data_blob_free(ap_rep); goto out;
krb5_auth_con_free(context, auth_context);
return NT_STATUS_LOGON_FAILURE;
} }
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 */ #endif /* HAVE_KRB5 */

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
/* /*
Unix SMB/CIFS implementation. Unix SMB/CIFS implementation.
ads (active directory) printer utility library 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 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 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) const char *printer, const char *servername)
{ {
ADS_STATUS status; ADS_STATUS status;
char *srv_dn, **srv_cn, *exp; char *srv_dn, **srv_cn, *s;
const char *attrs[] = {"*", "nTSecurityDescriptor", NULL}; const char *attrs[] = {"*", "nTSecurityDescriptor", NULL};
status = ads_find_machine_acct(ads, res, servername); 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); srv_cn = ldap_explode_dn(srv_dn, 1);
ads_msgfree(ads, *res); ads_msgfree(ads, *res);
asprintf(&exp, "(cn=%s-%s)", srv_cn[0], printer); asprintf(&s, "(cn=%s-%s)", srv_cn[0], printer);
status = ads_search(ads, res, exp, attrs); status = ads_search(ads, res, s, attrs);
ldap_memfree(srv_dn); ldap_memfree(srv_dn);
ldap_value_free(srv_cn); ldap_value_free(srv_cn);
free(exp); free(s);
return status; 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 modify a printer entry in the directory
*/ */
@@ -338,4 +352,3 @@ BOOL get_local_printer_publishing_data(TALLOC_CTX *mem_ctx,
} }
#endif #endif

View File

@@ -1,7 +1,7 @@
/* /*
Unix SMB/CIFS implementation. Unix SMB/CIFS implementation.
ads (active directory) utility library 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 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 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 ads_find_user_acct(ADS_STRUCT *ads, void **res, const char *user)
{ {
ADS_STATUS status; ADS_STATUS status;
char *exp; char *ldap_exp;
const char *attrs[] = {"*", NULL}; const char *attrs[] = {"*", NULL};
char *escaped_user = escape_ldap_string_alloc(user); char *escaped_user = escape_ldap_string_alloc(user);
if (!escaped_user) { if (!escaped_user) {
return ADS_ERROR(LDAP_NO_MEMORY); return ADS_ERROR(LDAP_NO_MEMORY);
} }
asprintf(&exp, "(samAccountName=%s)", escaped_user); asprintf(&ldap_exp, "(samAccountName=%s)", escaped_user);
status = ads_search(ads, res, exp, attrs); status = ads_search(ads, res, ldap_exp, attrs);
SAFE_FREE(exp); SAFE_FREE(ldap_exp);
SAFE_FREE(escaped_user); SAFE_FREE(escaped_user);
return status; return status;
} }

View File

@@ -28,13 +28,15 @@
this is supposed to catch dropped connections and auto-reconnect 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, 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) const char **attrs, void **res)
{ {
ADS_STATUS status; ADS_STATUS status;
int count = 3; int count = 3;
char *bp; char *bp;
*res = NULL;
if (!ads->ld && if (!ads->ld &&
time(NULL) - ads->last_attempt < ADS_RECONNECT_TIME) { time(NULL) - ads->last_attempt < ADS_RECONNECT_TIME) {
return ADS_ERROR(LDAP_SERVER_DOWN); 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); bp = strdup(bind_path);
if (!bp) if (!bp) {
return ADS_ERROR_NT(NT_STATUS_NO_MEMORY); return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
}
while (count--) { 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)) { if (ADS_ERR_OK(status)) {
DEBUG(5,("Search for %s gave %d replies\n", DEBUG(5,("Search for %s gave %d replies\n",
exp, ads_count_replies(ads, *res))); expr, ads_count_replies(ads, *res)));
free(bp); SAFE_FREE(bp);
return status; return status;
} }
if (*res) ads_msgfree(ads, *res); if (*res)
ads_msgfree(ads, *res);
*res = NULL; *res = NULL;
DEBUG(3,("Reopening ads connection to realm '%s' after error %s\n", DEBUG(3,("Reopening ads connection to realm '%s' after error %s\n",
ads->config.realm, ads_errstr(status))); ads->config.realm, ads_errstr(status)));
if (ads->ld) { if (ads->ld) {
ldap_unbind(ads->ld); ldap_unbind(ads->ld);
} }
ads->ld = NULL; ads->ld = NULL;
status = ads_connect(ads); status = ads_connect(ads);
if (!ADS_ERR_OK(status)) { if (!ADS_ERR_OK(status)) {
DEBUG(1,("ads_search_retry: failed to reconnect (%s)\n", DEBUG(1,("ads_search_retry: failed to reconnect (%s)\n",
ads_errstr(status))); ads_errstr(status)));
ads_destroy(&ads); ads_destroy(&ads);
free(bp); SAFE_FREE(bp);
return status; 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; return status;
} }
ADS_STATUS ads_search_retry(ADS_STRUCT *ads, void **res, ADS_STATUS ads_search_retry(ADS_STRUCT *ads, void **res,
const char *exp, const char *expr,
const char **attrs) const char **attrs)
{ {
return ads_do_search_retry(ads, ads->config.bind_path, LDAP_SCOPE_SUBTREE, 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, 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); msg1 = gen_negTokenTarg(mechs, blob);
data_blob_free(&blob); data_blob_free(&blob);
cred.bv_val = msg1.data; cred.bv_val = (char *)msg1.data;
cred.bv_len = msg1.length; cred.bv_len = msg1.length;
rc = ldap_sasl_bind_s(ads->ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred); 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, nthash, 24,
lp_workgroup(), lp_workgroup(),
ads->auth.user_name, ads->auth.user_name,
lp_netbios_name(), global_myname(),
sess_key, 16, sess_key, 16,
neg_flags); neg_flags);
@@ -106,7 +106,7 @@ static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads)
data_blob_free(&blob); data_blob_free(&blob);
/* now send the auth packet and we should be done */ /* 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; cred.bv_len = auth.length;
rc = ldap_sasl_bind_s(ads->ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred); 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; DATA_BLOB blob;
struct berval cred, *scred; struct berval cred, *scred;
DATA_BLOB session_key;
int rc; 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) { if (rc) {
return ADS_ERROR(LDAP_OPERATIONS_ERROR); return ADS_ERROR_KRB5(rc);
} }
/* now send the auth packet and we should be done */ /* 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; cred.bv_len = blob.length;
rc = ldap_sasl_bind_s(ads->ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred); rc = ldap_sasl_bind_s(ads->ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred);
data_blob_free(&blob); data_blob_free(&blob);
data_blob_free(&session_key);
return ADS_ERROR(rc); 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); blob = data_blob(scred->bv_val, scred->bv_len);
ber_bvfree(scred);
#if 0 #if 0
file_save("sasl_spnego.dat", blob.data, blob.length); file_save("sasl_spnego.dat", blob.data, blob.length);
#endif #endif
@@ -195,11 +199,18 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
status = ads_sasl_spnego_krb5_bind(ads, principal); status = ads_sasl_spnego_krb5_bind(ads, principal);
if (ADS_ERR_OK(status)) if (ADS_ERR_OK(status))
return 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); 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; return status;
}
} }
#endif #endif
@@ -223,13 +234,13 @@ failed:
*/ */
static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads) static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
{ {
int minor_status; uint32 minor_status;
gss_name_t serv_name; gss_name_t serv_name;
gss_buffer_desc input_name; gss_buffer_desc input_name;
gss_ctx_id_t context_handle; gss_ctx_id_t context_handle;
gss_OID mech_type = GSS_C_NULL_OID; gss_OID mech_type = GSS_C_NULL_OID;
gss_buffer_desc output_token, input_token; gss_buffer_desc output_token, input_token;
OM_uint32 ret_flags, conf_state; uint32 ret_flags, conf_state;
struct berval cred; struct berval cred;
struct berval *scred; struct berval *scred;
int i=0; 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_release_name(&minor_status, &serv_name);
gss_rc = gss_unwrap(&minor_status,context_handle,&input_token,&output_token, gss_rc = gss_unwrap(&minor_status,context_handle,&input_token,&output_token,
&conf_state,NULL); (int *)&conf_state,NULL);
if (gss_rc) { if (gss_rc) {
status = ADS_ERROR_GSS(gss_rc, minor_status); status = ADS_ERROR_GSS(gss_rc, minor_status);
goto failed; 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>>16;
*p++ = max_msg_size>>8; *p++ = max_msg_size>>8;
*p++ = max_msg_size; *p++ = max_msg_size;
snprintf(p, strlen(ads->config.bind_path)+4, "dn:%s", ads->config.bind_path); snprintf((char *)p, strlen(ads->config.bind_path)+4, "dn:%s", ads->config.bind_path);
p += strlen(p); p += strlen((const char *)p);
output_token.length = PTR_DIFF(p, output_token.value); output_token.length = PTR_DIFF(p, output_token.value);
gss_rc = gss_wrap(&minor_status, context_handle,0,GSS_C_QOP_DEFAULT, gss_rc = gss_wrap(&minor_status, context_handle,0,GSS_C_QOP_DEFAULT,
&output_token, &conf_state, &output_token, (int *)&conf_state,
&input_token); &input_token);
if (gss_rc) { if (gss_rc) {
status = ADS_ERROR_GSS(gss_rc, minor_status); 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) ADS_STATUS ads_change_trust_account_password(ADS_STRUCT *ads, char *host_principal)
{ {
char *tmp_password; char *tmp_password;
char *password; char *password;
char *new_password; char *new_password;
char *service_principal; char *service_principal = NULL;
ADS_STATUS ret; ADS_STATUS ret;
uint32 sec_channel_type;
if ((password = secrets_fetch_machine_password()) == NULL) { 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)); DEBUG(1,("Failed to retrieve password for principal %s\n", host_principal));
return ADS_ERROR_SYSTEM(ENOENT); return ADS_ERROR_SYSTEM(ENOENT);
} }
tmp_password = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH); tmp_password = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
new_password = strdup(tmp_password); new_password = strdup(tmp_password);
asprintf(&service_principal, "HOST/%s", host_principal);
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)) { ret = kerberos_set_password(ads->auth.kdc_server, service_principal, password, service_principal, new_password, ads->auth.time_offset);
DEBUG(1,("Failed to save machine password\n"));
return ADS_ERROR_SYSTEM(EACCES); 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: failed:
SAFE_FREE(service_principal); SAFE_FREE(service_principal);
SAFE_FREE(new_password); SAFE_FREE(new_password);
return ret; return ret;
} }

View File

@@ -97,7 +97,9 @@
return ret; return ret;
} }
krb5_use_enctype(context, &eblock, enctype); 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) #elif defined(HAVE_KRB5_GET_PW_SALT) && defined(HAVE_KRB5_STRING_TO_KEY_SALT)
int create_kerberos_key_from_string(krb5_context context, 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 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, static krb5_error_code ads_krb5_mk_req(krb5_context context,
krb5_auth_context *auth_context, krb5_auth_context *auth_context,
const krb5_flags ap_req_options, const krb5_flags ap_req_options,
const char *principal, const char *principal,
krb5_ccache ccache, krb5_ccache ccache,
krb5_data *outbuf) krb5_data *outbuf)
{ {
krb5_error_code retval; krb5_error_code retval;
krb5_principal server; krb5_principal server;
@@ -255,7 +257,7 @@ static krb5_error_code krb5_mk_req2(krb5_context context,
} }
/* obtain ticket & session key */ /* obtain ticket & session key */
memset((char *)&creds, 0, sizeof(creds)); ZERO_STRUCT(creds);
if ((retval = krb5_copy_principal(context, server, &creds.server))) { if ((retval = krb5_copy_principal(context, server, &creds.server))) {
DEBUG(1,("krb5_copy_principal failed (%s)\n", DEBUG(1,("krb5_copy_principal failed (%s)\n",
error_message(retval))); error_message(retval)));
@@ -305,14 +307,14 @@ cleanup_princ:
/* /*
get a kerberos5 ticket for the given service 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_error_code retval;
krb5_data packet; krb5_data packet;
krb5_ccache ccdef; krb5_ccache ccdef;
krb5_context context; krb5_context context;
krb5_auth_context auth_context = NULL; krb5_auth_context auth_context = NULL;
DATA_BLOB ret;
krb5_enctype enc_types[] = { krb5_enctype enc_types[] = {
#ifdef ENCTYPE_ARCFOUR_HMAC #ifdef ENCTYPE_ARCFOUR_HMAC
ENCTYPE_ARCFOUR_HMAC, ENCTYPE_ARCFOUR_HMAC,
@@ -344,56 +346,76 @@ DATA_BLOB krb5_get_ticket(const char *principal, time_t time_offset)
goto failed; goto failed;
} }
if ((retval = krb5_mk_req2(context, if ((retval = ads_krb5_mk_req(context,
&auth_context, &auth_context,
0, AP_OPTS_USE_SUBKEY,
principal, principal,
ccdef, &packet))) { ccdef, &packet))) {
goto failed; 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? */ /* Hmm, heimdal dooesn't have this - what's the correct call? */
/* krb5_free_data_contents(context, &packet); */ #ifdef HAVE_KRB5_FREE_DATA_CONTENTS
krb5_free_context(context); krb5_free_data_contents(context, &packet);
return ret; #endif
failed: failed:
if ( context ) if ( context )
krb5_free_context(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; krb5_keyblock *skey;
#endif krb5_error_code err;
BOOL ret = False; BOOL ret = False;
memset(session_key, 0, 16); memset(session_key, 0, 16);
#ifdef ENCTYPE_ARCFOUR_HMAC if (remote)
if (krb5_auth_con_getremotesubkey(context, auth_context, &skey) == 0 && skey != NULL) { err = krb5_auth_con_getremotesubkey(context, auth_context, &skey);
if (KRB5_KEY_TYPE(skey) == else
ENCTYPE_ARCFOUR_HMAC err = krb5_auth_con_getlocalsubkey(context, auth_context, &skey);
&& KRB5_KEY_LENGTH(skey) == 16) { if (err == 0 && skey != NULL) {
memcpy(session_key, KRB5_KEY_DATA(skey), KRB5_KEY_LENGTH(skey)); DEBUG(10, ("Got KRB5 session key of length %d\n", KRB5_KEY_LENGTH(skey)));
ret = True; *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); krb5_free_keyblock(context, skey);
} else {
DEBUG(10, ("KRB5 error getting session key %d\n", err));
} }
#endif /* ENCTYPE_ARCFOUR_HMAC */
return ret; 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 */ #else /* HAVE_KRB5 */
/* this saves a few linking headaches */ /* this saves a few linking headaches */
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)
{
DEBUG(0,("NO KERBEROS SUPPORT\n")); DEBUG(0,("NO KERBEROS SUPPORT\n"));
return data_blob(NULL, 0); return 1;
} }
#endif #endif

View File

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