summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/Makefile.in85
-rw-r--r--source3/client/client.c7
-rw-r--r--source3/client/smbmount.c43
-rw-r--r--source3/include/ads.h3
-rw-r--r--source3/libads/krb5_setpw.c428
-rw-r--r--source3/libads/ldap.c24
-rw-r--r--source3/libads/sasl.c7
-rw-r--r--source3/libads/util.c10
-rw-r--r--source3/libsmb/cliconnect.c22
-rw-r--r--source3/libsmb/clikrb5.c2
-rw-r--r--source3/torture/locktest.c5
-rw-r--r--source3/torture/torture.c4
-rw-r--r--source3/utils/net_ads.c16
13 files changed, 475 insertions, 181 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index b4559e2b4e..a14380ce6c 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -176,8 +176,10 @@ UBIQX_OBJ = ubiqx/ubi_BinTree.o ubiqx/ubi_Cache.o ubiqx/ubi_SplayTree.o \
PARAM_OBJ = param/loadparm.o param/params.o dynconfig.o
+KRBCLIENT_OBJ = libads/kerberos.o
+
LIBADS_OBJ = libads/ldap.o libads/ldap_printer.o libads/sasl.o \
- libads/krb5_setpw.o libads/kerberos.o libads/ldap_user.o \
+ libads/krb5_setpw.o libads/ldap_user.o \
libads/ads_struct.o libads/ads_status.o \
libads/disp_sec.o libads/ads_utils.o libads/ldap_utils.o \
libads/ads_ldap.o
@@ -186,22 +188,24 @@ LIBADS_SERVER_OBJ = libads/util.o libads/kerberos_verify.o
SECRETS_OBJ = passdb/secrets.o
+LIBNMB_OBJ = libsmb/unexpected.o libsmb/namecache.o libsmb/nmblib.o \
+ libsmb/namequery.o
+
LIBNTLMSSP_OBJ = libsmb/ntlmssp.o libsmb/ntlmssp_parse.o
-LIBSAMBA_OBJ = libsmb/nterr.o
+LIBSAMBA_OBJ = libsmb/nterr.o libsmb/smbdes.o libsmb/smbencrypt.o
LIBSMB_OBJ = libsmb/clientgen.o libsmb/cliconnect.o libsmb/clifile.o \
libsmb/clikrb5.o libsmb/clispnego.o libsmb/asn1.o \
libsmb/clirap.o libsmb/clierror.o libsmb/climessage.o \
libsmb/clireadwrite.o libsmb/clilist.o libsmb/cliprint.o \
libsmb/clitrans.o libsmb/clisecdesc.o libsmb/clidgram.o \
- libsmb/namequery.o libsmb/nmblib.o libsmb/clistr.o \
- libsmb/smbdes.o libsmb/smbencrypt.o \
+ libsmb/clistr.o \
libsmb/smberr.o libsmb/credentials.o libsmb/pwd_cache.o \
libsmb/clioplock.o libsmb/errormap.o libsmb/clirap2.o \
- libsmb/passchange.o libsmb/unexpected.o libsmb/doserr.o \
- libsmb/namecache.o libsmb/trustdom_cache.o \
- $(RPC_PARSE_OBJ1) $(LIBNTLMSSP_OBJ) $(LIBSAMBA_OBJ)
+ libsmb/passchange.o libsmb/doserr.o \
+ libsmb/trustdom_cache.o \
+ $(RPC_PARSE_OBJ1) $(LIBNTLMSSP_OBJ) $(LIBSAMBA_OBJ) $(LIBNMB_OBJ)
LIBMSRPC_OBJ = rpc_client/cli_lsarpc.o rpc_client/cli_samr.o \
rpc_client/cli_netlogon.o rpc_client/cli_srvsvc.o \
@@ -293,7 +297,7 @@ SAM_STATIC_MODULES = sam/sam_plugin.o sam/sam_skel.o sam/sam_ads.o
SAM_OBJ = sam/account.o sam/get_set_account.o sam/get_set_group.o \
sam/get_set_domain.o sam/interface.o $(SAM_STATIC_MODULES)
-SAMTEST_OBJ = torture/samtest.o torture/cmd_sam.o $(SAM_OBJ) $(LIB_OBJ) $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) $(READLINE_OBJ) lib/util_seaccess.o $(LIBADS_OBJ) $(PASSDB_OBJ) $(SECRETS_OBJ) $(GROUPDB_OBJ)
+SAMTEST_OBJ = torture/samtest.o torture/cmd_sam.o $(SAM_OBJ) $(LIB_OBJ) $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) $(READLINE_OBJ) lib/util_seaccess.o $(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(PASSDB_OBJ) $(SECRETS_OBJ) $(GROUPDB_OBJ)
GROUPDB_OBJ = groupdb/mapping.o
@@ -340,7 +344,7 @@ SMBD_OBJ_BASE = $(SMBD_OBJ_SRV) $(MSDFS_OBJ) $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_
$(LIB_OBJ) $(PRINTBACKEND_OBJ) $(QUOTAOBJS) $(OPLOCK_OBJ) \
$(NOTIFY_OBJ) $(GROUPDB_OBJ) $(AUTH_OBJ) \
$(LIBMSRPC_OBJ) $(LIBMSRPC_SERVER_OBJ) \
- $(LIBADS_OBJ) $(LIBADS_SERVER_OBJ) \
+ $(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(LIBADS_SERVER_OBJ) \
$(LIB_SMBD_OBJ) $(REGISTRY_OBJ) $(POPT_LIB_OBJ)
@@ -368,7 +372,7 @@ NMBD_OBJ1 = nmbd/asyncdns.o nmbd/nmbd.o nmbd/nmbd_become_dmb.o \
nmbd/nmbd_subnetdb.o nmbd/nmbd_winsproxy.o nmbd/nmbd_winsserver.o \
nmbd/nmbd_workgroupdb.o nmbd/nmbd_synclists.o
-NMBD_OBJ = $(NMBD_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) \
+NMBD_OBJ = $(NMBD_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(UBIQX_OBJ) \
$(PROFILE_OBJ) $(LIB_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ)
WREPL_OBJ1 = wrepld/server.o wrepld/process.o wrepld/parser.o wrepld/socket.o \
@@ -381,7 +385,7 @@ SWAT_OBJ1 = web/cgi.o web/diagnose.o web/startstop.o web/statuspage.o \
web/swat.o web/neg_lang.o
SWAT_OBJ = $(SWAT_OBJ1) $(PRINTING_OBJ) $(LIBSMB_OBJ) $(LOCKING_OBJ) \
- $(PARAM_OBJ) $(PASSDB_OBJ) $(SECRETS_OBJ) \
+ $(PARAM_OBJ) $(PASSDB_OBJ) $(SECRETS_OBJ) $(KRBCLIENT_OBJ) \
$(UBIQX_OBJ) $(LIB_OBJ) $(GROUPDB_OBJ) $(PLAINTEXT_AUTH_OBJ)
SMBSH_OBJ = smbwrapper/smbsh.o smbwrapper/shared.o \
@@ -395,7 +399,8 @@ SMBCONTROL_OBJ = utils/smbcontrol.o $(LOCKING_OBJ) $(PARAM_OBJ) \
printing/printing_db.o
SMBTREE_OBJ = utils/smbtree.o $(LOCKING_OBJ) $(PARAM_OBJ) \
- $(UBIQX_OBJ) $(PROFILE_OBJ) $(LIB_OBJ) $(LIBSMB_OBJ)
+ $(UBIQX_OBJ) $(PROFILE_OBJ) $(LIB_OBJ) $(LIBSMB_OBJ) \
+ $(KRBCLIENT_OBJ)
TESTPARM_OBJ = utils/testparm.o \
$(PARAM_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) $(POPT_LIB_OBJ)
@@ -405,14 +410,14 @@ TESTPRNS_OBJ = utils/testprns.o $(PARAM_OBJ) $(PRINTING_OBJ) $(UBIQX_OBJ) \
SMBPASSWD_OBJ = utils/smbpasswd.o $(PARAM_OBJ) $(SECRETS_OBJ) \
$(LIBSMB_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ)\
- $(UBIQX_OBJ) $(LIB_OBJ)
+ $(UBIQX_OBJ) $(LIB_OBJ) $(KRBCLIENT_OBJ)
-PDBEDIT_OBJ = utils/pdbedit.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(PASSDB_OBJ) \
+PDBEDIT_OBJ = utils/pdbedit.o $(PARAM_OBJ) $(PASSDB_OBJ) $(LIBSAMBA_OBJ) \
$(UBIQX_OBJ) $(LIB_OBJ) $(GROUPDB_OBJ) $(SECRETS_OBJ) \
$(POPT_LIB_OBJ)
SMBGROUPEDIT_OBJ = utils/smbgroupedit.o $(GROUPDB_OBJ) $(PARAM_OBJ) \
- $(LIBSMB_OBJ) $(PASSDB_OBJ) $(SECRETS_OBJ) $(UBIQX_OBJ) $(LIB_OBJ)
+ $(LIBSAMBA_OBJ) $(PASSDB_OBJ) $(SECRETS_OBJ) $(UBIQX_OBJ) $(LIB_OBJ)
RPCCLIENT_OBJ1 = rpcclient/rpcclient.o rpcclient/cmd_lsarpc.o \
rpcclient/cmd_samr.o rpcclient/cmd_spoolss.o \
@@ -423,7 +428,7 @@ RPCCLIENT_OBJ1 = rpcclient/rpcclient.o rpcclient/cmd_lsarpc.o \
RPCCLIENT_OBJ = $(RPCCLIENT_OBJ1) \
$(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \
$(RPC_PARSE_OBJ) $(PASSDB_OBJ) $(LIBMSRPC_OBJ) \
- $(READLINE_OBJ) $(GROUPDB_OBJ) \
+ $(READLINE_OBJ) $(GROUPDB_OBJ) $(KRBCLIENT_OBJ) \
$(LIBADS_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ)
PAM_WINBIND_OBJ = nsswitch/pam_winbind.po nsswitch/wb_common.po lib/snprintf.po
@@ -433,7 +438,7 @@ SMBW_OBJ1 = smbwrapper/smbw.o \
smbwrapper/realcalls.o smbwrapper/shared.o \
smbwrapper/smbw_cache.o
-SMBW_OBJ = $(SMBW_OBJ1) $(LIBSMB_OBJ) $(PARAM_OBJ) \
+SMBW_OBJ = $(SMBW_OBJ1) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(PARAM_OBJ) \
$(UBIQX_OBJ) $(LIB_OBJ)
SMBWRAPPER_OBJ1 = smbwrapper/wrapped.o
@@ -442,7 +447,7 @@ SMBWRAPPER_OBJ = $(SMBW_OBJ) $(SMBWRAPPER_OBJ1)
LIBSMBCLIENT_OBJ = libsmb/libsmbclient.o libsmb/libsmb_compat.o \
libsmb/libsmb_cache.o $(LIB_OBJ) \
- $(LIBSMB_OBJ) $(PARAM_OBJ) $(UBIQX_OBJ)
+ $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(PARAM_OBJ) $(UBIQX_OBJ)
# This shared library is intended for linking with unit test programs
# to test Samba internals. It's called libbigballofmud.so to
@@ -452,54 +457,56 @@ LIBBIGBALLOFMUD_MAJOR = 0
LIBBIGBALLOFMUD_OBJ = $(LIB_OBJ) $(UBIQX_OBJ) $(PARAM_OBJ) $(SECRETS_OBJ) \
$(LIBSMB_OBJ) $(LIBMSRPC_OBJ) $(RPC_PARSE_OBJ) $(PASSDB_OBJ) \
- $(GROUPDB_OBJ)
+ $(GROUPDB_OBJ) $(KRBCLIENT_OBJ)
LIBBIGBALLOFMUD_PICOBJS = $(LIBBIGBALLOFMUD_OBJ:.o=.po)
CLIENT_OBJ1 = client/client.o client/clitar.o
-CLIENT_OBJ = $(CLIENT_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \
- $(READLINE_OBJ) $(POPT_LIB_OBJ)
+CLIENT_OBJ = $(CLIENT_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) \
+ $(LIB_OBJ) $(KRBCLIENT_OBJ) \
+ $(READLINE_OBJ) $(POPT_LIB_OBJ)
NET_OBJ1 = utils/net.o utils/net_ads.o utils/net_ads_cldap.o utils/net_help.o \
utils/net_rap.o utils/net_rpc.o utils/net_rpc_samsync.o \
utils/net_rpc_join.o utils/net_time.o utils/net_lookup.o \
utils/net_cache.o
-NET_OBJ = $(NET_OBJ1) $(SECRETS_OBJ) $(LIBSMB_OBJ) \
+NET_OBJ = $(NET_OBJ1) $(SECRETS_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \
$(RPC_PARSE_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
$(PARAM_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \
$(LIBMSRPC_OBJ) $(LIBMSRPC_SERVER_OBJ) \
$(LIBADS_OBJ) $(LIBADS_SERVER_OBJ) $(POPT_LIB_OBJ)
-CUPS_OBJ = client/smbspool.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) $(LIB_OBJ)
+CUPS_OBJ = client/smbspool.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) \
+ $(LIB_OBJ) $(KRBCLIENT_OBJ)
MOUNT_OBJ = client/smbmount.o \
- $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) $(LIB_OBJ)
+ $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(UBIQX_OBJ) $(LIB_OBJ)
MNT_OBJ = client/smbmnt.o
UMOUNT_OBJ = client/smbumount.o
-NMBLOOKUP_OBJ = utils/nmblookup.o $(PARAM_OBJ) $(UBIQX_OBJ) \
- $(LIBSMB_OBJ) $(LIB_OBJ)
+NMBLOOKUP_OBJ = utils/nmblookup.o $(PARAM_OBJ) $(UBIQX_OBJ) $(LIBNMB_OBJ) \
+ $(LIB_OBJ)
SMBTORTURE_OBJ1 = torture/torture.o torture/nbio.o torture/scanner.o torture/utable.o \
torture/denytest.o torture/mangle_test.o
SMBTORTURE_OBJ = $(SMBTORTURE_OBJ1) \
- $(LIBSMB_OBJ) $(PARAM_OBJ) $(UBIQX_OBJ) $(LIB_OBJ)
+ $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(PARAM_OBJ) $(UBIQX_OBJ) $(LIB_OBJ)
-MASKTEST_OBJ = torture/masktest.o $(LIBSMB_OBJ) $(PARAM_OBJ) \
+MASKTEST_OBJ = torture/masktest.o $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(PARAM_OBJ) \
$(UBIQX_OBJ) $(LIB_OBJ)
-MSGTEST_OBJ = torture/msgtest.o $(LIBSMB_OBJ) $(PARAM_OBJ) \
+MSGTEST_OBJ = torture/msgtest.o $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(PARAM_OBJ) \
$(UBIQX_OBJ) $(LIB_OBJ)
-LOCKTEST_OBJ = torture/locktest.o $(LOCKING_OBJ) $(LIBSMB_OBJ) $(PARAM_OBJ) \
+LOCKTEST_OBJ = torture/locktest.o $(LOCKING_OBJ) $(KRBCLIENT_OBJ) $(LIBSMB_OBJ) $(PARAM_OBJ) \
$(UBIQX_OBJ) $(LIB_OBJ)
-NSSTEST_OBJ = torture/nsstest.o $(LIBSMB_OBJ) $(PARAM_OBJ) \
+NSSTEST_OBJ = torture/nsstest.o $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(PARAM_OBJ) \
$(UBIQX_OBJ) $(LIB_OBJ)
VFSTEST_OBJ = torture/cmd_vfs.o torture/vfstest.o $(SMBD_OBJ_BASE) $(READLINE_OBJ)
@@ -510,10 +517,12 @@ VFS_RECYCLE_OBJ = modules/vfs_recycle.o
VFS_NETATALK_OBJ = modules/vfs_netatalk.o
VFS_FAKE_PERMS_OBJ = modules/vfs_fake_perms.o
-LOCKTEST2_OBJ = torture/locktest2.o $(LOCKING_OBJ) $(LIBSMB_OBJ) $(PARAM_OBJ) \
+LOCKTEST2_OBJ = torture/locktest2.o $(LOCKING_OBJ) $(LIBSMB_OBJ) \
+ $(KRBCLIENT_OBJ) $(PARAM_OBJ) \
$(UBIQX_OBJ) $(LIB_OBJ)
-SMBCACLS_OBJ = utils/smbcacls.o $(LOCKING_OBJ) $(LIBSMB_OBJ) $(PARAM_OBJ) \
+SMBCACLS_OBJ = utils/smbcacls.o $(LOCKING_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \
+ $(PARAM_OBJ) \
$(UBIQX_OBJ) $(LIB_OBJ) $(RPC_PARSE_OBJ) $(PASSDB_GET_SET_OBJ) \
$(LIBMSRPC_OBJ) $(SECRETS_OBJ)
@@ -526,19 +535,19 @@ RPCTORTURE_OBJ = torture/rpctorture.o \
rpcclient/cmd_samr.o \
rpcclient/cmd_srvsvc.o \
rpcclient/cmd_netlogon.o \
- $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \
+ $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) $(KRBCLIENT_OBJ) \
$(RPC_CLIENT_OBJ) $(RPC_PARSE_OBJ) $(PASSDB_GET_SET_OBJ)
DEBUG2HTML_OBJ = utils/debug2html.o ubiqx/debugparse.o
SMBFILTER_OBJ = utils/smbfilter.o $(LIBSMB_OBJ) $(PARAM_OBJ) \
- $(UBIQX_OBJ) $(LIB_OBJ)
+ $(UBIQX_OBJ) $(LIB_OBJ) $(KRBCLIENT_OBJ)
PROTO_OBJ = $(SMBD_OBJ_MAIN) \
$(SMBD_OBJ_SRV) $(NMBD_OBJ1) $(SWAT_OBJ1) $(LIB_OBJ) $(LIBSMB_OBJ) \
$(SMBW_OBJ1) $(SMBWRAPPER_OBJ1) $(SMBTORTURE_OBJ1) $(RPCCLIENT_OBJ1) \
$(LIBMSRPC_OBJ) $(LIBMSRPC_SERVER_OBJ) $(RPC_CLIENT_OBJ) \
- $(RPC_PIPE_OBJ) $(RPC_PARSE_OBJ) \
+ $(RPC_PIPE_OBJ) $(RPC_PARSE_OBJ) $(KRBCLIENT_OBJ) \
$(AUTH_OBJ) $(PARAM_OBJ) $(LOCKING_OBJ) $(SECRETS_OBJ) \
$(PRINTING_OBJ) $(PRINTBACKEND_OBJ) $(OPLOCK_OBJ) $(NOTIFY_OBJ) \
$(QUOTAOBJS) $(PASSDB_OBJ) $(GROUPDB_OBJ) $(MSDFS_OBJ) \
@@ -582,10 +591,10 @@ WINBINDD_OBJ1 = \
WINBINDD_OBJ = \
$(WINBINDD_OBJ1) $(PASSDB_GET_SET_OBJ) \
- $(LIBNMB_OBJ) $(PARAM_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \
+ $(PARAM_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \
$(LIBSMB_OBJ) $(LIBMSRPC_OBJ) $(RPC_PARSE_OBJ) \
$(PROFILE_OBJ) $(UNIGRP_OBJ) \
- $(SECRETS_OBJ) $(LIBADS_OBJ)
+ $(SECRETS_OBJ) $(LIBADS_OBJ) $(KRBCLIENT_OBJ)
WBINFO_OBJ = nsswitch/wbinfo.o libsmb/smbencrypt.o libsmb/smbdes.o
diff --git a/source3/client/client.c b/source3/client/client.c
index 4761b0ae5c..e5a9592fcc 100644
--- a/source3/client/client.c
+++ b/source3/client/client.c
@@ -41,6 +41,7 @@ static pstring password;
static pstring username;
static pstring workgroup;
static char *cmdstr;
+static BOOL got_user;
static BOOL got_pass;
static int io_bufsize = 64512;
static BOOL use_kerberos;
@@ -2889,6 +2890,8 @@ static void remember_query_host(const char *arg,
case 'U':
{
char *lp;
+
+ got_user = True;
pstrcpy(username,optarg);
if ((lp=strchr_m(username,'%'))) {
*lp = 0;
@@ -2985,7 +2988,6 @@ static void remember_query_host(const char *arg,
case 'k':
#ifdef HAVE_KRB5
use_kerberos = True;
- got_pass = True;
#else
d_printf("No kerberos support compiled in\n");
exit(1);
@@ -2997,6 +2999,9 @@ static void remember_query_host(const char *arg,
}
}
+ if (use_kerberos && !got_user)
+ got_pass = True;
+
init_names();
if(*new_name_resolve_order)
diff --git a/source3/client/smbmount.c b/source3/client/smbmount.c
index 508521bedc..e2372d02b4 100644
--- a/source3/client/smbmount.c
+++ b/source3/client/smbmount.c
@@ -41,12 +41,16 @@ static pstring options;
static struct in_addr dest_ip;
static BOOL have_ip;
static int smb_port = 0;
+static BOOL got_user;
static BOOL got_pass;
static uid_t mount_uid;
static gid_t mount_gid;
static int mount_ro;
static unsigned mount_fmask;
static unsigned mount_dmask;
+static BOOL use_kerberos;
+/* TODO: Add code to detect smbfs version in kernel */
+static BOOL status32_smbfs = False;
static void usage(void);
@@ -155,11 +159,15 @@ static struct cli_state *do_connection(char *the_service)
}
/* SPNEGO doesn't work till we get NTSTATUS error support */
- c->use_spnego = False;
+ /* But it is REQUIRED for kerberos authentication */
+ if(!use_kerberos) c->use_spnego = False;
/* The kernel doesn't yet know how to sign it's packets */
c->sign_info.allow_smb_signing = False;
+ /* Use kerberos authentication if specified */
+ c->use_kerberos = use_kerberos;
+
if (!cli_session_request(c, &calling, &called)) {
char *p;
DEBUG(0,("%d: session request to %s failed (%s)\n",
@@ -193,9 +201,17 @@ static struct cli_state *do_connection(char *the_service)
/* This should be right for current smbfs. Future versions will support
large files as well as unicode and oplocks. */
- c->capabilities &= ~(CAP_UNICODE | CAP_LARGE_FILES | CAP_NT_SMBS |
- CAP_NT_FIND | CAP_STATUS32 | CAP_LEVEL_II_OPLOCKS);
- c->force_dos_errors = True;
+ if (status32_smbfs) {
+ c->capabilities &= ~(CAP_UNICODE | CAP_LARGE_FILES | CAP_NT_SMBS |
+ CAP_NT_FIND | CAP_LEVEL_II_OPLOCKS);
+ }
+ else {
+ c->capabilities &= ~(CAP_UNICODE | CAP_LARGE_FILES | CAP_NT_SMBS |
+ CAP_NT_FIND | CAP_STATUS32 |
+ CAP_LEVEL_II_OPLOCKS);
+ c->force_dos_errors = True;
+ }
+
if (!cli_session_setup(c, username,
password, strlen(password),
password, strlen(password),
@@ -629,8 +645,9 @@ static void read_credentials_file(char *filename)
pstrcpy(password, val);
got_pass = True;
}
- else if (strwicmp("username", param) == 0)
+ else if (strwicmp("username", param) == 0) {
pstrcpy(username, val);
+ }
memset(buf, 0, sizeof(buf));
}
@@ -652,6 +669,7 @@ static void usage(void)
username=<arg> SMB username\n\
password=<arg> SMB password\n\
credentials=<filename> file with username/password\n\
+ krb use kerberos (active directory)\n\
netbiosname=<arg> source NetBIOS name\n\
uid=<arg> mount uid or username\n\
gid=<arg> mount gid or groupname\n\
@@ -738,6 +756,7 @@ static void parse_mount_smb(int argc, char **argv)
if (!strcmp(opts, "username") ||
!strcmp(opts, "logon")) {
char *lp;
+ got_user = True;
pstrcpy(username,opteq+1);
if ((lp=strchr_m(username,'%'))) {
*lp = 0;
@@ -795,6 +814,16 @@ static void parse_mount_smb(int argc, char **argv)
} else if(!strcmp(opts, "guest")) {
*password = '\0';
got_pass = True;
+ } else if(!strcmp(opts, "krb")) {
+#ifdef HAVE_KRB5
+
+ use_kerberos = True;
+ if(!status32_smbfs)
+ fprintf(stderr, "Warning: kerberos support will only work for samba servers\n");
+#else
+ fprintf(stderr,"No kerberos support compiled in\n");
+ exit(1);
+#endif
} else if(!strcmp(opts, "rw")) {
mount_ro = 0;
} else if(!strcmp(opts, "ro")) {
@@ -879,6 +908,10 @@ static void parse_mount_smb(int argc, char **argv)
parse_mount_smb(argc, argv);
+ if (use_kerberos && !got_user) {
+ got_pass = True;
+ }
+
if (*credentials != 0) {
read_credentials_file(credentials);
}
diff --git a/source3/include/ads.h b/source3/include/ads.h
index 7f23e6506b..304a997b2c 100644
--- a/source3/include/ads.h
+++ b/source3/include/ads.h
@@ -205,3 +205,6 @@ typedef void **ADS_MODLIST;
#define ADS_AUTH_NO_BIND 0x02
#define ADS_AUTH_ANON_BIND 0x04
#define ADS_AUTH_SIMPLE_BIND 0x08
+
+/* Kerberos environment variable names */
+#define KRB5_ENV_CCNAME "KRB5CCNAME"
diff --git a/source3/libads/krb5_setpw.c b/source3/libads/krb5_setpw.c
index 087b0e9a71..c3ec754e39 100644
--- a/source3/libads/krb5_setpw.c
+++ b/source3/libads/krb5_setpw.c
@@ -24,13 +24,23 @@
#ifdef HAVE_KRB5
#define DEFAULT_KPASSWD_PORT 464
-#define KRB5_KPASSWD_VERS_CHANGEPW 1
-#define KRB5_KPASSWD_VERS_SETPW 0xff80
-#define KRB5_KPASSWD_ACCESSDENIED 5
-#define KRB5_KPASSWD_BAD_VERSION 6
-
-/* This implements the Kerb password change protocol as specifed in
- * kerb-chg-password-02.txt
+#define KRB5_KPASSWD_VERS_CHANGEPW 1
+#define KRB5_KPASSWD_VERS_SETPW 2
+#define KRB5_KPASSWD_VERS_SETPW_MS 0xff80
+#define KRB5_KPASSWD_ACCESSDENIED 5
+#define KRB5_KPASSWD_BAD_VERSION 6
+#define KRB5_KPASSWD_INITIAL_FLAG_NEEDED 7
+
+/* Those are defined by kerberos-set-passwd-02.txt and are probably
+ * not supported by M$ implementation */
+#define KRB5_KPASSWD_POLICY_REJECT 8
+#define KRB5_KPASSWD_BAD_PRINCIPAL 9
+#define KRB5_KPASSWD_ETYPE_NOSUPP 10
+
+/* This implements kerberos password change protocol as specified in
+ * kerb-chg-password-02.txt and kerberos-set-passwd-02.txt
+ * as well as microsoft version of the protocol
+ * as specified in kerberos-set-passwd-00.txt
*/
static DATA_BLOB encode_krb5_setpw(const char *principal, const char *password)
{
@@ -101,7 +111,8 @@ static DATA_BLOB encode_krb5_setpw(const char *principal, const char *password)
return ret;
}
-static krb5_error_code build_setpw_request(krb5_context context,
+static krb5_error_code build_kpasswd_request(uint16 pversion,
+ krb5_context context,
krb5_auth_context auth_context,
krb5_data *ap_req,
const char *princ,
@@ -123,7 +134,14 @@ static krb5_error_code build_setpw_request(krb5_context context,
return ret;
}
- setpw = encode_krb5_setpw(princ, passwd);
+ /* handle protocol differences in chpw and setpw */
+ if (pversion == KRB5_KPASSWD_VERS_CHANGEPW)
+ setpw = data_blob(passwd, strlen(passwd));
+ else if (pversion == KRB5_KPASSWD_VERS_SETPW ||
+ pversion == KRB5_KPASSWD_VERS_SETPW_MS)
+ setpw = encode_krb5_setpw(princ, passwd);
+ else
+ return EINVAL;
encoded_setpw.data = setpw.data;
encoded_setpw.length = setpw.length;
@@ -144,7 +162,7 @@ static krb5_error_code build_setpw_request(krb5_context context,
/* see the RFC for details */
p = ((char *)packet->data) + 2;
- RSSVAL(p, 0, 0xff80);
+ RSSVAL(p, 0, pversion);
p += 2;
RSSVAL(p, 0, ap_req->length);
p += 2;
@@ -160,6 +178,49 @@ static krb5_error_code build_setpw_request(krb5_context context,
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;
+ }
+
+ return(0);
+}
+
static krb5_error_code parse_setpw_reply(krb5_context context,
krb5_auth_context auth_context,
krb5_data *packet)
@@ -194,8 +255,11 @@ static krb5_error_code parse_setpw_reply(krb5_context context,
p += 2;
vnum = RSVAL(p, 0); p += 2;
-
- if (vnum != KRB5_KPASSWD_VERS_SETPW && vnum != KRB5_KPASSWD_VERS_CHANGEPW) {
+
+ /* FIXME: According to standard there is only one type of reply */
+ if (vnum != KRB5_KPASSWD_VERS_SETPW &&
+ vnum != KRB5_KPASSWD_VERS_SETPW_MS &&
+ vnum != KRB5_KPASSWD_VERS_CHANGEPW) {
DEBUG(1,("Bad vnum (%d) from kpasswd server\n", vnum));
return KRB5KDC_ERR_BAD_PVNO;
}
@@ -247,96 +311,56 @@ static krb5_error_code parse_setpw_reply(krb5_context context,
free(clearresult.data);
if ((res_code < KRB5_KPASSWD_SUCCESS) ||
- (res_code >= KRB5_KPASSWD_ACCESSDENIED)) {
+ (res_code > KRB5_KPASSWD_ETYPE_NOSUPP)) {
return KRB5KRB_AP_ERR_MODIFIED;
}
-
- return 0;
+
+ if(res_code == KRB5_KPASSWD_SUCCESS)
+ return 0;
+ else {
+ char *errstr;
+ krb5_setpw_result_code_string(context, res_code, &errstr);
+ DEBUG(1, ("Error changing password: %s\n", errstr));
+
+ switch(res_code) {
+ case KRB5_KPASSWD_ACCESSDENIED:
+ return KRB5KDC_ERR_BADOPTION;
+ break;
+ case KRB5_KPASSWD_INITIAL_FLAG_NEEDED:
+ return KV5M_ALT_METHOD;
+ break;
+ case KRB5_KPASSWD_ETYPE_NOSUPP:
+ return KRB5KDC_ERR_ETYPE_NOSUPP;
+ break;
+ case KRB5_KPASSWD_BAD_PRINCIPAL:
+ return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
+ break;
+ case KRB5_KPASSWD_POLICY_REJECT:
+ return KRB5KDC_ERR_POLICY;
+ break;
+ default:
+ return KRB5KRB_ERR_GENERIC;
+ break;
+ }
+ }
}
-ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char *newpw,
- int time_offset)
+static ADS_STATUS do_krb5_kpasswd_request(krb5_context context,
+ const char *kdc_host,
+ uint16 pversion,
+ krb5_creds *credsp,
+ const char *princ,
+ const char *newpw)
{
- krb5_context context;
krb5_auth_context auth_context = NULL;
- krb5_principal principal;
- char *princ_name;
- char *realm;
- krb5_creds creds, *credsp;
- krb5_ccache ccache;
krb5_data ap_req, chpw_req, chpw_rep;
int ret, sock, addr_len;
struct sockaddr remote_addr, local_addr;
krb5_address local_kaddr, remote_kaddr;
- ret = krb5_init_context(&context);
- if (ret) {
- DEBUG(1,("Failed to init krb5 context (%s)\n", error_message(ret)));
- return ADS_ERROR_KRB5(ret);
- }
-
- if (time_offset != 0) {
- krb5_set_real_time(context, time(NULL) + time_offset, 0);
- }
-
- ret = krb5_cc_default(context, &ccache);
- if (ret) {
- krb5_free_context(context);
- DEBUG(1,("Failed to get default creds (%s)\n", error_message(ret)));
- return ADS_ERROR_KRB5(ret);
- }
-
- ZERO_STRUCT(creds);
-
- realm = strchr(princ, '@');
- realm++;
-
- asprintf(&princ_name, "kadmin/changepw@%s", realm);
- ret = krb5_parse_name(context, princ_name, &creds.server);
- if (ret) {
- krb5_free_context(context);
- DEBUG(1,("Failed to parse kadmin/changepw (%s)\n", error_message(ret)));
- return ADS_ERROR_KRB5(ret);
- }
- free(princ_name);
-
- /* parse the principal we got as a function argument */
- ret = krb5_parse_name(context, princ, &principal);
- if (ret) {
- krb5_free_context(context);
- DEBUG(1,("Failed to parse %s (%s)\n", princ_name, error_message(ret)));
- return ADS_ERROR_KRB5(ret);
- }
-
- krb5_princ_set_realm(context, creds.server,
- krb5_princ_realm(context, principal));
-
- ret = krb5_cc_get_principal(context, ccache, &creds.client);
- if (ret) {
- krb5_free_principal(context, principal);
- krb5_free_context(context);
- DEBUG(1,("Failed to get principal from ccache (%s)\n",
- error_message(ret)));
- return ADS_ERROR_KRB5(ret);
- }
-
- ret = krb5_get_credentials(context, 0, ccache, &creds, &credsp);
- if (ret) {
- krb5_free_principal(context, creds.client);
- krb5_free_principal(context, principal);
- krb5_free_context(context);
- DEBUG(1,("krb5_get_credentials failed (%s)\n", error_message(ret)));
- return ADS_ERROR_KRB5(ret);
- }
-
- /* we might have to call krb5_free_creds(...) from now on ... */
ret = krb5_mk_req_extended(context, &auth_context, AP_OPTS_USE_SUBKEY,
NULL, credsp, &ap_req);
if (ret) {
- krb5_free_creds(context, credsp);
- krb5_free_principal(context, creds.client);
- krb5_free_principal(context, principal);
- krb5_free_context(context);
DEBUG(1,("krb5_mk_req_extended failed (%s)\n", error_message(ret)));
return ADS_ERROR_KRB5(ret);
}
@@ -345,10 +369,7 @@ ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char
if (sock == -1) {
int rc = errno;
free(ap_req.data);
- krb5_free_creds(context, credsp);
- krb5_free_principal(context, creds.client);
- krb5_free_principal(context, principal);
- krb5_free_context(context);
+ krb5_auth_con_free(context, auth_context);
DEBUG(1,("failed to open kpasswd socket to %s (%s)\n",
kdc_host, strerror(errno)));
return ADS_ERROR_SYSTEM(rc);
@@ -366,23 +387,17 @@ ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char
if (ret) {
close(sock);
free(ap_req.data);
- krb5_free_creds(context, credsp);
- krb5_free_principal(context, creds.client);
- krb5_free_principal(context, principal);
- krb5_free_context(context);
+ krb5_auth_con_free(context, auth_context);
DEBUG(1,("krb5_auth_con_setaddrs failed (%s)\n", error_message(ret)));
return ADS_ERROR_KRB5(ret);
}
- ret = build_setpw_request(context, auth_context, &ap_req,
+ ret = build_kpasswd_request(pversion, context, auth_context, &ap_req,
princ, newpw, &chpw_req);
if (ret) {
close(sock);
free(ap_req.data);
- krb5_free_creds(context, credsp);
- krb5_free_principal(context, creds.client);
- krb5_free_principal(context, principal);
- krb5_free_context(context);
+ krb5_auth_con_free(context, auth_context);
DEBUG(1,("build_setpw_request failed (%s)\n", error_message(ret)));
return ADS_ERROR_KRB5(ret);
}
@@ -391,10 +406,7 @@ ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char
close(sock);
free(chpw_req.data);
free(ap_req.data);
- krb5_free_creds(context, credsp);
- krb5_free_principal(context, creds.client);
- krb5_free_principal(context, principal);
- krb5_free_context(context);
+ krb5_auth_con_free(context, auth_context);
DEBUG(1,("send of chpw failed (%s)\n", strerror(errno)));
return ADS_ERROR_SYSTEM(errno);
}
@@ -406,10 +418,7 @@ ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char
if (!chpw_rep.data) {
close(sock);
free(ap_req.data);
- krb5_free_creds(context, credsp);
- krb5_free_principal(context, creds.client);
- krb5_free_principal(context, principal);
- krb5_free_context(context);
+ krb5_auth_con_free(context, auth_context);
DEBUG(1,("send of chpw failed (%s)\n", strerror(errno)));
errno = ENOMEM;
return ADS_ERROR_SYSTEM(errno);
@@ -420,10 +429,7 @@ ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char
close(sock);
free(chpw_rep.data);
free(ap_req.data);
- krb5_free_creds(context, credsp);
- krb5_free_principal(context, creds.client);
- krb5_free_principal(context, principal);
- krb5_free_context(context);
+ krb5_auth_con_free(context, auth_context);
DEBUG(1,("recv of chpw reply failed (%s)\n", strerror(errno)));
return ADS_ERROR_SYSTEM(errno);
}
@@ -435,10 +441,7 @@ ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char
if (ret) {
free(chpw_rep.data);
free(ap_req.data);
- krb5_free_creds(context, credsp);
- krb5_free_principal(context, creds.client);
- krb5_free_principal(context, principal);
- krb5_free_context(context);
+ krb5_auth_con_free(context, auth_context);
DEBUG(1,("krb5_auth_con_setaddrs on reply failed (%s)\n",
error_message(ret)));
return ADS_ERROR_KRB5(ret);
@@ -449,22 +452,194 @@ ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char
if (ret) {
free(ap_req.data);
- krb5_free_creds(context, credsp);
- krb5_free_principal(context, creds.client);
- krb5_free_principal(context, principal);
- krb5_free_context(context);
+ krb5_auth_con_free(context, auth_context);
DEBUG(1,("parse_setpw_reply failed (%s)\n",
error_message(ret)));
return ADS_ERROR_KRB5(ret);
}
free(ap_req.data);
+ krb5_auth_con_free(context, auth_context);
+
+ return ADS_SUCCESS;
+}
+
+ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char *newpw,
+ int time_offset)
+{
+
+ ADS_STATUS aret;
+ krb5_error_code ret;
+ krb5_context context;
+ krb5_principal principal;
+ char *princ_name;
+ char *realm;
+ krb5_creds creds, *credsp;
+ krb5_ccache ccache;
+
+ ret = krb5_init_context(&context);
+ if (ret) {
+ DEBUG(1,("Failed to init krb5 context (%s)\n", error_message(ret)));
+ return ADS_ERROR_KRB5(ret);
+ }
+
+ if (time_offset != 0) {
+ krb5_set_real_time(context, time(NULL) + time_offset, 0);
+ }
+
+ ret = krb5_cc_default(context, &ccache);
+ if (ret) {
+ krb5_free_context(context);
+ DEBUG(1,("Failed to get default creds (%s)\n", error_message(ret)));
+ return ADS_ERROR_KRB5(ret);
+ }
+
+ ZERO_STRUCT(creds);
+
+ realm = strchr(princ, '@');
+ realm++;
+
+ asprintf(&princ_name, "kadmin/changepw@%s", realm);
+ ret = krb5_parse_name(context, princ_name, &creds.server);
+ if (ret) {
+ krb5_free_context(context);
+ DEBUG(1,("Failed to parse kadmin/changepw (%s)\n", error_message(ret)));
+ return ADS_ERROR_KRB5(ret);
+ }
+ free(princ_name);
+
+ /* parse the principal we got as a function argument */
+ ret = krb5_parse_name(context, princ, &principal);
+ if (ret) {
+ krb5_free_context(context);
+ DEBUG(1,("Failed to parse %s (%s)\n", princ_name, error_message(ret)));
+ return ADS_ERROR_KRB5(ret);
+ }
+
+ krb5_princ_set_realm(context, creds.server,
+ krb5_princ_realm(context, principal));
+
+ ret = krb5_cc_get_principal(context, ccache, &creds.client);
+ if (ret) {
+ krb5_free_principal(context, principal);
+ krb5_free_context(context);
+ DEBUG(1,("Failed to get principal from ccache (%s)\n",
+ error_message(ret)));
+ return ADS_ERROR_KRB5(ret);
+ }
+
+ ret = krb5_get_credentials(context, 0, ccache, &creds, &credsp);
+ if (ret) {
+ krb5_free_principal(context, creds.client);
+ krb5_free_principal(context, principal);
+ krb5_free_context(context);
+ DEBUG(1,("krb5_get_credentials failed (%s)\n", error_message(ret)));
+ return ADS_ERROR_KRB5(ret);
+ }
+
+ /* we might have to call krb5_free_creds(...) from now on ... */
+
+ aret = do_krb5_kpasswd_request(context, kdc_host,
+ KRB5_KPASSWD_VERS_SETPW_MS,
+ credsp, princ, newpw);
+
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);
- return ADS_SUCCESS;
+ return aret;
+}
+
+/*
+ we use a prompter to avoid a crash bug in the kerberos libs when
+ dealing with empty passwords
+ this prompter is just a string copy ...
+*/
+static krb5_error_code
+kerb_prompter(krb5_context ctx, void *data,
+ const char *name,
+ const char *banner,
+ int num_prompts,
+ krb5_prompt prompts[])
+{
+ if (num_prompts == 0) return 0;
+
+ memset(prompts[0].reply->data, 0, prompts[0].reply->length);
+ if (prompts[0].reply->length > 0) {
+ if (data) {
+ strncpy(prompts[0].reply->data, data, prompts[0].reply->length-1);
+ prompts[0].reply->length = strlen(prompts[0].reply->data);
+ } else {
+ prompts[0].reply->length = 0;
+ }
+ }
+ return 0;
+}
+
+ADS_STATUS 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;
+ krb5_context context;
+ krb5_principal princ;
+ krb5_get_init_creds_opt opts;
+ krb5_creds creds;
+ char *chpw_princ = NULL, *password;
+
+ ret = krb5_init_context(&context);
+ if (ret) {
+ DEBUG(1,("Failed to init krb5 context (%s)\n", error_message(ret)));
+ return ADS_ERROR_KRB5(ret);
+ }
+
+ if ((ret = krb5_parse_name(context, principal,
+ &princ))) {
+ krb5_free_context(context);
+ DEBUG(1,("Failed to parse %s (%s)\n", principal, error_message(ret)));
+ return ADS_ERROR_KRB5(ret);
+ }
+
+ krb5_get_init_creds_opt_init(&opts);
+ krb5_get_init_creds_opt_set_tkt_life(&opts, 5*60);
+ krb5_get_init_creds_opt_set_renew_life(&opts, 0);
+ krb5_get_init_creds_opt_set_forwardable(&opts, 0);
+ krb5_get_init_creds_opt_set_proxiable(&opts, 0);
+
+ /* We have to obtain an INITIAL changepw ticket for changing password */
+ asprintf(&chpw_princ, "kadmin/changepw@%s",
+ (char *) krb5_princ_realm(context, princ));
+ password = strdup(oldpw);
+ ret = krb5_get_init_creds_password(context, &creds, princ, password,
+ kerb_prompter, NULL,
+ 0, chpw_princ, &opts);
+ SAFE_FREE(chpw_princ);
+ SAFE_FREE(password);
+
+ if (ret) {
+ if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY)
+ DEBUG(1,("Password incorrect while getting initial ticket"));
+ else
+ DEBUG(1,("krb5_get_init_creds_password failed (%s)\n", error_message(ret)));
+
+ krb5_free_principal(context, princ);
+ krb5_free_context(context);
+ return ADS_ERROR_KRB5(ret);
+ }
+
+ aret = do_krb5_kpasswd_request(context, kdc_host,
+ KRB5_KPASSWD_VERS_CHANGEPW,
+ &creds, principal, newpw);
+
+ krb5_free_principal(context, princ);
+ krb5_free_context(context);
+
+ return aret;
}
@@ -480,7 +655,12 @@ ADS_STATUS kerberos_set_password(const char *kpasswd_server,
return ADS_ERROR_KRB5(ret);
}
- return krb5_set_password(kpasswd_server, target_principal, new_password, time_offset);
+ if (!strcmp(auth_principal, target_principal))
+ return 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);
}
@@ -515,4 +695,6 @@ ADS_STATUS ads_set_machine_password(ADS_STRUCT *ads,
return status;
}
+
+
#endif
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index 47a94f0a08..c92e481078 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -1022,7 +1022,7 @@ char *ads_ou_string(const char *org_unit)
static ADS_STATUS ads_add_machine_acct(ADS_STRUCT *ads, const char *hostname,
const char *org_unit)
{
- ADS_STATUS ret;
+ ADS_STATUS ret, status;
char *host_spn, *host_upn, *new_dn, *samAccountName, *controlstr;
char *ou_str;
TALLOC_CTX *ctx;
@@ -1089,9 +1089,21 @@ static ADS_STATUS ads_add_machine_acct(ADS_STRUCT *ads, const char *hostname,
ads_mod_str(ctx, &mods, "operatingSystem", "Samba");
ads_mod_str(ctx, &mods, "operatingSystemVersion", VERSION);
- ads_gen_add(ads, new_dn, mods);
- ret = ads_set_machine_sd(ads, hostname, new_dn);
+ ret = ads_gen_add(ads, new_dn, mods);
+ if (!ADS_ERR_OK(ret))
+ goto done;
+
+ /* Do not fail if we can't set security descriptor
+ * it shouldn't be mandatory and probably we just
+ * don't have enough rights to do it.
+ */
+ status = ads_set_machine_sd(ads, hostname, new_dn);
+
+ if (!ADS_ERR_OK(status)) {
+ DEBUG(0, ("Warning: ads_set_machine_sd: %s\n",
+ ads_errstr(status)));
+ }
done:
talloc_destroy(ctx);
return ret;
@@ -1406,7 +1418,7 @@ ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname)
**/
ADS_STATUS ads_set_machine_sd(ADS_STRUCT *ads, const char *hostname, char *dn)
{
- const char *attrs[] = {"ntSecurityDescriptor", "objectSid", 0};
+ const char *attrs[] = {"nTSecurityDescriptor", "objectSid", 0};
char *exp = 0;
size_t sd_size = 0;
struct berval bval = {0, NULL};
@@ -1423,6 +1435,10 @@ ADS_STATUS ads_set_machine_sd(ADS_STRUCT *ads, const char *hostname, char *dn)
SEC_DESC *psd = 0;
TALLOC_CTX *ctx = 0;
+ /* Avoid segmentation fault in prs_mem_free if
+ * we have to bail out before prs_init */
+ ps_wire.is_dynamic = False;
+
if (!ads) return ADS_ERROR(LDAP_SERVER_DOWN);
ret = ADS_ERROR(LDAP_SUCCESS);
diff --git a/source3/libads/sasl.c b/source3/libads/sasl.c
index 7aa77bf2a2..29d4533a54 100644
--- a/source3/libads/sasl.c
+++ b/source3/libads/sasl.c
@@ -241,7 +241,12 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
ADS_STATUS status;
krb5_principal principal;
krb5_context ctx;
- krb5_enctype enc_types[] = {ENCTYPE_DES_CBC_MD5, ENCTYPE_NULL};
+ krb5_enctype enc_types[] = {
+#ifdef ENCTYPE_ARCFOUR_HMAC
+ ENCTYPE_ARCFOUR_HMAC,
+#endif
+ ENCTYPE_DES_CBC_MD5,
+ ENCTYPE_NULL};
gss_OID_desc nt_principal =
{10, "\052\206\110\206\367\022\001\002\002\002"};
diff --git a/source3/libads/util.c b/source3/libads/util.c
index 021f2d93e4..335cabc952 100644
--- a/source3/libads/util.c
+++ b/source3/libads/util.c
@@ -29,7 +29,7 @@ ADS_STATUS ads_change_trust_account_password(ADS_STRUCT *ads, char *host_princip
char *new_password;
char *service_principal;
ADS_STATUS ret;
-
+
if ((password = secrets_fetch_machine_password()) == NULL) {
DEBUG(1,("Failed to retrieve password for principal %s\n", host_principal));
return ADS_ERROR_SYSTEM(ENOENT);
@@ -38,15 +38,17 @@ ADS_STATUS ads_change_trust_account_password(ADS_STRUCT *ads, char *host_princip
tmp_password = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
new_password = strdup(tmp_password);
asprintf(&service_principal, "HOST/%s", host_principal);
-
- ret = kerberos_set_password(ads->auth.kdc_server, host_principal, password,
- service_principal, new_password, ads->auth.time_offset);
+
+ 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)) {
DEBUG(1,("Failed to save machine password\n"));
return ADS_ERROR_SYSTEM(EACCES);
}
+failed:
SAFE_FREE(service_principal);
SAFE_FREE(new_password);
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 9c7b168431..90a7eca8e7 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -446,6 +446,13 @@ static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
#ifdef HAVE_KRB5
/****************************************************************************
+ Use in-memory credentials cache
+****************************************************************************/
+static void use_in_memory_ccache() {
+ setenv(KRB5_ENV_CCNAME, "MEMORY:net_ads_testjoin", 1);
+}
+
+/****************************************************************************
Do a spnego/kerberos encrypted session setup.
****************************************************************************/
@@ -656,6 +663,21 @@ static BOOL cli_session_setup_spnego(struct cli_state *cli, const char *user,
fstrcpy(cli->user_name, user);
#ifdef HAVE_KRB5
+ /* If password is set we reauthenticate to kerberos server
+ * and do not store results */
+
+ if (*pass) {
+ int ret;
+
+ use_in_memory_ccache();
+ ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */);
+
+ if (ret){
+ DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
+ return False;
+ }
+ }
+
if (got_kerberos_mechanism && cli->use_kerberos) {
return cli_session_setup_kerberos(cli, principal, workgroup);
}
diff --git a/source3/libsmb/clikrb5.c b/source3/libsmb/clikrb5.c
index 203d9d874b..e380d80bcc 100644
--- a/source3/libsmb/clikrb5.c
+++ b/source3/libsmb/clikrb5.c
@@ -278,6 +278,7 @@ DATA_BLOB krb5_get_ticket(const char *principal, time_t time_offset)
ENCTYPE_ARCFOUR_HMAC,
#endif
ENCTYPE_DES_CBC_MD5,
+ ENCTYPE_DES_CBC_CRC,
ENCTYPE_NULL};
retval = krb5_init_context(&context);
@@ -324,7 +325,6 @@ failed:
return data_blob(NULL, 0);
}
-
#else /* HAVE_KRB5 */
/* this saves a few linking headaches */
DATA_BLOB krb5_get_ticket(const char *principal, time_t time_offset)
diff --git a/source3/torture/locktest.c b/source3/torture/locktest.c
index 5f9a63802b..63b9590dd6 100644
--- a/source3/torture/locktest.c
+++ b/source3/torture/locktest.c
@@ -24,6 +24,7 @@
static fstring password[2];
static fstring username[2];
+static int got_user;
static int got_pass;
static BOOL use_kerberos;
static int numops = 1000;
@@ -602,13 +603,13 @@ static void usage(void)
case 'k':
#ifdef HAVE_KRB5
use_kerberos = True;
- got_pass = True;
#else
d_printf("No kerberos support compiled in\n");
exit(1);
#endif
break;
case 'U':
+ got_user = 1;
if (got_pass == 2) {
d_printf("Max of 2 usernames\n");
exit(1);
@@ -663,6 +664,8 @@ static void usage(void)
}
}
+ if(use_kerberos && !got_user) got_pass = True;
+
argc -= optind;
argv += optind;
diff --git a/source3/torture/torture.c b/source3/torture/torture.c
index 56b8da768e..97e864de96 100644
--- a/source3/torture/torture.c
+++ b/source3/torture/torture.c
@@ -4082,6 +4082,7 @@ static void usage(void)
{
int opt, i;
char *p;
+ int gotuser = 0;
int gotpass = 0;
extern char *optarg;
extern int optind;
@@ -4167,13 +4168,13 @@ static void usage(void)
case 'k':
#ifdef HAVE_KRB5
use_kerberos = True;
- gotpass = True;
#else
d_printf("No kerberos support compiled in\n");
exit(1);
#endif
break;
case 'U':
+ gotuser = 1;
fstrcpy(username,optarg);
p = strchr_m(username,'%');
if (p) {
@@ -4188,6 +4189,7 @@ static void usage(void)
}
}
+ if(use_kerberos && !gotuser) gotpass = True;
while (!gotpass) {
p = getpass("Password:");
diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c
index 867252c95f..d508320423 100644
--- a/source3/utils/net_ads.c
+++ b/source3/utils/net_ads.c
@@ -110,6 +110,11 @@ static int net_ads_info(int argc, const char **argv)
return 0;
}
+static void use_in_memory_ccache() {
+ /* Use in-memory credentials cache so we do not interfere with
+ * existing credentials */
+ setenv(KRB5_ENV_CCNAME, "MEMORY:net_ads", 1);
+}
static ADS_STRUCT *ads_startup(void)
{
@@ -124,8 +129,10 @@ static ADS_STRUCT *ads_startup(void)
opt_user_name = "administrator";
}
- if (opt_user_specified)
+ if (opt_user_specified) {
need_password = True;
+ use_in_memory_ccache();
+ }
retry:
if (!opt_password && need_password) {
@@ -601,6 +608,8 @@ static int net_ads_join_ok(void)
*/
int net_ads_testjoin(int argc, const char **argv)
{
+ use_in_memory_ccache();
+
/* Display success or failure */
if (net_ads_join_ok() != 0) {
fprintf(stderr,"Join to domain is not valid\n");
@@ -878,7 +887,8 @@ static int net_ads_password(int argc, const char **argv)
(strchr(argv[0], '@') == NULL)) {
return net_ads_usage(argc, argv);
}
-
+
+ use_in_memory_ccache();
c = strchr(auth_principal, '@');
realm = ++c;
@@ -925,6 +935,8 @@ static int net_ads_change_localhost_pass(int argc, const char **argv)
opt_password = secrets_fetch_machine_password();
+ use_in_memory_ccache();
+
if (!(ads = ads_startup())) {
return -1;
}