diff options
-rw-r--r-- | source3/Makefile.in | 85 | ||||
-rw-r--r-- | source3/client/client.c | 7 | ||||
-rw-r--r-- | source3/client/smbmount.c | 43 | ||||
-rw-r--r-- | source3/include/ads.h | 3 | ||||
-rw-r--r-- | source3/libads/krb5_setpw.c | 428 | ||||
-rw-r--r-- | source3/libads/ldap.c | 24 | ||||
-rw-r--r-- | source3/libads/sasl.c | 7 | ||||
-rw-r--r-- | source3/libads/util.c | 10 | ||||
-rw-r--r-- | source3/libsmb/cliconnect.c | 22 | ||||
-rw-r--r-- | source3/libsmb/clikrb5.c | 2 | ||||
-rw-r--r-- | source3/torture/locktest.c | 5 | ||||
-rw-r--r-- | source3/torture/torture.c | 4 | ||||
-rw-r--r-- | source3/utils/net_ads.c | 16 |
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; } |