diff options
author | vorlon <vorlon@alioth.debian.org> | 2008-03-09 10:22:43 +0000 |
---|---|---|
committer | vorlon <vorlon@alioth.debian.org> | 2008-03-09 10:22:43 +0000 |
commit | 8f965abadc5783dc5df0a86f98b4fbfd5b001b52 (patch) | |
tree | ee76489b4823398625707e63a6bf51a68cd29e0f | |
parent | 868390f57c071cf3548bae532bf06b78688c3930 (diff) | |
download | samba-8f965abadc5783dc5df0a86f98b4fbfd5b001b52.tar.gz |
Load samba-3.0.28a into branches/samba/upstream.upstream/3.0.28a
git-svn-id: svn://svn.debian.org/svn/pkg-samba/branches/samba/upstream@1755 fc4039ab-9d04-0410-8cac-899223bdd6b0
106 files changed, 2534 insertions, 818 deletions
diff --git a/.gitignore b/.gitignore index d5e5177e22..4d39d12177 100644 --- a/.gitignore +++ b/.gitignore @@ -28,4 +28,4 @@ source/config.cache source/library-versions source/nsswitch/*.so source/proto_exists -source/winbindd/winbindd_proto.h +source/nsswitch/winbindd_proto.h diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 9e023d1c04..71d3c3a09f 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -1,3 +1,205 @@ + =============================== + Release Notes for Samba 3.0.28a + Mar 8, 2008 + =============================== + +This is the second production release of the Samba 3.0.28 code +base and is the version that servers should be run for for all +current bug fixes. + +Major bug fixes included in Samba 3.0.28a are: + + o Failure to join Windows 2008 domains + o Windows Vista (including SP1 RC) interop issues + + + +###################################################################### +Changes +####### + +smb.conf changes +---------------- + + Parameter Name Description Default + -------------- ----------- ------- + administrative share New No + ldap debug level New 0 + ldap debug threshold New 10 + + +Changes since 3.0.28 +-------------------- + +o Michael Adam <obnox@samba.org> + * Fix bug in version string's vendor tag. + * Prevent net getdomainsid from crashing when called as non-root. + * BUG 4801: Correctly implement LSA lookup levels for LookupNames. + * Fixes for internal LookupNames() calls for unqualified users and + groups. + * Remove unnecessary functions when managing domain trust + passwords. + * Fix winbindd on a Samba DC talking to a trusted domain DC + (again). + * Consolidate the detection of the machine_account_name when + obtaining trust credentials from the local database. + * Refactor trust account database routines and session key + management. + * Fix retrieval of trusted domain password policies when + authenticating a user (only when WBFLAG_PAM_GET_PWD is config + flags is set). + * Refactor Winbind's cm_connect_sam(). + * Enable building the notify_fam module. + * Add "ldap debug level" and "ldap debug threshold" smb.conf options. + + +o Jeremy Allison <jra@samba.org> + * Fix cut-n-paste bug when filling in form values for Printer + info. + * Fix SMB signing bug found by Volker. + * Create locking.tdb when running smbstatus before smbd to avoid + confusing error messages. + * Add a portable version of strlcpy and strlcat. + * BUG 4780: Cause user mounts to inherit uid= and gid= from the + calling user when called as non-root, except when overridden on + the command line. Original patch by Steve Langasek. + * BUG 5802: Recent versions of Linux-PAM support localization of + user prompts, so Samba must use the C locale when invoking PAM + * Merge Vista principal detection changes by Andreas Schneider + from 3.2 branch. + * BUG 5121: Fix problems running unix passwd sync on streams based + systems. + * BUG 4612: Fix smbd crash when connecting from an OS/2 client. + * Back port Volker's ACL fixes on newly create files form 3.2. + * Ensure that send_getdc_request() matches the 3.2 code base. + * BUG 3617: Fix crash in nmbd caused by referencing freed memory. + * Fixes for issues reported by IBM checker. + * Fixes for issues reported by Coverity. + * Back port Volker's fix for nlink count. + * Back port SAMR flag fixes from Matt Geddes + <musicalcarrion@gmail.com>. + * BUG 4929: Cope with protected ACL set correctly (based on work + from Jim McDonough). + * Fix ACL set bug when group being set is the primary group. + * Ensure NDR wire-reads of string types are always null + terminated. + * BUG 5247: Fix mget wildcard expansion in smbclient. + * Fix bug in SPNEGO negotiation. + * BUG 3617: Fix "Invalid read of size 4" errors. + * BUG 5267: Prevent nmbd from shutting down when no network + interfaces can be located. + + +o Kai Blin <kai@samba.org> + * libsmb: Do not upper-case target name on NTLMv2 hash generation. + * Fix an incompatible pointer type warning. + + +o Gerald Carter <jerry@samba.org> + * Restrict the enctypes in the generated krb5.conf files to + Win2003 types. + + +o Steven Danneman <steven.danneman@isilon.com> + * Error path memory leak fixes. + + +o Guenther Deschner <gd@samba.org> + * Fix PAC decoding from Vista SP1 client. + * Fix get_trust_creds() to return always an upper-cased krb5 + principal. + * Back port additional fixes necessary for support Windows 2008 + domain joins from the 3.2 branch. + + +o Mathias Gug <mathiaz@ubuntu.com> + * BUG 5802: Recent versions of Linux-PAM support localization of + user prompts, so Samba must use the C locale when invoking PAM + + +o Steve Langasek <vorlon@debian.org> + * BUG 3727: Fix smbpasswd abort when called by non-root user. + * BUG 4784: Prevent umount.cifs from allowing all users to unmount shares. + * BUG 5802: Recent versions of Linux-PAM support localization of + user prompts, so Samba must use the C locale when invoking PAM + + +o Volker Lendecke <vl@samba.org> + * When allocating a new vuid, also avoid partial ones. Also + fully invalidate intermediate ones. + * Fix error path exit in create_local_nt_token() to correctly roll + back security contexts. + * Fix valgrind warnings in nmbd. + * Pointer initialization fixes in notify_marshall_changes(). + * BUG 5208: Fix uninitialized variables in vfs_hpuxacl.c (reported + by David Leonard <David.Leonard@quest.com>). + * Copy the 3.2 version of string_replace to 3.0. + * Port SMB_FS_OBJECTID_INFORMATION from 3.2 (Patch by Corinna + Vinschen). + * Memory leak fixes. + * Fix error code propagation from cli_session_setup_kerberos(). + * BUG 5217: Fix inotify detection. + * BUG 5279: Correctly check return of rename(). + * BUG 5252: Fix confusing error messages in mount.cifs. + * BUG 5307: Respect FAMChanged (Thanks to Ricardo Santos). + * Work around a handle leak in XP 64 bit. + + +o Guenter Kukkukk <linux@kukkukk.com> + * OS/2 returns eclass == ERRDOS && ecode == ERRnofiles for a zero + entry directory listing. + + +o Tom Maher <tmaher@watson.org> + * BUG 5175: Support krb5 auth in smbcacls. + + +o Hans Mayer <hans.mayer@ages.at> + * BUG 5141: Solaris 9 compile fix. + + +o Stefan Metzmacher <metze@samba.org> + * Fix default printing system detection in libreplace. + + +o Laurent Pinchart <pinchart@skynet.be> + * BUG 5163: Return better error codes when a password cannot be + set in and LDAP directory. + + +o Jiri Sasek <Jiri.Sasek@Sun.COM> + * BUG 4866: Correct password routine detection on Solaris. + + +o Andreas Schneider <anschneider@suse.de> + * Remove trailing slashes on server names when parsing input from + smbclient. + * Support Windows 2008 domain joins (variant of Todd Stecher's + original patch). + * Add "administrative share" service parameter for defining hidden + administrative shares that cannot be managed from Windows. + + +o Karolin Seeger <kseeger@samba.org> + * Use the "ldap user suffix" when enumerating a users group + memberships. + + +o Simo Sorce <idra@samba.org> + * Don't assume NULL termination when copying the principal name + in kerberos_get_default_realm_from_ccache(). + * Fix winbindd running on a Samba DC (again). + + +o Bo Yang <boyang@novell.com> + * Fix bad private_data pointer in winbindd_lookupname_async(). + + + +Release notes for older releases follow: + + -------------------------------------------------- + ============================== Release Notes for Samba 3.0.28 Dec 10, 2007 @@ -29,8 +231,6 @@ o Volker Lendecke <vl@samba.org> when failing to add local groups in create_local_nt_token(). -Release notes for older releases follow: - -------------------------------------------------- =============================== diff --git a/examples/logon/genlogon/genlogon.pl b/examples/logon/genlogon/genlogon.pl index 8ebf392141..4799ac8452 100644 --- a/examples/logon/genlogon/genlogon.pl +++ b/examples/logon/genlogon/genlogon.pl @@ -45,7 +45,7 @@ if ($ARGV[1] eq "SUPPORT" || $ARGV[0] eq "support") } # Connect shares just used by Administration staff -If ($ARGV[1] eq "ADMIN" || $ARGV[0] eq "admin") +if ($ARGV[1] eq "ADMIN" || $ARGV[0] eq "admin") { print LOGON "NET USE L: \\\\$ARGV[2]\\ADMIN\r\n"; print LOGON "NET USE K: \\\\$ARGV[2]\\MKTING\r\n"; diff --git a/packaging/Example/setup.sh b/packaging/Example/setup.sh index 994b16d5ef..7fd8fc4110 100755 --- a/packaging/Example/setup.sh +++ b/packaging/Example/setup.sh @@ -24,4 +24,4 @@ echo "Done. Now settting up samba command" ln /sbin/init.d/samba.init /sbin/samba echo "Done." echo "To start / stop samba:" -echo " execute: samba [start | stop] +echo " execute: samba [start | stop]" diff --git a/packaging/RHEL/makerpms.sh b/packaging/RHEL/makerpms.sh index cbf5421422..2cb05a9288 100644 --- a/packaging/RHEL/makerpms.sh +++ b/packaging/RHEL/makerpms.sh @@ -20,7 +20,7 @@ SRCDIR=`rpm --eval %_sourcedir` USERID=`id -u` GRPID=`id -g` -VERSION='3.0.28' +VERSION='3.0.28a' REVISION='' SPECFILE="samba.spec" RPMVER=`rpm --version | awk '{print $3}'` diff --git a/packaging/RHEL/samba.spec b/packaging/RHEL/samba.spec index cfe55bda8f..85e3e7585e 100644 --- a/packaging/RHEL/samba.spec +++ b/packaging/RHEL/samba.spec @@ -5,7 +5,7 @@ Summary: Samba SMB client and server Vendor: Samba Team Packager: Samba Team <samba@samba.org> Name: samba -Version: 3.0.28 +Version: 3.0.28a Release: 1 Epoch: 0 License: GNU GPL version 2 diff --git a/source/Makefile.in b/source/Makefile.in index ee6d6ed559..f37a94e35a 100644 --- a/source/Makefile.in +++ b/source/Makefile.in @@ -270,7 +270,7 @@ READLINE_OBJ = lib/readline.o # Be sure to include them into your application POPT_LIB_OBJ = lib/popt_common.o -PARAM_OBJ = dynconfig.o param/loadparm.o param/params.o lib/sharesec.o +PARAM_OBJ = dynconfig.o param/loadparm.o param/params.o lib/sharesec.o lib/ldap_debug_handler.o KRBCLIENT_OBJ = libads/kerberos.o libads/ads_status.o @@ -286,9 +286,9 @@ LIBADS_OBJ = libads/ldap.o libads/ldap_printer.o libads/sasl.o \ libads/krb5_setpw.o libads/ldap_user.o \ libads/ads_struct.o libads/kerberos_keytab.o \ libads/disp_sec.o libads/ads_utils.o libads/ldap_utils.o \ - libads/authdata.o libads/cldap.o + libads/authdata.o libads/cldap.o libads/util.o -LIBADS_SERVER_OBJ = libads/util.o libads/kerberos_verify.o \ +LIBADS_SERVER_OBJ = libads/kerberos_verify.o \ libads/ldap_schema.o SECRETS_OBJ = passdb/secrets.o passdb/machine_sid.o @@ -1681,6 +1681,7 @@ python_install: $(PYTHON_OBJ) python_clean: @-if test -n "$(PYTHON)"; then $(PYTHON) python/setup.py clean; fi + @-rm -rf build/ # revert to the previously installed version revert: @@ -1869,6 +1870,7 @@ realclean: clean delheaders distclean: realclean -rm -f include/stamp-h + -rm -f smbadduser -rm -f include/config.h Makefile -rm -f config.status config.cache so_locations -rm -rf .deps TAGS diff --git a/source/VERSION b/source/VERSION index d80ff13cbe..73ca31d623 100644 --- a/source/VERSION +++ b/source/VERSION @@ -36,7 +36,7 @@ SAMBA_VERSION_RELEASE=28 # e.g. SAMBA_VERSION_REVISION=a # # -> "2.2.8a" # ######################################################## -SAMBA_VERSION_REVISION= +SAMBA_VERSION_REVISION=a ######################################################## # For 'pre' releases the version will be # diff --git a/source/auth/auth_domain.c b/source/auth/auth_domain.c index a32677d037..115c57fbe0 100644 --- a/source/auth/auth_domain.c +++ b/source/auth/auth_domain.c @@ -125,11 +125,14 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result))); if (!lp_client_schannel()) { /* We need to set up a creds chain on an unauthenticated netlogon pipe. */ - uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS; + uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS; uint32 sec_chan_type = 0; unsigned char machine_pwd[16]; + const char *account_name; - if (!get_trust_pw(domain, machine_pwd, &sec_chan_type)) { + if (!get_trust_pw_hash(domain, machine_pwd, &account_name, + &sec_chan_type)) + { DEBUG(0, ("connect_to_domain_password_server: could not fetch " "trust account password for domain '%s'\n", domain)); @@ -143,7 +146,7 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result))); dc_name, /* server name */ domain, /* domain */ global_myname(), /* client name */ - global_myname(), /* machine account name */ + account_name, /* machine account name */ machine_pwd, sec_chan_type, &neg_flags); diff --git a/source/auth/auth_ntlmssp.c b/source/auth/auth_ntlmssp.c index 51b145a760..a49b36a0a1 100644 --- a/source/auth/auth_ntlmssp.c +++ b/source/auth/auth_ntlmssp.c @@ -187,7 +187,13 @@ NTSTATUS auth_ntlmssp_start(AUTH_NTLMSSP_STATE **auth_ntlmssp_state) void auth_ntlmssp_end(AUTH_NTLMSSP_STATE **auth_ntlmssp_state) { - TALLOC_CTX *mem_ctx = (*auth_ntlmssp_state)->mem_ctx; + TALLOC_CTX *mem_ctx; + + if (*auth_ntlmssp_state == NULL) { + return; + } + + mem_ctx = (*auth_ntlmssp_state)->mem_ctx; if ((*auth_ntlmssp_state)->ntlmssp_state) { ntlmssp_end(&(*auth_ntlmssp_state)->ntlmssp_state); diff --git a/source/auth/auth_server.c b/source/auth/auth_server.c index d490b1a467..ba2a714539 100644 --- a/source/auth/auth_server.c +++ b/source/auth/auth_server.c @@ -71,6 +71,7 @@ static struct cli_state *server_cryptkey(TALLOC_CTX *mem_ctx) connection (tridge) */ if (!grab_server_mutex(desthost)) { + cli_shutdown(cli); return NULL; } diff --git a/source/auth/auth_util.c b/source/auth/auth_util.c index 32224fa219..b3a3d39924 100644 --- a/source/auth/auth_util.c +++ b/source/auth/auth_util.c @@ -811,7 +811,7 @@ static NTSTATUS create_builtin_administrators( void ) return NT_STATUS_NO_MEMORY; } fstr_sprintf( root_name, "%s\\root", get_global_sam_name() ); - ret = lookup_name( ctx, root_name, 0, NULL, NULL, &root_sid, &type ); + ret = lookup_name( ctx, root_name, LOOKUP_NAME_DOMAIN, NULL, NULL, &root_sid, &type ); TALLOC_FREE( ctx ); if ( ret ) { diff --git a/source/client/client.c b/source/client/client.c index 0cc14330cc..3f96f63f90 100644 --- a/source/client/client.c +++ b/source/client/client.c @@ -279,9 +279,11 @@ static int do_cd(char *newdir) pstrcpy(cur_dir,p); } else { pstrcat(cur_dir,p); - if ((cur_dir[0] != '\0') && (*(cur_dir+strlen(cur_dir)-1) != CLI_DIRSEP_CHAR)) { - pstrcat(cur_dir, CLI_DIRSEP_STR); - } + } + + /* Ensure cur_dir ends in a DIRSEP */ + if ((cur_dir[0] != '\0') && (*(cur_dir+strlen(cur_dir)-1) != CLI_DIRSEP_CHAR)) { + pstrcat(cur_dir, CLI_DIRSEP_STR); } clean_name(cur_dir); @@ -699,18 +701,12 @@ static int cmd_dir(void) int rc; dir_total = 0; - if (strcmp(cur_dir, CLI_DIRSEP_STR) != 0) { - pstrcpy(mask,cur_dir); - if ((mask[0] != '\0') && (mask[strlen(mask)-1]!=CLI_DIRSEP_CHAR)) - pstrcat(mask,CLI_DIRSEP_STR); - } else { - pstrcpy(mask, CLI_DIRSEP_STR); - } + pstrcpy(mask,cur_dir); if (next_token_nr(NULL,buf,NULL,sizeof(buf))) { dos_format(p); if (*p == CLI_DIRSEP_CHAR) - pstrcpy(mask,p + 1); + pstrcpy(mask,p); else pstrcat(mask,p); } else { @@ -745,9 +741,7 @@ static int cmd_du(void) dir_total = 0; pstrcpy(mask,cur_dir); - if ((mask[0] != '\0') && (mask[strlen(mask)-1]!=CLI_DIRSEP_CHAR)) - pstrcat(mask,CLI_DIRSEP_STR); - + if (next_token_nr(NULL,buf,NULL,sizeof(buf))) { dos_format(p); if (*p == CLI_DIRSEP_CHAR) @@ -912,7 +906,6 @@ static int cmd_get(void) char *p; pstrcpy(rname,cur_dir); - pstrcat(rname,CLI_DIRSEP_STR); p = rname + strlen(rname); @@ -1007,7 +1000,6 @@ static int cmd_more(void) int rc = 0; pstrcpy(rname,cur_dir); - pstrcat(rname,CLI_DIRSEP_STR); slprintf(lname,sizeof(lname)-1, "%s/smbmore.XXXXXX",tmpdir()); fd = smb_mkstemp(lname); @@ -1056,8 +1048,6 @@ static int cmd_mget(void) while (next_token_nr(NULL,p,NULL,sizeof(buf))) { pstrcpy(mget_mask,cur_dir); - if ((mget_mask[0] != '\0') && (mget_mask[strlen(mget_mask)-1]!=CLI_DIRSEP_CHAR)) - pstrcat(mget_mask,CLI_DIRSEP_STR); if (*p == CLI_DIRSEP_CHAR) pstrcpy(mget_mask,p); @@ -1068,8 +1058,6 @@ static int cmd_mget(void) if (!*mget_mask) { pstrcpy(mget_mask,cur_dir); - if(mget_mask[strlen(mget_mask)-1]!=CLI_DIRSEP_CHAR) - pstrcat(mget_mask,CLI_DIRSEP_STR); pstrcat(mget_mask,"*"); do_list(mget_mask, attribute,do_mget,False,True); } @@ -1348,7 +1336,6 @@ static int cmd_put(void) char *p=buf; pstrcpy(rname,cur_dir); - pstrcat(rname,CLI_DIRSEP_STR); if (!next_token_nr(NULL,p,NULL,sizeof(buf))) { d_printf("put <filename>\n"); @@ -1997,6 +1984,7 @@ static int cmd_posix(void) CLI_DIRSEP_CHAR = '/'; *CLI_DIRSEP_STR = '/'; pstrcpy(cur_dir, CLI_DIRSEP_STR); + do_cd(cur_dir); } return 0; @@ -2902,7 +2890,6 @@ static int cmd_reget(void) char *p; pstrcpy(remote_name, cur_dir); - pstrcat(remote_name, CLI_DIRSEP_STR); p = remote_name + strlen(remote_name); @@ -2931,7 +2918,6 @@ static int cmd_reput(void) SMB_STRUCT_STAT st; pstrcpy(remote_name, cur_dir); - pstrcat(remote_name, CLI_DIRSEP_STR); if (!next_token_nr(NULL, p, NULL, sizeof(buf))) { d_printf("reput <filename>\n"); @@ -3857,6 +3843,7 @@ static int do_message_op(void) int main(int argc,char *argv[]) { pstring base_directory; + int len = 0; int opt; pstring query_host; BOOL message = False; @@ -3907,7 +3894,7 @@ static int do_message_op(void) set_global_myworkgroup( "" ); set_global_myname( "" ); - /* set default debug level to 0 regardless of what smb.conf sets */ + /* set default debug level to 1 regardless of what smb.conf sets */ setup_logging( "smbclient", True ); DEBUGLEVEL_CLASS[DBGC_ALL] = 1; if ((dbf = x_fdup(x_stderr))) { @@ -4068,6 +4055,12 @@ static int do_message_op(void) poptPrintUsage(pc, stderr, 0); exit(1); } + /* Remove trailing slashes */ + len = strlen(service); + while(len > 0 && service[len - 1] == '\\') { + --len; + service[len] = '\0'; + } } if ( strlen(new_workgroup) != 0 ) diff --git a/source/client/mount.cifs.c b/source/client/mount.cifs.c index 2e48a42aaf..4385412f98 100755 --- a/source/client/mount.cifs.c +++ b/source/client/mount.cifs.c @@ -80,6 +80,40 @@ static char * mountpassword = NULL; char * domain_name = NULL; char * prefixpath = NULL; +/* glibc doesn't have strlcpy, strlcat. Ensure we do. JRA. We + * don't link to libreplace so need them here. */ + +/* like strncpy but does not 0 fill the buffer and always null + * terminates. bufsize is the size of the destination buffer */ +size_t strlcpy(char *d, const char *s, size_t bufsize) +{ + size_t len = strlen(s); + size_t ret = len; + if (bufsize <= 0) return 0; + if (len >= bufsize) len = bufsize-1; + memcpy(d, s, len); + d[len] = 0; + return ret; +} + +/* like strncat but does not 0 fill the buffer and always null + * terminates. bufsize is the length of the buffer, which should + * be one more than the maximum resulting string length */ +size_t strlcat(char *d, const char *s, size_t bufsize) +{ + size_t len1 = strlen(d); + size_t len2 = strlen(s); + size_t ret = len1 + len2; + + if (len1+len2 >= bufsize) { + len2 = bufsize - (len1+1); + } + if (len2 > 0) { + memcpy(d+len1, s, len2); + d[len1+len2] = 0; + } + return ret; +} /* BB finish BB @@ -169,8 +203,10 @@ static int open_cred_file(char * file_name) /* go past equals sign */ temp_val++; for(length = 0;length<4087;length++) { - if(temp_val[length] == '\n') + if ((temp_val[length] == '\n') + || (temp_val[length] == '\0')) { break; + } } if(length > 4086) { printf("mount.cifs failed due to malformed username in credentials file"); @@ -193,8 +229,10 @@ static int open_cred_file(char * file_name) /* go past equals sign */ temp_val++; for(length = 0;length<65;length++) { - if(temp_val[length] == '\n') + if ((temp_val[length] == '\n') + || (temp_val[length] == '\0')) { break; + } } if(length > 64) { printf("mount.cifs failed: password in credentials file too long\n"); @@ -222,8 +260,10 @@ static int open_cred_file(char * file_name) if(verboseflag) printf("\nDomain %s\n",temp_val); for(length = 0;length<65;length++) { - if(temp_val[length] == '\n') - break; + if ((temp_val[length] == '\n') + || (temp_val[length] == '\0')) { + break; + } } if(length > 64) { printf("mount.cifs failed: domain in credentials file too long\n"); @@ -321,6 +361,8 @@ static int parse_options(char ** optionsp, int * filesys_flags) int out_len = 0; int word_len; int rc = 0; + char user[32]; + char group[32]; if (!optionsp || !*optionsp) return 1; @@ -331,6 +373,13 @@ static int parse_options(char ** optionsp, int * filesys_flags) /* BB fixme check for separator override BB */ + if (getuid()) { + got_uid = 1; + snprintf(user,sizeof(user),"%u",getuid()); + got_gid = 1; + snprintf(group,sizeof(group),"%u",getgid()); + } + /* while ((data = strsep(&options, ",")) != NULL) { */ while(data != NULL) { /* check if ends with trailing comma */ @@ -493,33 +542,33 @@ static int parse_options(char ** optionsp, int * filesys_flags) got_uid = 1; if (!isdigit(*value)) { struct passwd *pw; - static char temp[32]; if (!(pw = getpwnam(value))) { printf("bad user name \"%s\"\n", value); exit(1); } - sprintf(temp, "%u", pw->pw_uid); - value = temp; - endpwent(); + snprintf(user, sizeof(user), "%u", pw->pw_uid); + } else { + strlcpy(user,value,sizeof(user)); } } + goto nocopy; } else if (strncmp(data, "gid", 3) == 0) { if (value && *value) { got_gid = 1; if (!isdigit(*value)) { struct group *gr; - static char temp[32]; if (!(gr = getgrnam(value))) { printf("bad group name \"%s\"\n", value); exit(1); } - sprintf(temp, "%u", gr->gr_gid); - value = temp; - endpwent(); + snprintf(group, sizeof(group), "%u", gr->gr_gid); + } else { + strlcpy(group,value,sizeof(group)); } } + goto nocopy; /* fmask and dmask synonyms for people used to smbfs syntax */ } else if (strcmp(data, "file_mode") == 0 || strcmp(data, "fmask")==0) { if (!value || !*value) { @@ -610,17 +659,55 @@ static int parse_options(char ** optionsp, int * filesys_flags) exit(1); } - if (out_len) - out[out_len++] = ','; + if (out_len) { + strlcat(out, ",", out_len + word_len + 2); + out_len++; + } + if (value) - sprintf(out + out_len, "%s=%s", data, value); + snprintf(out + out_len, word_len + 1, "%s=%s", data, value); else - sprintf(out + out_len, "%s", data); + snprintf(out + out_len, word_len + 1, "%s", data); out_len = strlen(out); nocopy: data = next_keyword; } + + /* special-case the uid and gid */ + if (got_uid) { + word_len = strlen(user); + + out = (char *)realloc(out, out_len + word_len + 6); + if (out == NULL) { + perror("malloc"); + exit(1); + } + + if (out_len) { + strlcat(out, ",", out_len + word_len + 6); + out_len++; + } + snprintf(out + out_len, word_len + 5, "uid=%s", user); + out_len = strlen(out); + } + if (got_gid) { + word_len = strlen(group); + + out = (char *)realloc(out, out_len + 1 + word_len + 6); + if (out == NULL) { + perror("malloc"); + exit(1); + } + + if (out_len) { + strlcat(out, ",", out_len + word_len + 6); + out_len++; + } + snprintf(out + out_len, word_len + 5, "gid=%s", group); + out_len = strlen(out); + } + free(*optionsp); *optionsp = out; return 0; @@ -723,7 +810,7 @@ static char * check_for_domain(char **ppuser) if(domainnm == NULL) return NULL; - strcpy(domainnm,*ppuser); + strlcpy(domainnm,*ppuser,len+1); /* move_string(*ppuser, usernm+1) */ len = strlen(usernm+1); @@ -894,6 +981,7 @@ int main(int argc, char ** argv) int gid = 0; int optlen = 0; int orgoptlen = 0; + size_t options_size = 0; int retry = 0; /* set when we have to retry mount with uppercase */ struct stat statbuf; struct utsname sysinfo; @@ -1163,38 +1251,38 @@ mount_retry: optlen += strlen(mountpassword) + 6; if(options) free(options); - options = (char *)malloc(optlen + 10 + 64 /* space for commas in password */ + 8 /* space for domain= , domain name itself was counted as part of the length username string above */); + options_size = optlen + 10 + 64; + options = (char *)malloc(options_size /* space for commas in password */ + 8 /* space for domain= , domain name itself was counted as part of the length username string above */); if(options == NULL) { printf("Could not allocate memory for mount options\n"); return -1; } - options[0] = 0; - strncat(options,"unc=",4); - strcat(options,share_name); + strlcpy(options,"unc=",options_size); + strlcat(options,share_name,options_size); /* scan backwards and reverse direction of slash */ temp = strrchr(options, '/'); if(temp > options + 6) *temp = '\\'; if(ipaddr) { - strncat(options,",ip=",4); - strcat(options,ipaddr); + strlcat(options,",ip=",options_size); + strlcat(options,ipaddr,options_size); } if(user_name) { /* check for syntax like user=domain\user */ if(got_domain == 0) domain_name = check_for_domain(&user_name); - strncat(options,",user=",6); - strcat(options,user_name); + strlcat(options,",user=",options_size); + strlcat(options,user_name,options_size); } if(retry == 0) { - if(domain_name) { + if(domain_name) { /* extra length accounted for in option string above */ - strncat(options,",domain=",8); - strcat(options,domain_name); + strlcat(options,",domain=",options_size); + strlcat(options,domain_name,options_size); } } if(mountpassword) { @@ -1203,21 +1291,21 @@ mount_retry: /* if(sep is not set)*/ if(retry == 0) check_for_comma(&mountpassword); - strncat(options,",pass=",6); - strcat(options,mountpassword); + strlcat(options,",pass=",options_size); + strlcat(options,mountpassword,options_size); } - strncat(options,",ver=",5); - strcat(options,MOUNT_CIFS_VERSION_MAJOR); + strlcat(options,",ver=",options_size); + strlcat(options,MOUNT_CIFS_VERSION_MAJOR,options_size); if(orgoptions) { - strcat(options,","); - strcat(options,orgoptions); + strlcat(options,",",options_size); + strlcat(options,orgoptions,options_size); } if(prefixpath) { - strncat(options,",prefixpath=",12); - strcat(options,prefixpath); /* no need to cat the / */ - } + strlcat(options,",prefixpath=",options_size); + strlcat(options,prefixpath,options_size); /* no need to cat the / */ + } if(verboseflag) printf("\nmount.cifs kernel mount options %s \n",options); if(mount(share_name, mountpoint, "cifs", flags, options)) { @@ -1261,23 +1349,23 @@ mount_retry: char * mount_user = getusername(); memset(mountent.mnt_opts,0,200); if(flags & MS_RDONLY) - strcat(mountent.mnt_opts,"ro"); + strlcat(mountent.mnt_opts,"ro",220); else - strcat(mountent.mnt_opts,"rw"); + strlcat(mountent.mnt_opts,"rw",220); if(flags & MS_MANDLOCK) - strcat(mountent.mnt_opts,",mand"); + strlcat(mountent.mnt_opts,",mand",220); if(flags & MS_NOEXEC) - strcat(mountent.mnt_opts,",noexec"); + strlcat(mountent.mnt_opts,",noexec",220); if(flags & MS_NOSUID) - strcat(mountent.mnt_opts,",nosuid"); + strlcat(mountent.mnt_opts,",nosuid",220); if(flags & MS_NODEV) - strcat(mountent.mnt_opts,",nodev"); + strlcat(mountent.mnt_opts,",nodev",220); if(flags & MS_SYNCHRONOUS) - strcat(mountent.mnt_opts,",synch"); + strlcat(mountent.mnt_opts,",synch",220); if(mount_user) { if(getuid() != 0) { - strcat(mountent.mnt_opts,",user="); - strcat(mountent.mnt_opts,mount_user); + strlcat(mountent.mnt_opts,",user=",220); + strlcat(mountent.mnt_opts,mount_user,220); } /* free(mount_user); do not free static mem */ } @@ -1318,4 +1406,3 @@ mount_exit: } return rc; } - diff --git a/source/client/umount.cifs.c b/source/client/umount.cifs.c index 47ddd1e92e..70829ebaa8 100644 --- a/source/client/umount.cifs.c +++ b/source/client/umount.cifs.c @@ -131,7 +131,7 @@ static int umount_check_perm(char * dir) printf("user unmounting via %s is an optional feature of",thisprogram); printf(" the cifs filesystem driver (cifs.ko)"); printf("\n\tand requires cifs.ko version 1.32 or later\n"); - } else if (rc > 0) + } else if (rc != 0) printf("user unmount of %s failed with %d %s\n",dir,errno,strerror(errno)); close(fileid); diff --git a/source/configure b/source/configure index 9f158f0503..c8f462c55b 100755 --- a/source/configure +++ b/source/configure @@ -14277,6 +14277,145 @@ fi done +for ac_header in stropts.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + { echo "$as_me:$LINENO: checking for usable net/if.h" >&5 echo $ECHO_N "checking for usable net/if.h... $ECHO_C" >&6; } @@ -19001,6 +19140,190 @@ LIBDL="$LIBS" LIBS="$save_LIBS" +{ echo "$as_me:$LINENO: checking for getpass" >&5 +echo $ECHO_N "checking for getpass... $ECHO_C" >&6; } +if test "${ac_cv_func_getpass+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define getpass to an innocuous variant, in case <limits.h> declares getpass. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define getpass innocuous_getpass + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char getpass (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef getpass + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char getpass (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_getpass || defined __stub___getpass +choke me +#endif + +int +main () +{ +return getpass (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_func_getpass=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_getpass=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_getpass" >&5 +echo "${ECHO_T}$ac_cv_func_getpass" >&6; } +if test $ac_cv_func_getpass = yes; then + samba_cv_HAVE_GETPASS=yes +fi + +{ echo "$as_me:$LINENO: checking for getpassphrase" >&5 +echo $ECHO_N "checking for getpassphrase... $ECHO_C" >&6; } +if test "${ac_cv_func_getpassphrase+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define getpassphrase to an innocuous variant, in case <limits.h> declares getpassphrase. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define getpassphrase innocuous_getpassphrase + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char getpassphrase (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef getpassphrase + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char getpassphrase (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_getpassphrase || defined __stub___getpassphrase +choke me +#endif + +int +main () +{ +return getpassphrase (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_func_getpassphrase=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_getpassphrase=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_getpassphrase" >&5 +echo "${ECHO_T}$ac_cv_func_getpassphrase" >&6; } +if test $ac_cv_func_getpassphrase = yes; then + samba_cv_HAVE_GETPASSPHRASE=yes +fi + +if test x"$samba_cv_HAVE_GETPASS" = x"yes" -a x"$samba_cv_HAVE_GETPASSPHRASE" = x"yes"; then + +cat >>confdefs.h <<\_ACEOF +#define REPLACE_GETPASS_BY_GETPASSPHRASE 1 +_ACEOF + + +cat >>confdefs.h <<\_ACEOF +#define REPLACE_GETPASS 1 +_ACEOF + + LIBREPLACEOBJ="${LIBREPLACEOBJ} getpass.o" +else + { echo "$as_me:$LINENO: checking whether getpass should be replaced" >&5 echo $ECHO_N "checking whether getpass should be replaced... $ECHO_C" >&6; } if test "${samba_cv_REPLACE_GETPASS+set}" = set; then @@ -19071,6 +19394,8 @@ _ACEOF LIBREPLACEOBJ="${LIBREPLACEOBJ} getpass.o" fi +fi + { echo "$as_me:$LINENO: checking whether strptime is available and works" >&5 echo $ECHO_N "checking whether strptime is available and works... $ECHO_C" >&6; } if test "${libreplace_cv_STRPTIME_OK+set}" = set; then @@ -43756,9 +44081,13 @@ fi done -{ echo "$as_me:$LINENO: checking for inotify_init" >&5 -echo $ECHO_N "checking for inotify_init... $ECHO_C" >&6; } -if test "${ac_cv_func_inotify_init+set}" = set; then + +for ac_func in inotify_init +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF @@ -43767,12 +44096,12 @@ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ -/* Define inotify_init to an innocuous variant, in case <limits.h> declares inotify_init. +/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func. For example, HP-UX 11i <limits.h> declares gettimeofday. */ -#define inotify_init innocuous_inotify_init +#define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, - which can conflict with char inotify_init (); below. + which can conflict with char $ac_func (); below. Prefer <limits.h> to <assert.h> if __STDC__ is defined, since <limits.h> exists even on freestanding compilers. */ @@ -43782,7 +44111,7 @@ cat >>conftest.$ac_ext <<_ACEOF # include <assert.h> #endif -#undef inotify_init +#undef $ac_func /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC @@ -43790,18 +44119,18 @@ cat >>conftest.$ac_ext <<_ACEOF #ifdef __cplusplus extern "C" #endif -char inotify_init (); +char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ -#if defined __stub_inotify_init || defined __stub___inotify_init +#if defined __stub_$ac_func || defined __stub___$ac_func choke me #endif int main () { -return inotify_init (); +return $ac_func (); ; return 0; } @@ -43824,19 +44153,27 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then - ac_cv_func_inotify_init=yes + eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 - ac_cv_func_inotify_init=no + eval "$as_ac_var=no" fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi -{ echo "$as_me:$LINENO: result: $ac_cv_func_inotify_init" >&5 -echo "${ECHO_T}$ac_cv_func_inotify_init" >&6; } +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done { echo "$as_me:$LINENO: checking for __NR_inotify_init declaration" >&5 @@ -48274,6 +48611,67 @@ _ACEOF fi + ####################################################### + # if we have LBER_OPT_LOG_PRINT_FN, we can intercept + # ldap logging and print it out in the samba logs + { echo "$as_me:$LINENO: checking for LBER_OPT_LOG_PRINT_FN" >&5 +echo $ECHO_N "checking for LBER_OPT_LOG_PRINT_FN... $ECHO_C" >&6; } +if test "${samba_cv_HAVE_LBER_OPT_LOG_PRINT_FN+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <lber.h> +int +main () +{ +int val = LBER_OPT_LOG_PRINT_FN; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + samba_cv_HAVE_LBER_OPT_LOG_PRINT_FN=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + samba_cv_HAVE_LBER_OPT_LOG_PRINT_FN=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $samba_cv_HAVE_LBER_OPT_LOG_PRINT_FN" >&5 +echo "${ECHO_T}$samba_cv_HAVE_LBER_OPT_LOG_PRINT_FN" >&6; } + + if test x"$samba_cv_HAVE_LBER_OPT_LOG_PRINT_FN" = x"yes"; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LBER_LOG_PRINT_FN 1 +_ACEOF + + fi + ######################################################## # now see if we can find the ldap libs in standard paths @@ -55931,6 +56329,128 @@ _ACEOF fi + { echo "$as_me:$LINENO: checking for krb5_principal_get_realm" >&5 +echo $ECHO_N "checking for krb5_principal_get_realm... $ECHO_C" >&6; } +if test "${samba_cv_HAVE_KRB5_PRINCIPAL_GET_REALM+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <krb5.h> +int +main () +{ +krb5_context ctx = NULL; krb5_principal princ = NULL; const char *str = krb5_principal_get_realm(ctx, princ); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + samba_cv_HAVE_KRB5_PRINCIPAL_GET_REALM=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + samba_cv_HAVE_KRB5_PRINCIPAL_GET_REALM=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $samba_cv_HAVE_KRB5_PRINCIPAL_GET_REALM" >&5 +echo "${ECHO_T}$samba_cv_HAVE_KRB5_PRINCIPAL_GET_REALM" >&6; } + + if test x"$samba_cv_HAVE_KRB5_PRINCIPAL_GET_REALM" = x"yes"; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_KRB5_PRINCIPAL_GET_REALM 1 +_ACEOF + + fi + + { echo "$as_me:$LINENO: checking for krb5_princ_realm" >&5 +echo $ECHO_N "checking for krb5_princ_realm... $ECHO_C" >&6; } +if test "${samba_cv_HAVE_KRB5_PRINC_REALM+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <krb5.h> +int +main () +{ +krb5_context ctx = NULL; krb5_principal princ = NULL; const char *str = krb5_princ_realm(ctx, princ)->data; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + samba_cv_HAVE_KRB5_PRINC_REALM=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + samba_cv_HAVE_KRB5_PRINC_REALM=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $samba_cv_HAVE_KRB5_PRINC_REALM" >&5 +echo "${ECHO_T}$samba_cv_HAVE_KRB5_PRINC_REALM" >&6; } + + if test x"$samba_cv_HAVE_KRB5_PRINC_REALM" = x"yes"; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_KRB5_PRINC_REALM 1 +_ACEOF + + fi + # # # Now the decisions whether we can support krb5 @@ -66139,6 +66659,43 @@ echo "${ECHO_T}not" >&6; } fi + { echo "$as_me:$LINENO: checking how to build vfs_notify_fam" >&5 +echo $ECHO_N "checking how to build vfs_notify_fam... $ECHO_C" >&6; } + if test "$MODULE_vfs_notify_fam"; then + DEST=$MODULE_vfs_notify_fam + elif test "$MODULE_vfs" -a "$MODULE_DEFAULT_vfs_notify_fam"; then + DEST=$MODULE_vfs + else + DEST=$MODULE_DEFAULT_vfs_notify_fam + fi + + if test x"$DEST" = xSHARED; then + +cat >>confdefs.h <<\_ACEOF +#define vfs_notify_fam_init init_module +_ACEOF + + VFS_MODULES="$VFS_MODULES "bin/notify_fam.$SHLIBEXT"" + { echo "$as_me:$LINENO: result: shared" >&5 +echo "${ECHO_T}shared" >&6; } + + string_shared_modules="$string_shared_modules vfs_notify_fam" + elif test x"$DEST" = xSTATIC; then + init_static_modules_vfs="$init_static_modules_vfs vfs_notify_fam_init();" + decl_static_modules_vfs="$decl_static_modules_vfs extern NTSTATUS vfs_notify_fam_init(void);" + string_static_modules="$string_static_modules vfs_notify_fam" + VFS_STATIC="$VFS_STATIC \$(VFS_NOTIFY_FAM_OBJ)" + + + { echo "$as_me:$LINENO: result: static" >&5 +echo "${ECHO_T}static" >&6; } + else + string_ignored_modules="$string_ignored_modules vfs_notify_fam" + { echo "$as_me:$LINENO: result: not" >&5 +echo "${ECHO_T}not" >&6; } + fi + + diff --git a/source/configure.in b/source/configure.in index 91f1582c56..9c31de4bf3 100644 --- a/source/configure.in +++ b/source/configure.in @@ -2541,7 +2541,7 @@ fi AC_CACHE_CHECK([for inotify support],samba_cv_HAVE_INOTIFY,[ AC_CHECK_HEADERS(linux/inotify.h asm/unistd.h) -AC_CHECK_FUNC(inotify_init) +AC_CHECK_FUNCS(inotify_init) AC_HAVE_DECL(__NR_inotify_init, [#include <asm/unistd.h>]) ], samba_cv_HAVE_INOTIFY=yes, @@ -3243,6 +3243,21 @@ if test x"$with_ldap_support" != x"no"; then # this test must be before the libldap test AC_CHECK_LIB_EXT(lber, LDAP_LIBS, ber_scanf) + ####################################################### + # if we have LBER_OPT_LOG_PRINT_FN, we can intercept + # ldap logging and print it out in the samba logs + AC_CACHE_CHECK([for LBER_OPT_LOG_PRINT_FN], + samba_cv_HAVE_LBER_OPT_LOG_PRINT_FN, + [AC_TRY_COMPILE([#include <lber.h>], + [int val = LBER_OPT_LOG_PRINT_FN;], + samba_cv_HAVE_LBER_OPT_LOG_PRINT_FN=yes, + samba_cv_HAVE_LBER_OPT_LOG_PRINT_FN=no)]) + + if test x"$samba_cv_HAVE_LBER_OPT_LOG_PRINT_FN" = x"yes"; then + AC_DEFINE(HAVE_LBER_LOG_PRINT_FN, 1, + [Support for LDAP/LBER logging interception]) + fi + ######################################################## # now see if we can find the ldap libs in standard paths AC_CHECK_LIB_EXT(ldap, LDAP_LIBS, ldap_init) @@ -3944,6 +3959,30 @@ if test x"$with_ads_support" != x"no"; then fi + AC_CACHE_CHECK([for krb5_principal_get_realm], + samba_cv_HAVE_KRB5_PRINCIPAL_GET_REALM,[ + AC_TRY_LINK([#include <krb5.h>], + [krb5_context ctx = NULL; krb5_principal princ = NULL; const char *str = krb5_principal_get_realm(ctx, princ);], + samba_cv_HAVE_KRB5_PRINCIPAL_GET_REALM=yes, + samba_cv_HAVE_KRB5_PRINCIPAL_GET_REALM=no)]) + + if test x"$samba_cv_HAVE_KRB5_PRINCIPAL_GET_REALM" = x"yes"; then + AC_DEFINE(HAVE_KRB5_PRINCIPAL_GET_REALM,1, + [Whether the function krb5_principal_get_realm is defined]) + fi + + AC_CACHE_CHECK([for krb5_princ_realm], + samba_cv_HAVE_KRB5_PRINC_REALM,[ + AC_TRY_LINK([#include <krb5.h>], + [krb5_context ctx = NULL; krb5_principal princ = NULL; const char *str = krb5_princ_realm(ctx, princ)->data;], + samba_cv_HAVE_KRB5_PRINC_REALM=yes, + samba_cv_HAVE_KRB5_PRINC_REALM=no)]) + + if test x"$samba_cv_HAVE_KRB5_PRINC_REALM" = x"yes"; then + AC_DEFINE(HAVE_KRB5_PRINC_REALM,1, + [Whether the macro krb5_princ_realm is defined]) + fi + # # # Now the decisions whether we can support krb5 @@ -6099,6 +6138,7 @@ SMB_MODULE(vfs_prealloc, \$(VFS_PREALLOC_OBJ), "bin/prealloc.$SHLIBEXT", VFS) SMB_MODULE(vfs_commit, \$(VFS_COMMIT_OBJ), "bin/commit.$SHLIBEXT", VFS) SMB_MODULE(vfs_gpfs, \$(VFS_GPFS_OBJ), "bin/gpfs.$SHLIBEXT", VFS) SMB_MODULE(vfs_readahead, \$(VFS_READAHEAD_OBJ), "bin/readahead.$SHLIBEXT", VFS) +SMB_MODULE(vfs_notify_fam, \$(VFS_NOTIFY_FAM_OBJ), "bin/notify_fam.$SHLIBEXT", VFS) SMB_SUBSYSTEM(VFS,smbd/vfs.o) diff --git a/source/groupdb/mapping.c b/source/groupdb/mapping.c index b0e59c0ddd..cf015a5eab 100644 --- a/source/groupdb/mapping.c +++ b/source/groupdb/mapping.c @@ -452,7 +452,7 @@ NTSTATUS pdb_default_create_alias(struct pdb_methods *methods, return NT_STATUS_NO_MEMORY; } - exists = lookup_name(mem_ctx, name, LOOKUP_NAME_ISOLATED, + exists = lookup_name(mem_ctx, name, LOOKUP_NAME_LOCAL, NULL, NULL, &sid, &type); TALLOC_FREE(mem_ctx); diff --git a/source/include/ads.h b/source/include/ads.h index fcaeb2069d..24884f5e18 100644 --- a/source/include/ads.h +++ b/source/include/ads.h @@ -321,4 +321,7 @@ typedef struct { int val; int critical; } ads_control; + +#define ADS_IGNORE_PRINCIPAL "not_defined_in_RFC4178@please_ignore" + #endif /* _INCLUDE_ADS_H_ */ diff --git a/source/include/config.h.in b/source/include/config.h.in index f8f3516e8a..892d80d125 100644 --- a/source/include/config.h.in +++ b/source/include/config.h.in @@ -685,6 +685,9 @@ /* Whether kernel has inotify support */ #undef HAVE_INOTIFY +/* Define to 1 if you have the `inotify_init' function. */ +#undef HAVE_INOTIFY_INIT + /* Whether int16 typedef is included by rpc/rpc.h */ #undef HAVE_INT16_FROM_RPC_RPC_H @@ -842,9 +845,15 @@ /* Define to 1 if you have the `krb5_principal_get_comp_string' function. */ #undef HAVE_KRB5_PRINCIPAL_GET_COMP_STRING +/* Whether the function krb5_principal_get_realm is defined */ +#undef HAVE_KRB5_PRINCIPAL_GET_REALM + /* Whether krb5_princ_component is available */ #undef HAVE_KRB5_PRINC_COMPONENT +/* Whether the macro krb5_princ_realm is defined */ +#undef HAVE_KRB5_PRINC_REALM + /* Define to 1 if you have the `krb5_princ_size' function. */ #undef HAVE_KRB5_PRINC_SIZE @@ -890,6 +899,9 @@ /* Define to 1 if you have the <lber.h> header file. */ #undef HAVE_LBER_H +/* Support for LDAP/LBER logging interception */ +#undef HAVE_LBER_LOG_PRINT_FN + /* Whether ldap is available */ #undef HAVE_LDAP @@ -1571,6 +1583,9 @@ /* Define to 1 if you have the `strnlen' function. */ #undef HAVE_STRNLEN +/* Define to 1 if you have the <stropts.h> header file. */ +#undef HAVE_STROPTS_H + /* Define to 1 if you have the `strpbrk' function. */ #undef HAVE_STRPBRK @@ -2279,6 +2294,9 @@ /* Whether getpass should be replaced */ #undef REPLACE_GETPASS +/* getpass returns <9 chars where getpassphrase returns <265 chars */ +#undef REPLACE_GETPASS_BY_GETPASSPHRASE + /* Whether inet_ntoa should be replaced */ #undef REPLACE_INET_NTOA @@ -2825,6 +2843,9 @@ /* Whether to build vfs_netatalk as shared module */ #undef vfs_netatalk_init +/* Whether to build vfs_notify_fam as shared module */ +#undef vfs_notify_fam_init + /* Whether to build vfs_posixacl as shared module */ #undef vfs_posixacl_init diff --git a/source/include/includes.h b/source/include/includes.h index 3ddfc7d96d..045b989158 100644 --- a/source/include/includes.h +++ b/source/include/includes.h @@ -107,7 +107,6 @@ #include "system/locale.h" #include "system/network.h" #include "system/passwd.h" -#include "system/printing.h" #include "system/readline.h" #include "system/select.h" #include "system/shmem.h" diff --git a/source/include/rpc_dce.h b/source/include/rpc_dce.h index 09e5f25da8..8a7934c04a 100644 --- a/source/include/rpc_dce.h +++ b/source/include/rpc_dce.h @@ -112,6 +112,8 @@ enum RPC_PKT_TYPE { /* these are the flags that ADS clients use */ #define NETLOGON_NEG_AUTH2_ADS_FLAGS (0x200fbffb | NETLOGON_NEG_ARCFOUR | NETLOGON_NEG_128BIT | NETLOGON_NEG_SCHANNEL) +#define NETLOGON_NEG_SELECT_AUTH2_FLAGS ((lp_security() == SEC_ADS) ? NETLOGON_NEG_AUTH2_ADS_FLAGS : NETLOGON_NEG_AUTH2_FLAGS) + enum schannel_direction { SENDER_IS_INITIATOR, SENDER_IS_ACCEPTOR diff --git a/source/include/rpc_samr.h b/source/include/rpc_samr.h index 575cd78ef2..a7a9660c7f 100644 --- a/source/include/rpc_samr.h +++ b/source/include/rpc_samr.h @@ -146,6 +146,31 @@ SamrTestPrivateFunctionsUser #define SAMR_CHGPASSWD_USER3 0x3F #define SAMR_CONNECT5 0x40 +/* SAMR account creation flags/permissions */ +#define SAMR_USER_GETNAME 0x1 +#define SAMR_USER_GETLOCALE 0x2 +#define SAMR_USER_GETLOCCOM 0x4 +#define SAMR_USER_GETLOGONINFO 0x8 +#define SAMR_USER_GETATTR 0x10 +#define SAMR_USER_SETATTR 0x20 +#define SAMR_USER_CHPASS 0x40 +#define SAMR_USER_SETPASS 0x80 +#define SAMR_USER_GETGROUPS 0x100 +#define SAMR_USER_GETMEMBERSHIP 0x200 +#define SAMR_USER_CHMEMBERSHIP 0x400 +#define SAMR_STANDARD_DELETE 0x10000 +#define SAMR_STANDARD_READCTRL 0x20000 +#define SAMR_STANDARD_WRITEDAC 0x40000 +#define SAMR_STANDARD_WRITEOWNER 0x80000 +#define SAMR_STANDARD_SYNC 0x100000 +#define SAMR_GENERIC_ACCESSSACL 0x800000 +#define SAMR_GENERIC_MAXALLOWED 0x2000000 +#define SAMR_GENERIC_ALL 0x10000000 +#define SAMR_GENERIC_EXECUTE 0x20000000 +#define SAMR_GENERIC_WRITE 0x40000000 +#define SAMR_GENERIC_READ 0x80000000 + + typedef struct logon_hours_info { uint32 max_len; /* normally 1260 bytes */ @@ -1557,7 +1582,7 @@ typedef struct q_samr_create_user_info UNISTR2 uni_name; /* unicode account name */ uint32 acb_info; /* account control info */ - uint32 access_mask; /* 0xe005 00b0 */ + uint32 acct_flags; /* 0xe005 00b0 */ } SAMR_Q_CREATE_USER; diff --git a/source/include/smb.h b/source/include/smb.h index 3f2f2235f6..46afcde7c6 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -28,7 +28,7 @@ #define _SMB_H /* logged when starting the various Samba daemons */ -#define COPYRIGHT_STARTUP_MESSAGE "Copyright Andrew Tridgell and the Samba Team 1992-2007" +#define COPYRIGHT_STARTUP_MESSAGE "Copyright Andrew Tridgell and the Samba Team 1992-2008" #if defined(LARGE_SMB_OFF_T) @@ -257,12 +257,28 @@ enum lsa_SidType { SID_NAME_COMPUTER /* sid for a computer */ }; -#define LOOKUP_NAME_ISOLATED 1 /* Look up unqualified names */ -#define LOOKUP_NAME_REMOTE 2 /* Ask others */ -#define LOOKUP_NAME_ALL (LOOKUP_NAME_ISOLATED|LOOKUP_NAME_REMOTE) -#define LOOKUP_NAME_GROUP 4 /* (unused) This is a NASTY hack for valid users = @foo - * where foo also exists in as user. */ +#define LOOKUP_NAME_NONE 0x00000000 +#define LOOKUP_NAME_ISOLATED 0x00000001 /* Look up unqualified names */ +#define LOOKUP_NAME_REMOTE 0x00000002 /* Ask others */ +#define LOOKUP_NAME_GROUP 0x00000004 /* (unused) This is a NASTY hack for + valid users = @foo where foo also + exists in as user. */ +#define LOOKUP_NAME_EXPLICIT 0x00000008 /* Only include + explicitly mapped names and not + the Unix {User,Group} domain */ +#define LOOKUP_NAME_BUILTIN 0x00000010 /* builtin names */ +#define LOOKUP_NAME_WKN 0x00000020 /* well known names */ +#define LOOKUP_NAME_DOMAIN 0x00000040 /* only lookup own domain */ +#define LOOKUP_NAME_LOCAL (LOOKUP_NAME_ISOLATED\ + |LOOKUP_NAME_BUILTIN\ + |LOOKUP_NAME_WKN\ + |LOOKUP_NAME_DOMAIN) +#define LOOKUP_NAME_ALL (LOOKUP_NAME_ISOLATED\ + |LOOKUP_NAME_REMOTE\ + |LOOKUP_NAME_BUILTIN\ + |LOOKUP_NAME_WKN\ + |LOOKUP_NAME_DOMAIN) /** * @brief Security Identifier @@ -1918,4 +1934,15 @@ enum usershare_err { /* Different reasons for closing a file. */ enum file_close_type {NORMAL_CLOSE=0,SHUTDOWN_CLOSE,ERROR_CLOSE}; +/* Used in SMB_FS_OBJECTID_INFORMATION requests. Must be exactly 48 bytes. */ +#define SAMBA_EXTENDED_INFO_MAGIC 0x536d4261 /* "SmBa" */ +#define SAMBA_EXTENDED_INFO_VERSION_STRING_LENGTH 28 +struct smb_extended_info { + uint32 samba_magic; /* Always SAMBA_EXTRA_INFO_MAGIC */ + uint32 samba_version; /* Major/Minor/Release/Revision */ + uint32 samba_subversion; /* Prerelease/RC/Vendor patch */ + NTTIME samba_gitcommitdate; + char samba_version_string[SAMBA_EXTENDED_INFO_VERSION_STRING_LENGTH]; +}; + #endif /* _SMB_H */ diff --git a/source/include/version.h b/source/include/version.h index 9d5070159c..9f5bd0c7bb 100644 --- a/source/include/version.h +++ b/source/include/version.h @@ -2,5 +2,6 @@ #define SAMBA_VERSION_MAJOR 3 #define SAMBA_VERSION_MINOR 0 #define SAMBA_VERSION_RELEASE 28 -#define SAMBA_VERSION_OFFICIAL_STRING "3.0.28" +#define SAMBA_VERSION_REVISION "a" +#define SAMBA_VERSION_OFFICIAL_STRING "3.0.28a" #define SAMBA_VERSION_STRING samba_version_string() diff --git a/source/lib/charcnv.c b/source/lib/charcnv.c index 7b52830cde..7d42e50c52 100644 --- a/source/lib/charcnv.c +++ b/source/lib/charcnv.c @@ -525,7 +525,7 @@ size_t convert_string(charset_t from, charset_t to, size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to, void const *src, size_t srclen, void *dst, BOOL allow_bad_conv) { - size_t i_len, o_len, destlen = MAX(srclen, 512); + size_t i_len, o_len, destlen = (srclen * 3) / 2; size_t retval; const char *inbuf = (const char *)src; char *outbuf = NULL, *ob = NULL; @@ -551,7 +551,8 @@ size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to, convert: - if ((destlen*2) < destlen) { + /* +2 is for ucs2 null termination. */ + if ((destlen*2)+2 < destlen) { /* wrapped ! abort. */ if (!conv_silent) DEBUG(0, ("convert_string_allocate: destlen wrapped !\n")); @@ -562,10 +563,11 @@ size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to, destlen = destlen * 2; } + /* +2 is for ucs2 null termination. */ if (ctx) { - ob = (char *)TALLOC_REALLOC(ctx, ob, destlen); + ob = (char *)TALLOC_REALLOC(ctx, ob, destlen + 2); } else { - ob = (char *)SMB_REALLOC(ob, destlen); + ob = (char *)SMB_REALLOC(ob, destlen + 2); } if (!ob) { @@ -611,9 +613,10 @@ size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to, destlen = destlen - o_len; if (ctx) { - ob = (char *)TALLOC_REALLOC(ctx,ob,destlen); + /* We're shrinking here so we know the +2 is safe from wrap. */ + ob = (char *)TALLOC_REALLOC(ctx,ob,destlen + 2); } else { - ob = (char *)SMB_REALLOC(ob,destlen); + ob = (char *)SMB_REALLOC(ob,destlen + 2); } if (destlen && !ob) { @@ -622,6 +625,11 @@ size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to, } *dest = ob; + + /* Must ucs2 null terminate in the extra space we allocated. */ + ob[destlen] = '\0'; + ob[destlen+1] = '\0'; + return destlen; use_as_is: diff --git a/source/lib/clobber.c b/source/lib/clobber.c index fb3a0dc281..d3a9c59c36 100644 --- a/source/lib/clobber.c +++ b/source/lib/clobber.c @@ -54,7 +54,11 @@ void clobber_region(const char *fn, unsigned int line, char *dest, size_t len) * (This is not redundant with the clobbering above. The * marking might not actually take effect if we're not running * under valgrind.) */ +#if defined(VALGRIND_MAKE_MEM_UNDEFINED) + VALGRIND_MAKE_MEM_UNDEFINED(dest, len); +#elif defined(VALGRIND_MAKE_WRITABLE) VALGRIND_MAKE_WRITABLE(dest, len); +#endif #endif /* VALGRIND */ #endif /* DEVELOPER */ } diff --git a/source/lib/ldap_debug_handler.c b/source/lib/ldap_debug_handler.c new file mode 100644 index 0000000000..f289f743fb --- /dev/null +++ b/source/lib/ldap_debug_handler.c @@ -0,0 +1,52 @@ +/* + * Unix SMB/CIFS implementation. + * Intercept libldap debug output. + * Copyright (C) Michael Adam 2008 + * + * 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, see <http://www.gnu.org/licenses/>. + */ + +#include "includes.h" + +#if HAVE_LDAP + +static void samba_ldap_log_print_fn(LDAP_CONST char *data) +{ + DEBUG(lp_ldap_debug_threshold(), ("[LDAP] %s", data)); +} + +#endif + +void init_ldap_debugging(void) +{ +#if defined(HAVE_LDAP) && defined(HAVE_LBER_LOG_PRINT_FN) + int ret; + int ldap_debug_level = lp_ldap_debug_level(); + + ret = ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &ldap_debug_level); + if (ret != LDAP_OPT_SUCCESS) { + DEBUG(10, ("Error setting LDAP debug level.\n")); + } + + if (ldap_debug_level == 0) { + return; + } + + ret = ber_set_option(NULL, LBER_OPT_LOG_PRINT_FN, + (void *)samba_ldap_log_print_fn); + if (ret != LBER_OPT_SUCCESS) { + DEBUG(10, ("Error setting LBER log print function.\n")); + } +#endif /* HAVE_LDAP && HAVE_LBER_LOG_PRINT_FN */ +} diff --git a/source/lib/replace/getpass.c b/source/lib/replace/getpass.c index 2ccbf7b733..90f9af9ec6 100644 --- a/source/lib/replace/getpass.c +++ b/source/lib/replace/getpass.c @@ -20,6 +20,19 @@ Cambridge, MA 02139, USA. */ #include "replace.h" +#if defined(REPLACE_GETPASS_BY_GETPASSPHRASE) + +#if defined(HAVE_STDIO_H) +#include <stdio.h> +#endif + +char *getsmbpass(const char *prompt) +{ + return getpassphrase(prompt); +} + +#else /* !REPLACE_GETPASS_BY_GETPASSPHRASE */ + #if defined(HAVE_TERMIOS_H) /* POSIX terminal handling. */ #include <termios.h> @@ -210,3 +223,5 @@ char *getsmbpass(const char *prompt) void getsmbpasswd_dummy(void); void getsmbpasswd_dummy(void) {;} #endif + +#endif /* REPLACE_GETPASS_BY_GETPASSPHRASE */ diff --git a/source/lib/replace/getpass.m4 b/source/lib/replace/getpass.m4 index 20d04a63f6..9e3a5e11c4 100644 --- a/source/lib/replace/getpass.m4 +++ b/source/lib/replace/getpass.m4 @@ -1,3 +1,11 @@ +AC_CHECK_FUNC(getpass, samba_cv_HAVE_GETPASS=yes) +AC_CHECK_FUNC(getpassphrase, samba_cv_HAVE_GETPASSPHRASE=yes) +if test x"$samba_cv_HAVE_GETPASS" = x"yes" -a x"$samba_cv_HAVE_GETPASSPHRASE" = x"yes"; then + AC_DEFINE(REPLACE_GETPASS_BY_GETPASSPHRASE, 1, [getpass returns <9 chars where getpassphrase returns <265 chars]) + AC_DEFINE(REPLACE_GETPASS,1,[Whether getpass should be replaced]) + LIBREPLACEOBJ="${LIBREPLACEOBJ} getpass.o" +else + AC_CACHE_CHECK([whether getpass should be replaced],samba_cv_REPLACE_GETPASS,[ SAVE_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS -I$libreplacedir/" @@ -15,3 +23,5 @@ if test x"$samba_cv_REPLACE_GETPASS" = x"yes"; then AC_DEFINE(REPLACE_GETPASS,1,[Whether getpass should be replaced]) LIBREPLACEOBJ="${LIBREPLACEOBJ} getpass.o" fi + +fi diff --git a/source/lib/replace/libreplace.m4 b/source/lib/replace/libreplace.m4 index e9b19b7cf5..e430a7f151 100644 --- a/source/lib/replace/libreplace.m4 +++ b/source/lib/replace/libreplace.m4 @@ -99,7 +99,7 @@ AC_CHECK_HEADERS(stdarg.h vararg.h) AC_CHECK_HEADERS(sys/socket.h netinet/in.h netdb.h arpa/inet.h) AC_CHECK_HEADERS(netinet/ip.h netinet/tcp.h netinet/in_systm.h netinet/in_ip.h) AC_CHECK_HEADERS(sys/sockio.h sys/un.h) - +AC_CHECK_HEADERS(stropts.h) dnl we need to check that net/if.h really can be used, to cope with hpux dnl where including it always fails diff --git a/source/lib/replace/system/network.h b/source/lib/replace/system/network.h index 5e648dcd15..94ec132a2e 100644 --- a/source/lib/replace/system/network.h +++ b/source/lib/replace/system/network.h @@ -74,6 +74,10 @@ #include <sys/ioctl.h> #endif +#ifdef HAVE_STROPTS_H +#include <stropts.h> +#endif + #ifdef SOCKET_WRAPPER #ifndef SOCKET_WRAPPER_NOT_REPLACE #define SOCKET_WRAPPER_REPLACE diff --git a/source/lib/system.c b/source/lib/system.c index ac1add8fc1..b23aa04846 100644 --- a/source/lib/system.c +++ b/source/lib/system.c @@ -2161,9 +2161,10 @@ int sys_setxattr (const char *path, const char *name, const void *value, size_t #elif defined(HAVE_ATTROPEN) int ret = -1; int myflags = O_RDWR; + int attrfd; if (flags & XATTR_CREATE) myflags |= O_EXCL; if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT; - int attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE); + attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE); if (attrfd >= 0) { ret = solaris_write_xattr(attrfd, value, size); close(attrfd); @@ -2224,9 +2225,10 @@ int sys_lsetxattr (const char *path, const char *name, const void *value, size_t #elif defined(HAVE_ATTROPEN) int ret = -1; int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW; + int attrfd; if (flags & XATTR_CREATE) myflags |= O_EXCL; if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT; - int attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE); + attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE); if (attrfd >= 0) { ret = solaris_write_xattr(attrfd, value, size); close(attrfd); @@ -2288,9 +2290,10 @@ int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size #elif defined(HAVE_ATTROPEN) int ret = -1; int myflags = O_RDWR | O_XATTR; + int attrfd; if (flags & XATTR_CREATE) myflags |= O_EXCL; if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT; - int attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE); + attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE); if (attrfd >= 0) { ret = solaris_write_xattr(attrfd, value, size); close(attrfd); diff --git a/source/lib/util_str.c b/source/lib/util_str.c index 52cdbfcedd..b734495b83 100644 --- a/source/lib/util_str.c +++ b/source/lib/util_str.c @@ -394,7 +394,11 @@ BOOL strisnormal(const char *s, int case_default) NOTE: oldc and newc must be 7 bit characters **/ -void string_replace( pstring s, char oldc, char newc ) +/** + String replace. + NOTE: oldc and newc must be 7 bit characters +**/ +void string_replace( char *s, char oldc, char newc ) { char *p; @@ -406,8 +410,9 @@ void string_replace( pstring s, char oldc, char newc ) for (p = s; *p; p++) { if (*p & 0x80) /* mb string - slow path. */ break; - if (*p == oldc) + if (*p == oldc) { *p = newc; + } } if (!*p) @@ -418,9 +423,18 @@ void string_replace( pstring s, char oldc, char newc ) /* With compose characters we must restart from the beginning. JRA. */ p = s; #endif - push_ucs2(NULL, tmpbuf, p, sizeof(tmpbuf), STR_TERMINATE); - string_replace_w(tmpbuf, UCS2_CHAR(oldc), UCS2_CHAR(newc)); - pull_ucs2(NULL, p, tmpbuf, -1, sizeof(tmpbuf), STR_TERMINATE); + + while (*p) { + size_t c_size; + next_codepoint(p, &c_size); + + if (c_size == 1) { + if (*p == oldc) { + *p = newc; + } + } + p += c_size; + } } /** diff --git a/source/libads/kerberos.c b/source/libads/kerberos.c index c74c98dd97..089540536c 100644 --- a/source/libads/kerberos.c +++ b/source/libads/kerberos.c @@ -362,6 +362,61 @@ char* kerberos_secrets_fetch_des_salt( void ) return salt; } +/************************************************************************ + Routine to get the default realm from the kerberos credentials cache. + Caller must free if the return value is not NULL. +************************************************************************/ + +char *kerberos_get_default_realm_from_ccache( void ) +{ + char *realm = NULL; + krb5_context ctx = NULL; + krb5_ccache cc = NULL; + krb5_principal princ = NULL; + + initialize_krb5_error_table(); + if (krb5_init_context(&ctx)) { + return NULL; + } + + DEBUG(5,("kerberos_get_default_realm_from_ccache: " + "Trying to read krb5 cache: %s\n", + krb5_cc_default_name(ctx))); + if (krb5_cc_default(ctx, &cc)) { + DEBUG(0,("kerberos_get_default_realm_from_ccache: " + "failed to read default cache\n")); + goto out; + } + if (krb5_cc_get_principal(ctx, cc, &princ)) { + DEBUG(0,("kerberos_get_default_realm_from_ccache: " + "failed to get default principal\n")); + goto out; + } + +#if defined(HAVE_KRB5_PRINCIPAL_GET_REALM) + realm = SMB_STRDUP(krb5_principal_get_realm(ctx, princ)); +#elif defined(HAVE_KRB5_PRINC_REALM) + { + krb5_data *realm_data = krb5_princ_realm(ctx, princ); + realm = SMB_STRNDUP(realm_data->data, realm_data->length); + } +#endif + + out: + + if (princ) { + krb5_free_principal(ctx, princ); + } + if (cc) { + krb5_cc_close(ctx, cc); + } + if (ctx) { + krb5_free_context(ctx); + } + + return realm; +} + /************************************************************************ Routine to get the salting principal for this service. This is @@ -621,11 +676,15 @@ BOOL create_local_private_krb5_conf_for_domain(const char *realm, const char *do TALLOC_FREE(dname); return False; } - - file_contents = talloc_asprintf(fname, "[libdefaults]\n\tdefault_realm = %s\n\n" - "[realms]\n\t%s = {\n" - "\t%s\t}\n", - realm_upper, realm_upper, kdc_ip_string); + + file_contents = talloc_asprintf(fname, + "[libdefaults]\n\tdefault_realm = %s\n" + "default_tgs_enctypes = RC4-HMAC DES-CBC-CRC DES-CBC-MD5\n" + "default_tkt_enctypes = RC4-HMAC DES-CBC-CRC DES-CBC-MD5\n" + "preferred_enctypes = RC4-HMAC DES-CBC-CRC DES-CBC-MD5\n\n" + "[realms]\n\t%s = {\n" + "\t%s\t}\n", + realm_upper, realm_upper, kdc_ip_string); if (!file_contents) { TALLOC_FREE(dname); diff --git a/source/libads/sasl.c b/source/libads/sasl.c index 0067a19d3b..40749be745 100644 --- a/source/libads/sasl.c +++ b/source/libads/sasl.c @@ -137,10 +137,81 @@ static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads) } #ifdef HAVE_KRB5 +struct ads_service_principal { + char *string; +#ifdef HAVE_GSSAPI + gss_name_t name; +#endif +}; + +static void ads_free_service_principal(struct ads_service_principal *p) +{ + SAFE_FREE(p->string); + +#ifdef HAVE_GSSAPI + if (p->name) { + uint32 minor_status; + gss_release_name(&minor_status, &p->name); + } +#endif + ZERO_STRUCTP(p); +} + +static ADS_STATUS ads_generate_service_principal(ADS_STRUCT *ads, + const char *given_principal, + struct ads_service_principal *p) +{ + ADS_STATUS status; +#ifdef HAVE_GSSAPI + gss_buffer_desc input_name; + /* GSS_KRB5_NT_PRINCIPAL_NAME */ + gss_OID_desc nt_principal = + {10, CONST_DISCARD(char *, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01")}; + uint32 minor_status; + int gss_rc; +#endif + + ZERO_STRUCTP(p); + + /* I've seen a child Windows 2000 domain not send + the principal name back in the first round of + the SASL bind reply. So we guess based on server + name and realm. --jerry */ + /* Also try best guess when we get the w2k8 ignore + principal back - gd */ + + if (!given_principal || + strequal(given_principal, ADS_IGNORE_PRINCIPAL)) { + + status = ads_guess_service_principal(ads, &p->string); + if (!ADS_ERR_OK(status)) { + return status; + } + } else { + p->string = SMB_STRDUP(given_principal); + if (!p->string) { + return ADS_ERROR(LDAP_NO_MEMORY); + } + } + +#ifdef HAVE_GSSAPI + input_name.value = p->string; + input_name.length = strlen(p->string); + + gss_rc = gss_import_name(&minor_status, &input_name, &nt_principal, &p->name); + if (gss_rc) { + ads_free_service_principal(p); + return ADS_ERROR_GSS(gss_rc, minor_status); + } +#endif + + return ADS_SUCCESS; +} + /* perform a LDAP/SASL/SPNEGO/KRB5 bind */ -static ADS_STATUS ads_sasl_spnego_krb5_bind(ADS_STRUCT *ads, const char *principal) +static ADS_STATUS ads_sasl_spnego_rawkrb5_bind(ADS_STRUCT *ads, const char *principal) { DATA_BLOB blob = data_blob(NULL, 0); struct berval cred, *scred = NULL; @@ -167,6 +238,13 @@ static ADS_STATUS ads_sasl_spnego_krb5_bind(ADS_STRUCT *ads, const char *princip return ADS_ERROR(rc); } + +static ADS_STATUS ads_sasl_spnego_krb5_bind(ADS_STRUCT *ads, + struct ads_service_principal *p) +{ + return ads_sasl_spnego_rawkrb5_bind(ads, p->string); +} + #endif /* @@ -178,7 +256,7 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads) int rc, i; ADS_STATUS status; DATA_BLOB blob; - char *principal = NULL; + char *given_principal = NULL; char *OIDs[ASN1_MAX_OIDS]; #ifdef HAVE_KRB5 BOOL got_kerberos_mechanism = False; @@ -201,7 +279,7 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads) /* the server sent us the first part of the SPNEGO exchange in the negprot reply */ - if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) { + if (!spnego_parse_negTokenInit(blob, OIDs, &given_principal)) { data_blob_free(&blob); status = ADS_ERROR(LDAP_OPERATIONS_ERROR); goto failed; @@ -219,42 +297,23 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads) #endif free(OIDs[i]); } - DEBUG(3,("ads_sasl_spnego_bind: got server principal name = %s\n", principal)); + DEBUG(3,("ads_sasl_spnego_bind: got server principal name = %s\n", given_principal)); #ifdef HAVE_KRB5 if (!(ads->auth.flags & ADS_AUTH_DISABLE_KERBEROS) && got_kerberos_mechanism) { - /* I've seen a child Windows 2000 domain not send - the principal name back in the first round of - the SASL bind reply. So we guess based on server - name and realm. --jerry */ - if ( !principal ) { - if ( ads->server.realm && ads->server.ldap_server ) { - char *server, *server_realm; - - server = SMB_STRDUP( ads->server.ldap_server ); - server_realm = SMB_STRDUP( ads->server.realm ); - - if ( !server || !server_realm ) - return ADS_ERROR(LDAP_NO_MEMORY); - - strlower_m( server ); - strupper_m( server_realm ); - asprintf( &principal, "ldap/%s@%s", server, server_realm ); - - SAFE_FREE( server ); - SAFE_FREE( server_realm ); - - if ( !principal ) - return ADS_ERROR(LDAP_NO_MEMORY); - } - + struct ads_service_principal p; + + status = ads_generate_service_principal(ads, given_principal, &p); + SAFE_FREE(given_principal); + if (!ADS_ERR_OK(status)) { + return status; } - - status = ads_sasl_spnego_krb5_bind(ads, principal); + + status = ads_sasl_spnego_krb5_bind(ads, &p); if (ADS_ERR_OK(status)) { - SAFE_FREE(principal); + ads_free_service_principal(&p); return status; } @@ -264,19 +323,26 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads) 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, &p); + if (!ADS_ERR_OK(status)) { + DEBUG(0,("kinit succeeded but " + "ads_sasl_spnego_krb5_bind failed: %s\n", + ads_errstr(status))); + } } + ads_free_service_principal(&p); + /* only fallback to NTLMSSP if allowed */ if (ADS_ERR_OK(status) || !(ads->auth.flags & ADS_AUTH_ALLOW_NTLMSSP)) { - SAFE_FREE(principal); return status; } - } + } else #endif - - SAFE_FREE(principal); + { + SAFE_FREE(given_principal); + } /* lets do NTLMSSP ... this has the big advantage that we don't need to sync clocks, and we don't rely on special versions of the krb5 diff --git a/source/libads/util.c b/source/libads/util.c index eb6dccb3af..365f72e7da 100644 --- a/source/libads/util.c +++ b/source/libads/util.c @@ -52,4 +52,61 @@ failed: SAFE_FREE(password); return ret; } + +ADS_STATUS ads_guess_service_principal(ADS_STRUCT *ads, + char **returned_principal) +{ + char *princ = NULL; + + if (ads->server.realm && ads->server.ldap_server) { + char *server, *server_realm; + + server = SMB_STRDUP(ads->server.ldap_server); + server_realm = SMB_STRDUP(ads->server.realm); + + if (!server || !server_realm) { + return ADS_ERROR(LDAP_NO_MEMORY); + } + + strlower_m(server); + strupper_m(server_realm); + asprintf(&princ, "ldap/%s@%s", server, server_realm); + + SAFE_FREE(server); + SAFE_FREE(server_realm); + + if (!princ) { + return ADS_ERROR(LDAP_NO_MEMORY); + } + } else if (ads->config.realm && ads->config.ldap_server_name) { + char *server, *server_realm; + + server = SMB_STRDUP(ads->config.ldap_server_name); + server_realm = SMB_STRDUP(ads->config.realm); + + if (!server || !server_realm) { + return ADS_ERROR(LDAP_NO_MEMORY); + } + + strlower_m(server); + strupper_m(server_realm); + asprintf(&princ, "ldap/%s@%s", server, server_realm); + + SAFE_FREE(server); + SAFE_FREE(server_realm); + + if (!princ) { + return ADS_ERROR(LDAP_NO_MEMORY); + } + } + + if (!princ) { + return ADS_ERROR(LDAP_PARAM_ERROR); + } + + *returned_principal = princ; + + return ADS_SUCCESS; +} + #endif diff --git a/source/libmsrpc/cac_samr.c b/source/libmsrpc/cac_samr.c index 4d3acc85e3..dd9e2c28db 100644 --- a/source/libmsrpc/cac_samr.c +++ b/source/libmsrpc/cac_samr.c @@ -365,9 +365,7 @@ int cac_SamCreateUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx, POLICY_HND *user_out = NULL; uint32 rid_out; - - /**found in rpcclient/cmd_samr.c*/ - uint32 unknown = 0xe005000b; + uint32 acct_flags=0; if ( !hnd ) return CAC_FAILURE; @@ -395,10 +393,16 @@ int cac_SamCreateUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx, return CAC_FAILURE; } + acct_flags = SAMR_GENERIC_READ | SAMR_GENERIC_WRITE | + SAMR_GENERIC_EXECUTE | SAMR_STANDARD_WRITEDAC | + SAMR_STANDARD_DELETE | SAMR_USER_SETPASS | SAMR_USER_GETATTR | + SAMR_USER_SETATTR; + DEBUG(10, ("Creating account with flags: %d\n",acct_flags)); + hnd->status = rpccli_samr_create_dom_user( pipe_hnd, mem_ctx, op->in.dom_hnd, op->in.name, - op->in.acb_mask, unknown, + op->in.acb_mask, acct_flags, user_out, &rid_out ); if ( !NT_STATUS_IS_OK( hnd->status ) ) diff --git a/source/libsmb/cliconnect.c b/source/libsmb/cliconnect.c index d458ce2757..42e0b63511 100644 --- a/source/libsmb/cliconnect.c +++ b/source/libsmb/cliconnect.c @@ -40,6 +40,8 @@ static const struct { {-1,NULL} }; +static const char *star_smbserver_name = "*SMBSERVER"; + /** * Set the user session key for a connection * @param cli The cli structure to add it too @@ -628,7 +630,7 @@ static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char * if (!cli_session_setup_blob(cli, negTokenTarg, session_key_krb5)) { data_blob_free(&negTokenTarg); data_blob_free(&session_key_krb5); - ADS_ERROR_NT(cli_nt_error(cli)); + return ADS_ERROR_NT(cli_nt_error(cli)); } cli_set_session_key(cli, session_key_krb5); @@ -861,10 +863,55 @@ ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user, } } - rc = cli_session_setup_kerberos(cli, principal, domain); - if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) { + /* If we get a bad principal, try to guess it if + we have a valid host NetBIOS name. + */ + if (strequal(principal, ADS_IGNORE_PRINCIPAL)) { SAFE_FREE(principal); - return rc; + } + if (principal == NULL && + !is_ipaddress(cli->desthost) && + !strequal(star_smbserver_name, + cli->desthost)) { + char *realm = NULL; + char *machine = NULL; + char *host = NULL; + DEBUG(3,("cli_session_setup_spnego: got a " + "bad server principal, trying to guess ...\n")); + + host = strchr_m(cli->desthost, '.'); + if (host) { + machine = SMB_STRNDUP(cli->desthost, + host - cli->desthost); + } else { + machine = SMB_STRDUP(cli->desthost); + } + if (machine == NULL) { + return ADS_ERROR_NT(NT_STATUS_NO_MEMORY); + } + + realm = kerberos_get_default_realm_from_ccache(); + if (realm && *realm) { + if (asprintf(&principal, "%s$@%s", + machine, realm) < 0) { + SAFE_FREE(machine); + SAFE_FREE(realm); + return ADS_ERROR_NT(NT_STATUS_NO_MEMORY); + } + DEBUG(3,("cli_session_setup_spnego: guessed " + "server principal=%s\n", + principal ? principal : "<null>")); + } + SAFE_FREE(machine); + SAFE_FREE(realm); + } + + if (principal) { + rc = cli_session_setup_kerberos(cli, principal, domain); + if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) { + SAFE_FREE(principal); + return rc; + } } } #endif @@ -1412,7 +1459,7 @@ NTSTATUS cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip char *p; /* reasonable default hostname */ - if (!host) host = "*SMBSERVER"; + if (!host) host = star_smbserver_name; fstrcpy(cli->desthost, host); @@ -1527,8 +1574,8 @@ again: *p = 0; goto again; } - if (strcmp(called.name, "*SMBSERVER")) { - make_nmb_name(&called , "*SMBSERVER", 0x20); + if (strcmp(called.name, star_smbserver_name)) { + make_nmb_name(&called , star_smbserver_name, 0x20); goto again; } return NT_STATUS_BAD_NETWORK_NAME; @@ -1652,7 +1699,7 @@ BOOL attempt_netbios_session_request(struct cli_state **ppcli, const char *srcho */ if(is_ipaddress(desthost)) { - make_nmb_name(&called, "*SMBSERVER", 0x20); + make_nmb_name(&called, star_smbserver_name, 0x20); } else { make_nmb_name(&called, desthost, 0x20); } @@ -1661,7 +1708,7 @@ BOOL attempt_netbios_session_request(struct cli_state **ppcli, const char *srcho NTSTATUS status; struct nmb_name smbservername; - make_nmb_name(&smbservername , "*SMBSERVER", 0x20); + make_nmb_name(&smbservername, star_smbserver_name, 0x20); /* * If the name wasn't *SMBSERVER then diff --git a/source/libsmb/clierror.c b/source/libsmb/clierror.c index ff6fbf522f..cacfe8221c 100644 --- a/source/libsmb/clierror.c +++ b/source/libsmb/clierror.c @@ -469,3 +469,15 @@ void cli_set_nt_error(struct cli_state *cli, NTSTATUS status) SSVAL(cli->inbuf,smb_flg2, SVAL(cli->inbuf,smb_flg2)|FLAGS2_32_BIT_ERROR_CODES); SIVAL(cli->inbuf, smb_rcls, NT_STATUS_V(status)); } + +/* Reset an error. */ + +void cli_reset_error(struct cli_state *cli) +{ + if (SVAL(cli->inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES) { + SIVAL(cli->inbuf, smb_rcls, NT_STATUS_V(NT_STATUS_OK)); + } else { + SCVAL(cli->inbuf,smb_rcls,0); + SSVAL(cli->inbuf,smb_err,0); + } +} diff --git a/source/libsmb/clikrb5.c b/source/libsmb/clikrb5.c index 6337b50ce9..e7b68921e5 100644 --- a/source/libsmb/clikrb5.c +++ b/source/libsmb/clikrb5.c @@ -336,8 +336,8 @@ BOOL unwrap_pac(TALLOC_CTX *mem_ctx, DATA_BLOB *auth_data, DATA_BLOB *unwrapped_ got_auth_data_pac = unwrap_pac(mem_ctx, &auth_data_wrapped, auth_data); data_blob_free(&auth_data_wrapped); - if (!got_auth_data_pac) { - continue; + if (got_auth_data_pac) { + return true; } } @@ -363,9 +363,9 @@ BOOL unwrap_pac(TALLOC_CTX *mem_ctx, DATA_BLOB *auth_data, DATA_BLOB *unwrapped_ /* check if it is a PAC */ got_auth_data_pac = unwrap_pac(mem_ctx, &auth_data_wrapped, auth_data); data_blob_free(&auth_data_wrapped); - - if (!got_auth_data_pac) { - continue; + + if (got_auth_data_pac) { + return true; } } diff --git a/source/libsmb/clilist.c b/source/libsmb/clilist.c index 3e76cd4775..98c043635f 100644 --- a/source/libsmb/clilist.c +++ b/source/libsmb/clilist.c @@ -247,7 +247,7 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute, &rparam, ¶m_len, &rdata, &data_len) && cli_is_dos_error(cli)) { - /* we need to work around a Win95 bug - sometimes + /* We need to work around a Win95 bug - sometimes it gives ERRSRV/ERRerror temprarily */ uint8 eclass; uint32 ecode; @@ -256,6 +256,20 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute, SAFE_FREE(rparam); cli_dos_error(cli, &eclass, &ecode); + + /* + * OS/2 might return "no more files", + * which just tells us, that searchcount is zero + * in this search. + * Guenter Kukkukk <linux@kukkukk.com> + */ + + if (eclass == ERRDOS && ecode == ERRnofiles) { + ff_searchcount = 0; + cli_reset_error(cli); + break; + } + if (eclass != ERRSRV || ecode != ERRerror) break; smb_msleep(100); diff --git a/source/libsmb/clitrans.c b/source/libsmb/clitrans.c index f212f49994..f43a2aa028 100644 --- a/source/libsmb/clitrans.c +++ b/source/libsmb/clitrans.c @@ -95,14 +95,9 @@ BOOL cli_send_trans(struct cli_state *cli, int trans, return False; } - /* Note we're in a trans state. Save the sequence - * numbers for replies. */ - client_set_trans_sign_state_on(cli, mid); - if (this_ldata < ldata || this_lparam < lparam) { /* receive interim response */ if (!cli_receive_smb(cli) || cli_is_error(cli)) { - client_set_trans_sign_state_off(cli, mid); return(False); } @@ -144,7 +139,6 @@ BOOL cli_send_trans(struct cli_state *cli, int trans, show_msg(cli->outbuf); if (!cli_send_smb(cli)) { - client_set_trans_sign_state_off(cli, mid); return False; } @@ -323,7 +317,6 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans, out: - client_set_trans_sign_state_off(cli, SVAL(cli->inbuf,smb_mid)); return ret; } @@ -391,14 +384,9 @@ BOOL cli_send_nt_trans(struct cli_state *cli, return False; } - /* Note we're in a trans state. Save the sequence - * numbers for replies. */ - client_set_trans_sign_state_on(cli, mid); - if (this_ldata < ldata || this_lparam < lparam) { /* receive interim response */ if (!cli_receive_smb(cli) || cli_is_error(cli)) { - client_set_trans_sign_state_off(cli, mid); return(False); } @@ -440,7 +428,6 @@ BOOL cli_send_nt_trans(struct cli_state *cli, show_msg(cli->outbuf); if (!cli_send_smb(cli)) { - client_set_trans_sign_state_off(cli, mid); return False; } @@ -640,6 +627,5 @@ BOOL cli_receive_nt_trans(struct cli_state *cli, out: - client_set_trans_sign_state_off(cli, SVAL(cli->inbuf,smb_mid)); return ret; } diff --git a/source/libsmb/nmblib.c b/source/libsmb/nmblib.c index 5280dfdbff..641473bea1 100644 --- a/source/libsmb/nmblib.c +++ b/source/libsmb/nmblib.c @@ -702,6 +702,8 @@ struct packet_struct *parse_packet(char *buf,int length, if (!p) return(NULL); + ZERO_STRUCTP(p); /* initialize for possible padding */ + p->next = NULL; p->prev = NULL; p->ip = lastip; diff --git a/source/libsmb/smb_signing.c b/source/libsmb/smb_signing.c index df74b2db36..6768c2accc 100644 --- a/source/libsmb/smb_signing.c +++ b/source/libsmb/smb_signing.c @@ -26,7 +26,6 @@ struct outstanding_packet_lookup { struct outstanding_packet_lookup *prev, *next; uint16 mid; uint32 reply_seq_num; - BOOL can_delete; /* Set to False in trans state. */ }; struct smb_basic_signing_context { @@ -43,7 +42,9 @@ static BOOL store_sequence_for_reply(struct outstanding_packet_lookup **list, /* Ensure we only add a mid once. */ for (t = *list; t; t = t->next) { if (t->mid == mid) { - return False; + DLIST_REMOVE(*list, t); + SAFE_FREE(t); + break; } } @@ -52,7 +53,6 @@ static BOOL store_sequence_for_reply(struct outstanding_packet_lookup **list, t->mid = mid; t->reply_seq_num = reply_seq_num; - t->can_delete = True; /* * Add to the *start* of the list not the end of the list. @@ -79,23 +79,8 @@ static BOOL get_sequence_for_reply(struct outstanding_packet_lookup **list, *reply_seq_num = t->reply_seq_num; DEBUG(10,("get_sequence_for_reply: found seq = %u mid = %u\n", (unsigned int)t->reply_seq_num, (unsigned int)t->mid )); - if (t->can_delete) { - DLIST_REMOVE(*list, t); - SAFE_FREE(t); - } - return True; - } - } - return False; -} - -static BOOL set_sequence_can_delete_flag(struct outstanding_packet_lookup **list, uint16 mid, BOOL can_delete_entry) -{ - struct outstanding_packet_lookup *t; - - for (t = *list; t; t = t->next) { - if (t->mid == mid) { - t->can_delete = can_delete_entry; + DLIST_REMOVE(*list, t); + SAFE_FREE(t); return True; } } @@ -604,60 +589,6 @@ BOOL cli_check_sign_mac(struct cli_state *cli) } /*********************************************************** - Enter trans/trans2/nttrans state. -************************************************************/ - -BOOL client_set_trans_sign_state_on(struct cli_state *cli, uint16 mid) -{ - struct smb_sign_info *si = &cli->sign_info; - struct smb_basic_signing_context *data = (struct smb_basic_signing_context *)si->signing_context; - - if (!si->doing_signing) { - return True; - } - - if (!data) { - return False; - } - - if (!set_sequence_can_delete_flag(&data->outstanding_packet_list, mid, False)) { - return False; - } - - return True; -} - -/*********************************************************** - Leave trans/trans2/nttrans state. -************************************************************/ - -BOOL client_set_trans_sign_state_off(struct cli_state *cli, uint16 mid) -{ - uint32 reply_seq_num; - struct smb_sign_info *si = &cli->sign_info; - struct smb_basic_signing_context *data = (struct smb_basic_signing_context *)si->signing_context; - - if (!si->doing_signing) { - return True; - } - - if (!data) { - return False; - } - - if (!set_sequence_can_delete_flag(&data->outstanding_packet_list, mid, True)) { - return False; - } - - /* Now delete the stored mid entry. */ - if (!get_sequence_for_reply(&data->outstanding_packet_list, mid, &reply_seq_num)) { - return False; - } - - return True; -} - -/*********************************************************** SMB signing - Server implementation - send the MAC. ************************************************************/ diff --git a/source/libsmb/smbencrypt.c b/source/libsmb/smbencrypt.c index 5f7b5b1809..9812cbf67a 100644 --- a/source/libsmb/smbencrypt.c +++ b/source/libsmb/smbencrypt.c @@ -444,7 +444,7 @@ BOOL SMBNTLMv2encrypt_hash(const char *user, const char *domain, const uchar nt_ the username and domain. This prevents username swapping during the auth exchange */ - if (!ntv2_owf_gen(nt_hash, user, domain, True, ntlm_v2_hash)) { + if (!ntv2_owf_gen(nt_hash, user, domain, False, ntlm_v2_hash)) { return False; } diff --git a/source/libsmb/trusts_util.c b/source/libsmb/trusts_util.c index e4061883eb..2580b50054 100644 --- a/source/libsmb/trusts_util.c +++ b/source/libsmb/trusts_util.c @@ -41,7 +41,7 @@ static NTSTATUS just_change_the_password(struct rpc_pipe_client *cli, TALLOC_CTX already have valid creds. If not we must set them up. */ if (cli->auth.auth_type != PIPE_AUTH_TYPE_SCHANNEL) { - uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS; + uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS; result = rpccli_netlogon_setup_creds(cli, cli->cli->desthost, /* server name */ diff --git a/source/libsmb/unexpected.c b/source/libsmb/unexpected.c index 97d6071e71..0e4e03384c 100644 --- a/source/libsmb/unexpected.c +++ b/source/libsmb/unexpected.c @@ -59,6 +59,8 @@ void unexpected_packet(struct packet_struct *p) len = build_packet(buf, p); + ZERO_STRUCT(key); /* needed for potential alignment */ + key.packet_type = p->packet_type; key.timestamp = p->timestamp; key.count = count++; @@ -81,6 +83,10 @@ static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *st { struct unexpected_key key; + if (kbuf.dsize != sizeof(key)) { + tdb_delete(ttdb, kbuf); + } + memcpy(&key, kbuf.dptr, sizeof(key)); if (lastt - key.timestamp > NMBD_UNEXPECTED_TIMEOUT) { @@ -120,6 +126,10 @@ static int traverse_match(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void struct unexpected_key key; struct packet_struct *p; + if (kbuf.dsize != sizeof(key)) { + return 0; + } + memcpy(&key, kbuf.dptr, sizeof(key)); if (key.packet_type != match_type) return 0; diff --git a/source/modules/vfs_default.c b/source/modules/vfs_default.c index 98e9aaa263..4cc6e8856b 100644 --- a/source/modules/vfs_default.c +++ b/source/modules/vfs_default.c @@ -444,7 +444,7 @@ static int vfswrap_rename(vfs_handle_struct *handle, const char *oldname, const START_PROFILE(syscall_rename); result = rename(oldname, newname); - if (errno == EXDEV) { + if ((result == -1) && (errno == EXDEV)) { /* Rename across filesystems needed. */ result = copy_reg(oldname, newname); } diff --git a/source/modules/vfs_hpuxacl.c b/source/modules/vfs_hpuxacl.c index 3885758523..f1e0c5087b 100644 --- a/source/modules/vfs_hpuxacl.c +++ b/source/modules/vfs_hpuxacl.c @@ -141,7 +141,7 @@ SMB_ACL_T hpuxacl_sys_acl_get_file(vfs_handle_struct *handle, { SMB_ACL_T result = NULL; int count; - HPUX_ACL_T hpux_acl; + HPUX_ACL_T hpux_acl = NULL; DEBUG(10, ("hpuxacl_sys_acl_get_file called for file '%s'.\n", path_p)); @@ -215,7 +215,7 @@ int hpuxacl_sys_acl_set_file(vfs_handle_struct *handle, { int ret = -1; SMB_STRUCT_STAT s; - HPUX_ACL_T hpux_acl; + HPUX_ACL_T hpux_acl = NULL; int count; DEBUG(10, ("hpuxacl_sys_acl_set_file called for file '%s'\n", diff --git a/source/modules/vfs_notify_fam.c b/source/modules/vfs_notify_fam.c index b76046b378..1758a9f2bc 100644 --- a/source/modules/vfs_notify_fam.c +++ b/source/modules/vfs_notify_fam.c @@ -156,6 +156,9 @@ static void fam_handler(struct event_context *event_ctx, fam_event.filename)); switch (fam_event.code) { + case FAMChanged: + ne.action = NOTIFY_ACTION_MODIFIED; + break; case FAMCreated: ne.action = NOTIFY_ACTION_ADDED; break; diff --git a/source/nmbd/nmbd.c b/source/nmbd/nmbd.c index 46f209872b..742c747ae5 100644 --- a/source/nmbd/nmbd.c +++ b/source/nmbd/nmbd.c @@ -150,23 +150,30 @@ static void expire_names_and_servers(time_t t) /************************************************************************** ** Reload the list of network interfaces. + Doesn't return until a network interface is up. ************************************************************************** */ -static BOOL reload_interfaces(time_t t) +static void reload_interfaces(time_t t) { static time_t lastt; int n; struct subnet_record *subrec; - if (t && ((t - lastt) < NMBD_INTERFACES_RELOAD)) return False; + if (t && ((t - lastt) < NMBD_INTERFACES_RELOAD)) { + return; + } lastt = t; - if (!interfaces_changed()) return False; + if (!interfaces_changed()) { + return; + } /* the list of probed interfaces has changed, we may need to add/remove some subnets */ load_interfaces(); + try_again: + /* find any interfaces that need adding */ for (n=iface_count() - 1; n >= 0; n--) { struct interface *iface = get_interface(n); @@ -221,15 +228,35 @@ static BOOL reload_interfaces(time_t t) close_subnet(subrec); } } - + rescan_listen_set = True; - /* We need to shutdown if there are no subnets... */ + /* We need to wait if there are no subnets... */ if (FIRST_SUBNET == NULL) { - DEBUG(0,("reload_interfaces: No subnets to listen to. Shutting down...\n")); - return True; + void (*saved_handler)(int); + + DEBUG(0,("reload_interfaces: " + "No subnets to listen to. Waiting..\n")); + + /* + * Whilst we're waiting for an interface, allow SIGTERM to + * cause us to exit. + */ + + saved_handler = CatchSignal( SIGTERM, SIGNAL_CAST SIG_DFL ); + + while (iface_count() == 0) { + sleep(5); + load_interfaces(); + } + + /* + * We got an interface, restore our normal term handler. + */ + + CatchSignal( SIGTERM, SIGNAL_CAST saved_handler ); + goto try_again; } - return False; } /**************************************************************************** ** @@ -267,8 +294,6 @@ static BOOL reload_nmbd_services(BOOL test) /**************************************************************************** ** * React on 'smbcontrol nmbd reload-config' in the same way as to SIGHUP - * We use buf here to return BOOL result to process() when reload_interfaces() - * detects that there are no subnets. **************************************************************************** */ static void msg_reload_nmbd_services(int msg_type, struct process_id src, @@ -278,14 +303,7 @@ static void msg_reload_nmbd_services(int msg_type, struct process_id src, dump_all_namelists(); reload_nmbd_services( True ); reopen_logs(); - - if(buf) { - /* We were called from process() */ - /* If reload_interfaces() returned True */ - /* we need to shutdown if there are no subnets... */ - /* pass this info back to process() */ - *((BOOL*)buf) = reload_interfaces(0); - } + reload_interfaces(0); } static void msg_nmbd_send_packet(int msg_type, struct process_id src, @@ -348,7 +366,6 @@ static void msg_nmbd_send_packet(int msg_type, struct process_id src, static void process(void) { BOOL run_election; - BOOL no_subnets; while( True ) { time_t t = time(NULL); @@ -558,19 +575,16 @@ static void process(void) if(reload_after_sighup) { DEBUG( 0, ( "Got SIGHUP dumping debug info.\n" ) ); msg_reload_nmbd_services(MSG_SMB_CONF_UPDATED, - pid_to_procid(0), (void*) &no_subnets, 0, NULL); - if(no_subnets) - return; + pid_to_procid(0), NULL, 0, NULL); reload_after_sighup = 0; } /* check for new network interfaces */ - if(reload_interfaces(t)) - return; + reload_interfaces(t); /* free up temp memory */ - lp_TALLOC_FREE(); + lp_TALLOC_FREE(); } } diff --git a/source/nmbd/nmbd_namelistdb.c b/source/nmbd/nmbd_namelistdb.c index cda12885ef..a4ad6cfca3 100644 --- a/source/nmbd/nmbd_namelistdb.c +++ b/source/nmbd/nmbd_namelistdb.c @@ -294,7 +294,6 @@ void standard_success_register(struct subnet_record *subrec, ******************************************************************/ void standard_fail_register( struct subnet_record *subrec, - struct response_record *rrec, struct nmb_name *nmbname ) { struct name_record *namerec; diff --git a/source/nmbd/nmbd_nameregister.c b/source/nmbd/nmbd_nameregister.c index 8f2a889254..541d594d82 100644 --- a/source/nmbd/nmbd_nameregister.c +++ b/source/nmbd/nmbd_nameregister.c @@ -153,10 +153,11 @@ static void register_name_response(struct subnet_record *subrec, if( rrec->success_fn) (*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, answer_name, nb_flags, ttl, register_ip); } else { + struct nmb_name qname = *question_name; if( rrec->fail_fn) (*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name); /* Remove the name. */ - standard_fail_register( subrec, rrec, question_name); + standard_fail_register( subrec, &qname); } /* Ensure we don't retry. */ @@ -281,10 +282,11 @@ static void register_name_timeout_response(struct subnet_record *subrec, if( rrec->success_fn) (*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip); } else { + struct nmb_name qname = *question_name; if( rrec->fail_fn) (*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name); /* Remove the name. */ - standard_fail_register( subrec, rrec, question_name); + standard_fail_register( subrec, &qname); } /* Ensure we don't retry. */ diff --git a/source/nmbd/nmbd_packets.c b/source/nmbd/nmbd_packets.c index 1460f7d8cd..97a81fe5e1 100644 --- a/source/nmbd/nmbd_packets.c +++ b/source/nmbd/nmbd_packets.c @@ -1606,6 +1606,8 @@ void retransmit_or_expire_response_records(time_t t) for (subrec = FIRST_SUBNET; subrec; subrec = get_next_subnet_maybe_unicast_or_wins_server(subrec)) { struct response_record *rrec, *nextrrec; + restart: + for (rrec = subrec->responselist; rrec; rrec = nextrrec) { nextrrec = rrec->next; @@ -1644,6 +1646,9 @@ on subnet %s\n", rrec->response_id, inet_ntoa(rrec->packet->ip), subrec->subnet_ no timeout function. */ remove_response_record(subrec, rrec); } + /* We have changed subrec->responselist, + * restart from the beginning of this list. */ + goto restart; } /* !rrec->in_expitation_processing */ } /* rrec->repeat_count > 0 */ } /* rrec->repeat_time <= t */ diff --git a/source/nmbd/nmbd_responserecordsdb.c b/source/nmbd/nmbd_responserecordsdb.c index 367c1f4427..dc16a07ccf 100644 --- a/source/nmbd/nmbd_responserecordsdb.c +++ b/source/nmbd/nmbd_responserecordsdb.c @@ -32,26 +32,12 @@ int num_response_packets = 0; static void add_response_record(struct subnet_record *subrec, struct response_record *rrec) { - struct response_record *rrec2; - num_response_packets++; /* count of total number of packets still around */ DEBUG(4,("add_response_record: adding response record id:%hu to subnet %s. num_records:%d\n", rrec->response_id, subrec->subnet_name, num_response_packets)); - if (!subrec->responselist) { - subrec->responselist = rrec; - rrec->prev = NULL; - rrec->next = NULL; - return; - } - - for (rrec2 = subrec->responselist; rrec2->next; rrec2 = rrec2->next) - ; - - rrec2->next = rrec; - rrec->next = NULL; - rrec->prev = rrec2; + DLIST_ADD_END(subrec->responselist, rrec, struct response_record *); } /*************************************************************************** @@ -61,13 +47,25 @@ static void add_response_record(struct subnet_record *subrec, void remove_response_record(struct subnet_record *subrec, struct response_record *rrec) { - if (rrec->prev) - rrec->prev->next = rrec->next; - if (rrec->next) - rrec->next->prev = rrec->prev; + /* It is possible this can be called twice, + with a rrec pointer that has been freed. So + before we inderect into rrec, search for it + on the responselist first. Bug #3617. JRA. */ + + struct response_record *p = NULL; + + for (p = subrec->responselist; p; p = p->next) { + if (p == rrec) { + break; + } + } + + if (p == NULL) { + /* We didn't find rrec on the list. */ + return; + } - if (subrec->responselist == rrec) - subrec->responselist = rrec->next; + DLIST_REMOVE(subrec->responselist, rrec); if(rrec->userdata) { if(rrec->userdata->free_fn) { diff --git a/source/nsswitch/idmap.c b/source/nsswitch/idmap.c index 9c38f6b5ad..49ed62bfef 100644 --- a/source/nsswitch/idmap.c +++ b/source/nsswitch/idmap.c @@ -367,7 +367,7 @@ NTSTATUS idmap_init(void) /* terminate */ dl[1] = NULL; - dom_list = dl; + dom_list = (const char **)dl; default_domain = dl[0]; } @@ -906,7 +906,7 @@ static NTSTATUS idmap_can_map(const struct id_map *map, if ( (dom = find_idmap_domain_from_sid( map->sid )) == NULL ) { /* huh, couldn't find a suitable domain, * let's just leave it unmapped */ - DEBUG(10, ("Could not find idmap backend for SID %s", + DEBUG(10, ("Could not find idmap backend for SID %s\n", sid_string_static(map->sid))); return NT_STATUS_NO_SUCH_DOMAIN; } diff --git a/source/nsswitch/pam_winbind.c b/source/nsswitch/pam_winbind.c index ec6361e52b..2846e141fd 100644 --- a/source/nsswitch/pam_winbind.c +++ b/source/nsswitch/pam_winbind.c @@ -1028,7 +1028,9 @@ static int winbind_auth_request(pam_handle_t * pamh, request.data.auth.krb5_cc_type[0] = '\0'; request.data.auth.uid = -1; - request.flags = WBFLAG_PAM_INFO3_TEXT | WBFLAG_PAM_CONTACT_TRUSTDOM; + request.flags = WBFLAG_PAM_INFO3_TEXT | + WBFLAG_PAM_GET_PWD_POLICY | + WBFLAG_PAM_CONTACT_TRUSTDOM; if (ctrl & (WINBIND_KRB5_AUTH|WINBIND_CACHED_LOGIN)) { struct passwd *pwd = NULL; diff --git a/source/nsswitch/winbind_nss_config.h b/source/nsswitch/winbind_nss_config.h index c36d4e7232..3722db62d1 100644 --- a/source/nsswitch/winbind_nss_config.h +++ b/source/nsswitch/winbind_nss_config.h @@ -36,9 +36,9 @@ #include "lib/replace/replace.h" #endif -#include "system/passwd.h" #include "system/filesys.h" #include "system/network.h" +#include "system/passwd.h" #include "nsswitch/winbind_nss.h" diff --git a/source/nsswitch/winbindd.c b/source/nsswitch/winbindd.c index 9bbc0f088b..18abdab348 100644 --- a/source/nsswitch/winbindd.c +++ b/source/nsswitch/winbindd.c @@ -541,7 +541,7 @@ static void request_len_recv(void *private_data, BOOL success) if (*(uint32 *)(&state->request) != sizeof(state->request)) { DEBUG(0,("request_len_recv: Invalid request size received: %d (expected %d)\n", - *(uint32 *)(&state->request), sizeof(state->request))); + *(uint32 *)(&state->request), (uint32)sizeof(state->request))); state->finished = True; return; } diff --git a/source/nsswitch/winbindd_async.c b/source/nsswitch/winbindd_async.c index 32d4e66b0a..ad136bdc0d 100644 --- a/source/nsswitch/winbindd_async.c +++ b/source/nsswitch/winbindd_async.c @@ -782,6 +782,12 @@ enum winbindd_result winbindd_dual_lookupsid(struct winbindd_domain *domain, This is the second callback after contacting the forest root ********************************************************************/ +struct lookupname_state { + char *dom_name; + char *name; + void *caller_private_data; +}; + static void lookupname_recv2(TALLOC_CTX *mem_ctx, BOOL success, struct winbindd_response *response, void *c, void *private_data) @@ -790,27 +796,28 @@ static void lookupname_recv2(TALLOC_CTX *mem_ctx, BOOL success, enum lsa_SidType type) = (void (*)(void *, BOOL, const DOM_SID *, enum lsa_SidType))c; DOM_SID sid; + struct lookupname_state *s = talloc_get_type_abort(private_data, struct lookupname_state); if (!success) { DEBUG(5, ("Could not trigger lookup_name\n")); - cont(private_data, False, NULL, SID_NAME_UNKNOWN); + cont(s->caller_private_data, False, NULL, SID_NAME_UNKNOWN); return; } if (response->result != WINBINDD_OK) { DEBUG(5, ("lookup_name returned an error\n")); - cont(private_data, False, NULL, SID_NAME_UNKNOWN); + cont(s->caller_private_data, False, NULL, SID_NAME_UNKNOWN); return; } if (!string_to_sid(&sid, response->data.sid.sid)) { DEBUG(0, ("Could not convert string %s to sid\n", response->data.sid.sid)); - cont(private_data, False, NULL, SID_NAME_UNKNOWN); + cont(s->caller_private_data, False, NULL, SID_NAME_UNKNOWN); return; } - cont(private_data, True, &sid, + cont(s->caller_private_data, True, &sid, (enum lsa_SidType)response->data.sid.type); } @@ -826,36 +833,32 @@ static void lookupname_recv(TALLOC_CTX *mem_ctx, BOOL success, enum lsa_SidType type) = (void (*)(void *, BOOL, const DOM_SID *, enum lsa_SidType))c; DOM_SID sid; + struct lookupname_state *s = talloc_get_type_abort(private_data, struct lookupname_state); if (!success) { DEBUG(5, ("lookupname_recv: lookup_name() failed!\n")); - cont(private_data, False, NULL, SID_NAME_UNKNOWN); + cont(s->caller_private_data, False, NULL, SID_NAME_UNKNOWN); return; } if (response->result != WINBINDD_OK) { /* Try again using the forest root */ struct winbindd_domain *root_domain = find_root_domain(); - struct winbindd_cli_state *state = (struct winbindd_cli_state*)private_data; - struct winbindd_request request; - char *name_domain, *name_account; - + struct winbindd_request request; + if ( !root_domain ) { DEBUG(5,("lookupname_recv: unable to determine forest root\n")); - cont(private_data, False, NULL, SID_NAME_UNKNOWN); + cont(s->caller_private_data, False, NULL, SID_NAME_UNKNOWN); return; } - name_domain = state->request.data.name.dom_name; - name_account = state->request.data.name.name; - ZERO_STRUCT(request); request.cmd = WINBINDD_LOOKUPNAME; - fstrcpy(request.data.name.dom_name, name_domain); - fstrcpy(request.data.name.name, name_account); + fstrcpy(request.data.name.dom_name, s->dom_name); + fstrcpy(request.data.name.name, s->name); do_async_domain(mem_ctx, root_domain, &request, lookupname_recv2, - (void *)cont, private_data); + (void *)cont, s); return; } @@ -863,11 +866,11 @@ static void lookupname_recv(TALLOC_CTX *mem_ctx, BOOL success, if (!string_to_sid(&sid, response->data.sid.sid)) { DEBUG(0, ("Could not convert string %s to sid\n", response->data.sid.sid)); - cont(private_data, False, NULL, SID_NAME_UNKNOWN); + cont(s->caller_private_data, False, NULL, SID_NAME_UNKNOWN); return; } - cont(private_data, True, &sid, + cont(s->caller_private_data, True, &sid, (enum lsa_SidType)response->data.sid.type); } @@ -886,6 +889,7 @@ void winbindd_lookupname_async(TALLOC_CTX *mem_ctx, { struct winbindd_request request; struct winbindd_domain *domain; + struct lookupname_state *s; if ( (domain = find_lookup_domain_from_name(dom_name)) == NULL ) { DEBUG(5, ("Could not find domain for name %s\n", dom_name)); @@ -898,8 +902,23 @@ void winbindd_lookupname_async(TALLOC_CTX *mem_ctx, fstrcpy(request.data.name.dom_name, dom_name); fstrcpy(request.data.name.name, name); + if ( (s = TALLOC_ZERO_P(mem_ctx, struct lookupname_state)) == NULL ) { + DEBUG(0, ("winbindd_lookupname_async: talloc failed\n")); + cont(private_data, False, NULL, SID_NAME_UNKNOWN); + return; + } + + s->dom_name = talloc_strdup( s, dom_name ); + s->name = talloc_strdup( s, name ); + if (!s->dom_name || !s->name) { + cont(private_data, False, NULL, SID_NAME_UNKNOWN); + return; + } + + s->caller_private_data = private_data; + do_async_domain(mem_ctx, domain, &request, lookupname_recv, - (void *)cont, private_data); + (void *)cont, s); } enum winbindd_result winbindd_dual_lookupname(struct winbindd_domain *domain, diff --git a/source/nsswitch/winbindd_cm.c b/source/nsswitch/winbindd_cm.c index 9fa1ef1626..14c3fc1fde 100644 --- a/source/nsswitch/winbindd_cm.c +++ b/source/nsswitch/winbindd_cm.c @@ -585,6 +585,44 @@ static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain, return True; } +/** + * Helper function to assemble trust password and account name + */ +static NTSTATUS get_trust_creds(const struct winbindd_domain *domain, + char **machine_password, + char **machine_account, + char **machine_krb5_principal) +{ + const char *account_name; + + if (!get_trust_pw_clear(domain->name, machine_password, + &account_name, NULL)) + { + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } + + if ((machine_account != NULL) && + (asprintf(machine_account, "%s$", account_name) == -1)) + { + return NT_STATUS_NO_MEMORY; + } + + /* this is at least correct when domain is our domain, + * which is the only case, when this is currently used: */ + if (machine_krb5_principal != NULL) + { + if (asprintf(machine_krb5_principal, "%s$@%s", + account_name, domain->alt_name) == -1) + { + return NT_STATUS_NO_MEMORY; + } + + strupper_m(*machine_krb5_principal); + } + + return NT_STATUS_OK; +} + /************************************************************************ Given a fd with a just-connected TCP connection to a DC, open a connection to the pipe. @@ -596,8 +634,12 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, struct cli_state **cli, BOOL *retry) { - char *machine_password, *machine_krb5_principal, *machine_account; - char *ipc_username, *ipc_domain, *ipc_password; + char *machine_password = NULL; + char *machine_krb5_principal = NULL; + char *machine_account = NULL; + char *ipc_username = NULL; + char *ipc_domain = NULL; + char *ipc_password = NULL; BOOL got_mutex; @@ -611,23 +653,6 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n", controller, domain->name )); - machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL, - NULL); - - if (asprintf(&machine_account, "%s$", global_myname()) == -1) { - SAFE_FREE(machine_password); - return NT_STATUS_NO_MEMORY; - } - - if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(), - lp_realm()) == -1) { - SAFE_FREE(machine_account); - SAFE_FREE(machine_password); - return NT_STATUS_NO_MEMORY; - } - - cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password); - *retry = True; got_mutex = secrets_named_mutex(controller, @@ -684,10 +709,20 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, result = NT_STATUS_UNSUCCESSFUL; goto done; } - - if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) { + + if (!is_trusted_domain_situation(domain->name) && + (*cli)->protocol >= PROTOCOL_NT1 && + (*cli)->capabilities & CAP_EXTENDED_SECURITY) + { ADS_STATUS ads_status; + result = get_trust_creds(domain, &machine_password, + &machine_account, + &machine_krb5_principal); + if (!NT_STATUS_IS_OK(result)) { + goto done; + } + if (lp_security() == SEC_ADS) { /* Try a krb5 session */ @@ -700,7 +735,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, ads_status = cli_session_setup_spnego(*cli, machine_krb5_principal, machine_password, - lp_workgroup()); + domain->name); if (!ADS_ERR_OK(ads_status)) { DEBUG(4,("failed kerberos session setup with %s\n", @@ -710,7 +745,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, result = ads_ntstatus(ads_status); if (NT_STATUS_IS_OK(result)) { /* Ensure creds are stored for NTLMSSP authenticated pipe access. */ - cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password); + cli_init_creds(*cli, machine_account, domain->name, machine_password); goto session_setup_done; } } @@ -720,12 +755,12 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, DEBUG(5, ("connecting to %s from %s with username " "[%s]\\[%s]\n", controller, global_myname(), - lp_workgroup(), machine_account)); + domain->name, machine_account)); ads_status = cli_session_setup_spnego(*cli, machine_account, machine_password, - lp_workgroup()); + domain->name); if (!ADS_ERR_OK(ads_status)) { DEBUG(4, ("authenticated session setup failed with %s\n", ads_errstr(ads_status))); @@ -734,15 +769,17 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, result = ads_ntstatus(ads_status); if (NT_STATUS_IS_OK(result)) { /* Ensure creds are stored for NTLMSSP authenticated pipe access. */ - cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password); + cli_init_creds(*cli, machine_account, domain->name, machine_password); goto session_setup_done; } } - /* Fall back to non-kerberos session setup */ + /* Fall back to non-kerberos session setup with auth_user */ (*cli)->use_kerberos = False; + cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password); + if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) && (strlen(ipc_username) > 0)) { @@ -907,13 +944,22 @@ static BOOL send_getdc_request(struct in_addr dc_ip, SIVAL(p, 0, 0); /* The sender's token ... */ p += 2; - p += dos_PutUniCode(p, global_myname(), sizeof(pstring), True); + p += dos_PutUniCode(p, global_myname(), + sizeof(outbuf) - PTR_DIFF(p, outbuf), True); fstr_sprintf(my_acct_name, "%s$", global_myname()); - p += dos_PutUniCode(p, my_acct_name, sizeof(pstring), True); + p += dos_PutUniCode(p, my_acct_name, + sizeof(outbuf) - PTR_DIFF(p, outbuf), True); + + if (strlen(my_mailslot)+1 > sizeof(outbuf) - PTR_DIFF(p, outbuf)) { + return False; + } memcpy(p, my_mailslot, strlen(my_mailslot)+1); p += strlen(my_mailslot)+1; + if (sizeof(outbuf) - PTR_DIFF(p, outbuf) < 8) { + return False; + } SIVAL(p, 0, 0x80); p+=4; @@ -922,7 +968,15 @@ static BOOL send_getdc_request(struct in_addr dc_ip, p = ALIGN4(p, outbuf); - sid_linearize(p, sid_size(sid), sid); + if (PTR_DIFF(p, outbuf) > sizeof(outbuf)) { + return False; + } + + if (sid_size(sid) + 8 > sizeof(outbuf) - PTR_DIFF(p, outbuf)) { + return False; + } + + sid_linearize(p, sizeof(outbuf) - PTR_DIFF(p, outbuf), sid); p += sid_size(sid); SIVAL(p, 0, 1); @@ -1689,6 +1743,9 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, NTSTATUS result = NT_STATUS_UNSUCCESSFUL; fstring conn_pwd; struct dcinfo *p_dcinfo; + char *machine_password = NULL; + char *machine_account = NULL; + char *domain_name = NULL; result = init_dc_connection(domain); if (!NT_STATUS_IS_OK(result)) { @@ -1711,10 +1768,25 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, pwd_get_cleartext(&conn->cli->pwd, conn_pwd); if ((conn->cli->user_name[0] == '\0') || (conn->cli->domain[0] == '\0') || - (conn_pwd[0] == '\0')) { - DEBUG(10, ("cm_connect_sam: No no user available for " - "domain %s, trying schannel\n", conn->cli->domain)); - goto schannel; + (conn_pwd[0] == '\0')) + { + result = get_trust_creds(domain, &machine_password, + &machine_account, NULL); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10, ("cm_connect_sam: No no user available for " + "domain %s, trying schannel\n", conn->cli->domain)); + goto schannel; + } + domain_name = domain->name; + } else { + machine_password = SMB_STRDUP(conn_pwd); + machine_account = SMB_STRDUP(conn->cli->user_name); + domain_name = conn->cli->domain; + } + + if (!machine_password || !machine_account) { + result = NT_STATUS_NO_MEMORY; + goto done; } /* We have an authenticated connection. Use a NTLMSSP SPNEGO @@ -1722,23 +1794,23 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, conn->samr_pipe = cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY, - conn->cli->domain, - conn->cli->user_name, - conn_pwd, &result); + domain_name, + machine_account, + machine_password, &result); if (conn->samr_pipe == NULL) { DEBUG(10,("cm_connect_sam: failed to connect to SAMR " "pipe for domain %s using NTLMSSP " "authenticated pipe: user %s\\%s. Error was " - "%s\n", domain->name, conn->cli->domain, - conn->cli->user_name, nt_errstr(result))); + "%s\n", domain->name, domain_name, + machine_account, nt_errstr(result))); goto schannel; } DEBUG(10,("cm_connect_sam: connected to SAMR pipe for " "domain %s using NTLMSSP authenticated " "pipe: user %s\\%s\n", domain->name, - conn->cli->domain, conn->cli->user_name )); + domain_name, machine_account)); result = rpccli_samr_connect(conn->samr_pipe, mem_ctx, SEC_RIGHTS_MAXIMUM_ALLOWED, @@ -1823,6 +1895,8 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, *cli = conn->samr_pipe; *sam_handle = conn->sam_domain_handle; + SAFE_FREE(machine_password); + SAFE_FREE(machine_account); return result; } @@ -1953,7 +2027,7 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, struct winbindd_cm_conn *conn; NTSTATUS result; - uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS; + uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS; uint8 mach_pwd[16]; uint32 sec_chan_type; const char *account_name; @@ -1973,36 +2047,27 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, return NT_STATUS_OK; } - if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) { - return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - } - netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON, &result); if (netlogon_pipe == NULL) { return result; } + if ((!IS_DC) && (!domain->primary)) { + /* Clear the schannel request bit and drop down */ + neg_flags &= ~NETLOGON_NEG_SCHANNEL; + goto no_schannel; + } + if (lp_client_schannel() != False) { neg_flags |= NETLOGON_NEG_SCHANNEL; } - /* if we are a DC and this is a trusted domain, then we need to use our - domain name in the net_req_auth2() request */ - - if ( IS_DC - && !strequal(domain->name, lp_workgroup()) - && lp_allow_trusted_domains() ) + if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name, + &sec_chan_type)) { - account_name = lp_workgroup(); - } else { - account_name = domain->primary ? - global_myname() : domain->name; - } - - if (account_name == NULL) { cli_rpc_pipe_close(netlogon_pipe); - return NT_STATUS_NO_MEMORY; + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } result = rpccli_netlogon_setup_creds( @@ -2027,6 +2092,7 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, return NT_STATUS_ACCESS_DENIED; } + no_schannel: if ((lp_client_schannel() == False) || ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) { /* We're done - just keep the existing connection to NETLOGON diff --git a/source/nsswitch/winbindd_cred_cache.c b/source/nsswitch/winbindd_cred_cache.c index 368090c390..e47858b628 100644 --- a/source/nsswitch/winbindd_cred_cache.c +++ b/source/nsswitch/winbindd_cred_cache.c @@ -426,7 +426,7 @@ NTSTATUS add_ccache_to_list(const char *princ_name, NTSTATUS remove_ccache(const char *username) { struct WINBINDD_CCACHE_ENTRY *entry = get_ccache_by_username(username); - NTSTATUS status; + NTSTATUS status = NT_STATUS_OK; #ifdef HAVE_KRB5 krb5_error_code ret; #endif diff --git a/source/nsswitch/winbindd_dual.c b/source/nsswitch/winbindd_dual.c index ffbedfa9bf..fa6add3aab 100644 --- a/source/nsswitch/winbindd_dual.c +++ b/source/nsswitch/winbindd_dual.c @@ -35,6 +35,7 @@ #define DBGC_CLASS DBGC_WINBIND extern BOOL override_logfile; +extern struct winbindd_methods cache_methods; /* Read some data from a client connection */ @@ -988,6 +989,16 @@ static BOOL fork_domain_child(struct winbindd_child *child) child); } + /* Special case for Winbindd on a Samba DC, + * We want to make sure the child can connect to smbd + * but not the main daemon */ + + if (child->domain && child->domain->internal && IS_DC) { + child->domain->internal = False; + child->domain->methods = &cache_methods; + child->domain->online = False; + } + while (1) { int ret; diff --git a/source/nsswitch/winbindd_nss.h b/source/nsswitch/winbindd_nss.h index 135849ae8f..8f22e158f5 100644 --- a/source/nsswitch/winbindd_nss.h +++ b/source/nsswitch/winbindd_nss.h @@ -206,7 +206,7 @@ typedef struct winbindd_gr { #define WBFLAG_PAM_KRB5 0x1000 #define WBFLAG_PAM_FALLBACK_AFTER_KRB5 0x2000 #define WBFLAG_PAM_CACHED_LOGIN 0x4000 -#define WBFLAG_PAM_GET_PWD_POLICY 0x8000 /* not used */ +#define WBFLAG_PAM_GET_PWD_POLICY 0x8000 #define WINBINDD_MAX_EXTRA_DATA (128*1024) diff --git a/source/nsswitch/winbindd_pam.c b/source/nsswitch/winbindd_pam.c index 589f4839e0..e5e55e60f9 100644 --- a/source/nsswitch/winbindd_pam.c +++ b/source/nsswitch/winbindd_pam.c @@ -1517,11 +1517,13 @@ process_result: } } - result = fillup_password_policy(domain, state); + if (state->request.flags & WBFLAG_PAM_GET_PWD_POLICY) { + result = fillup_password_policy(domain, state); - if (!NT_STATUS_IS_OK(result)) { - DEBUG(10,("Failed to get password policies: %s\n", nt_errstr(result))); - goto done; + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10,("Failed to get password policies: %s\n", nt_errstr(result))); + goto done; + } } if (state->request.flags & WBFLAG_PAM_UNIX_NAME) { diff --git a/source/nsswitch/winbindd_util.c b/source/nsswitch/winbindd_util.c index d2daf7830d..ecd919d6ff 100644 --- a/source/nsswitch/winbindd_util.c +++ b/source/nsswitch/winbindd_util.c @@ -83,9 +83,6 @@ static BOOL is_internal_domain(const DOM_SID *sid) if (sid == NULL) return False; - if ( IS_DC ) - return sid_check_is_builtin(sid); - return (sid_check_is_domain(sid) || sid_check_is_builtin(sid)); } @@ -94,9 +91,6 @@ static BOOL is_in_internal_domain(const DOM_SID *sid) if (sid == NULL) return False; - if ( IS_DC ) - return sid_check_is_in_builtin(sid); - return (sid_check_is_in_our_domain(sid) || sid_check_is_in_builtin(sid)); } diff --git a/source/pam_smbpass/pam_smb_acct.c b/source/pam_smbpass/pam_smb_acct.c index 47bf059479..b5dbd9ca6c 100644 --- a/source/pam_smbpass/pam_smb_acct.c +++ b/source/pam_smbpass/pam_smb_acct.c @@ -70,6 +70,11 @@ int pam_sm_acct_mgmt( pam_handle_t *pamh, int flags, _log_err( LOG_DEBUG, "acct: username [%s] obtained", name ); } + if (geteuid() != 0) { + _log_err(pamh, LOG_DEBUG, "Cannot access samba password database, not running as root."); + return PAM_AUTHINFO_UNAVAIL; + } + /* Getting into places that might use LDAP -- protect the app from a SIGPIPE it's not expecting */ oldsig_handler = CatchSignal(SIGPIPE, SIGNAL_CAST SIG_IGN); diff --git a/source/pam_smbpass/pam_smb_auth.c b/source/pam_smbpass/pam_smb_auth.c index df6d20e01a..2b0735f2fb 100644 --- a/source/pam_smbpass/pam_smb_auth.c +++ b/source/pam_smbpass/pam_smb_auth.c @@ -101,6 +101,12 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, _log_err( LOG_DEBUG, "username [%s] obtained", name ); } + if (geteuid() != 0) { + _log_err(pamh, LOG_DEBUG, "Cannot access samba password database, not running as root."); + retval = PAM_AUTHINFO_UNAVAIL; + AUTH_RETURN; + } + if (!initialize_password_db(True)) { _log_err( LOG_ALERT, "Cannot access samba password database" ); retval = PAM_AUTHINFO_UNAVAIL; diff --git a/source/pam_smbpass/pam_smb_passwd.c b/source/pam_smbpass/pam_smb_passwd.c index 79bcfb6ff0..62c056ba01 100644 --- a/source/pam_smbpass/pam_smb_passwd.c +++ b/source/pam_smbpass/pam_smb_passwd.c @@ -125,6 +125,11 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, _log_err( LOG_DEBUG, "username [%s] obtained", user ); } + if (geteuid() != 0) { + _log_err(pamh, LOG_DEBUG, "Cannot access samba password database, not running as root."); + return PAM_AUTHINFO_UNAVAIL; + } + /* Getting into places that might use LDAP -- protect the app from a SIGPIPE it's not expecting */ oldsig_handler = CatchSignal(SIGPIPE, SIGNAL_CAST SIG_IGN); diff --git a/source/param/loadparm.c b/source/param/loadparm.c index be49927cc6..4f44088c8f 100644 --- a/source/param/loadparm.c +++ b/source/param/loadparm.c @@ -237,6 +237,8 @@ typedef struct { int ldap_ssl; char *szLdapSuffix; char *szLdapAdminDn; + int ldap_debug_level; + int ldap_debug_threshold; int iAclCompat; char *szCupsServer; char *szIPrintServer; @@ -403,6 +405,7 @@ typedef struct { BOOL bRead_only; BOOL bNo_set_dir; BOOL bGuest_only; + BOOL bAdministrative_share; BOOL bGuest_ok; BOOL bPrint_ok; BOOL bMap_system; @@ -545,6 +548,7 @@ static service sDefault = { True, /* bRead_only */ True, /* bNo_set_dir */ False, /* bGuest_only */ + False, /* bAdministrative_share */ False, /* bGuest_ok */ False, /* bPrint_ok */ False, /* bMap_system */ @@ -634,6 +638,7 @@ static BOOL handle_netbios_aliases( int snum, const char *pszParmValue, char **p static BOOL handle_netbios_scope( int snum, const char *pszParmValue, char **ptr ); static BOOL handle_charset( int snum, const char *pszParmValue, char **ptr ); static BOOL handle_printing( int snum, const char *pszParmValue, char **ptr); +static BOOL handle_ldap_debug_level( int snum, const char *pszParmValue, char **ptr); static void set_server_role(void); static void set_default_server_announce_type(void); @@ -935,6 +940,7 @@ static struct parm_struct parm_table[] = { {"inherit owner", P_BOOL, P_LOCAL, &sDefault.bInheritOwner, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, {"guest only", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, {"only guest", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL, NULL, FLAG_HIDE}, + {"administrative share", P_BOOL, P_LOCAL, &sDefault.bAdministrative_share, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, {"guest ok", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, {"public", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL, NULL, FLAG_HIDE}, @@ -1189,6 +1195,10 @@ static struct parm_struct parm_table[] = { {"ldap page size", P_INTEGER, P_GLOBAL, &Globals.ldap_page_size, NULL, NULL, FLAG_ADVANCED}, {"ldap user suffix", P_STRING, P_GLOBAL, &Globals.szLdapUserSuffix, NULL, NULL, FLAG_ADVANCED}, + {"ldap debug level", P_INTEGER, P_GLOBAL, &Globals.ldap_debug_level, handle_ldap_debug_level, NULL, FLAG_ADVANCED}, + {"ldap debug threshold", P_INTEGER, P_GLOBAL, &Globals.ldap_debug_threshold, NULL, NULL, FLAG_ADVANCED}, + + {N_("Miscellaneous Options"), P_SEP, P_SEPARATOR}, {"add share command", P_STRING, P_GLOBAL, &Globals.szAddShareCommand, NULL, NULL, FLAG_ADVANCED}, {"change share command", P_STRING, P_GLOBAL, &Globals.szChangeShareCommand, NULL, NULL, FLAG_ADVANCED}, @@ -1592,6 +1602,9 @@ static void init_globals(BOOL first_time_only) Globals.ldap_timeout = LDAP_CONNECT_DEFAULT_TIMEOUT; Globals.ldap_page_size = LDAP_PAGE_SIZE; + Globals.ldap_debug_level = 0; + Globals.ldap_debug_threshold = 10; + /* This is what we tell the afs client. in reality we set the token * to never expire, though, when this runs out the afs client will * forget the token. Set to 0 to get NEVERDATE.*/ @@ -1918,6 +1931,8 @@ FN_GLOBAL_BOOL(lp_ldap_delete_dn, &Globals.ldap_delete_dn) FN_GLOBAL_INTEGER(lp_ldap_replication_sleep, &Globals.ldap_replication_sleep) FN_GLOBAL_INTEGER(lp_ldap_timeout, &Globals.ldap_timeout) FN_GLOBAL_INTEGER(lp_ldap_page_size, &Globals.ldap_page_size) +FN_GLOBAL_INTEGER(lp_ldap_debug_level, &Globals.ldap_debug_level) +FN_GLOBAL_INTEGER(lp_ldap_debug_threshold, &Globals.ldap_debug_threshold) FN_GLOBAL_STRING(lp_add_share_cmd, &Globals.szAddShareCommand) FN_GLOBAL_STRING(lp_change_share_cmd, &Globals.szChangeShareCommand) FN_GLOBAL_STRING(lp_delete_share_cmd, &Globals.szDeleteShareCommand) @@ -2081,6 +2096,7 @@ FN_LOCAL_BOOL(lp_readonly, bRead_only) FN_LOCAL_BOOL(lp_no_set_dir, bNo_set_dir) FN_LOCAL_BOOL(lp_guest_ok, bGuest_ok) FN_LOCAL_BOOL(lp_guest_only, bGuest_only) +FN_LOCAL_BOOL(lp_administrative_share, bAdministrative_share) FN_LOCAL_BOOL(lp_print_ok, bPrint_ok) FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden) FN_LOCAL_BOOL(lp_map_archive, bMap_archive) @@ -2701,6 +2717,7 @@ static BOOL lp_add_ipc(const char *ipc_name, BOOL guest_ok) ServicePtrs[i]->bAvailable = True; ServicePtrs[i]->bRead_only = True; ServicePtrs[i]->bGuest_only = False; + ServicePtrs[i]->bAdministrative_share = True; ServicePtrs[i]->bGuest_ok = guest_ok; ServicePtrs[i]->bPrint_ok = False; ServicePtrs[i]->bBrowseable = sDefault.bBrowseable; @@ -3227,6 +3244,13 @@ static BOOL handle_copy(int snum, const char *pszParmValue, char **ptr) return (bRetval); } +static BOOL handle_ldap_debug_level(int snum, const char *pszParmValue, char **ptr) +{ + Globals.ldap_debug_level = lp_int(pszParmValue); + init_ldap_debugging(); + return True; +} + /*************************************************************************** Handle idmap/non unix account uid and gid allocation parameters. The format of these parameters is: diff --git a/source/passdb/lookup_sid.c b/source/passdb/lookup_sid.c index 37285f01d2..d1390fdadb 100644 --- a/source/passdb/lookup_sid.c +++ b/source/passdb/lookup_sid.c @@ -60,16 +60,19 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx, name = talloc_strdup(tmp_ctx, full_name); } - DEBUG(10,("lookup_name: %s => %s (domain), %s (name)\n", - full_name, domain, name)); - if ((domain == NULL) || (name == NULL)) { DEBUG(0, ("talloc failed\n")); TALLOC_FREE(tmp_ctx); return False; } - if (strequal(domain, get_global_sam_name())) { + DEBUG(10,("lookup_name: %s => %s (domain), %s (name)\n", + full_name, domain, name)); + DEBUG(10, ("lookup_name: flags = 0x0%x\n", flags)); + + if ((flags & LOOKUP_NAME_DOMAIN) && + strequal(domain, get_global_sam_name())) + { /* It's our own domain, lookup the name in passdb */ if (lookup_global_sam_name(name, flags, &rid, &type)) { @@ -81,8 +84,9 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx, return False; } - if (strequal(domain, builtin_domain_name())) { - + if ((flags & LOOKUP_NAME_BUILTIN) && + strequal(domain, builtin_domain_name())) + { /* Explicit request for a name in BUILTIN */ if (lookup_builtin_name(name, &rid)) { sid_copy(&sid, &global_sid_Builtin); @@ -98,6 +102,7 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx, * domain yet at this point yet. This comes later. */ if ((domain[0] != '\0') && + (flags & ~(LOOKUP_NAME_DOMAIN|LOOKUP_NAME_ISOLATED)) && (winbind_lookup_name(domain, name, &sid, &type))) { goto ok; } @@ -132,14 +137,18 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx, /* 1. well-known names */ - if (lookup_wellknown_name(tmp_ctx, name, &sid, &domain)) { + if ((flags & LOOKUP_NAME_WKN) && + lookup_wellknown_name(tmp_ctx, name, &sid, &domain)) + { type = SID_NAME_WKN_GRP; goto ok; } /* 2. Builtin domain as such */ - if (strequal(name, builtin_domain_name())) { + if ((flags & (LOOKUP_NAME_BUILTIN|LOOKUP_NAME_REMOTE)) && + strequal(name, builtin_domain_name())) + { /* Swap domain and name */ tmp = name; name = domain; domain = tmp; sid_copy(&sid, &global_sid_Builtin); @@ -149,7 +158,9 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx, /* 3. Account domain */ - if (strequal(name, get_global_sam_name())) { + if ((flags & LOOKUP_NAME_DOMAIN) && + strequal(name, get_global_sam_name())) + { if (!secrets_fetch_domain_sid(name, &sid)) { DEBUG(3, ("Could not fetch my SID\n")); TALLOC_FREE(tmp_ctx); @@ -163,7 +174,9 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx, /* 4. Primary domain */ - if (!IS_DC && strequal(name, lp_workgroup())) { + if ((flags & LOOKUP_NAME_DOMAIN) && !IS_DC && + strequal(name, lp_workgroup())) + { if (!secrets_fetch_domain_sid(name, &sid)) { DEBUG(3, ("Could not fetch the domain SID\n")); TALLOC_FREE(tmp_ctx); @@ -178,8 +191,9 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx, /* 5. Trusted domains as such, to me it looks as if members don't do this, tested an XP workstation in a NT domain -- vl */ - if (IS_DC && (secrets_fetch_trusted_domain_password(name, NULL, - &sid, NULL))) { + if ((flags & LOOKUP_NAME_REMOTE) && IS_DC && + (secrets_fetch_trusted_domain_password(name, NULL, &sid, NULL))) + { /* Swap domain and name */ tmp = name; name = domain; domain = tmp; type = SID_NAME_DOMAIN; @@ -188,7 +202,9 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx, /* 6. Builtin aliases */ - if (lookup_builtin_name(name, &rid)) { + if ((flags & LOOKUP_NAME_BUILTIN) && + lookup_builtin_name(name, &rid)) + { domain = talloc_strdup(tmp_ctx, builtin_domain_name()); sid_copy(&sid, &global_sid_Builtin); sid_append_rid(&sid, rid); @@ -201,7 +217,9 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx, /* Both cases are done by looking at our passdb */ - if (lookup_global_sam_name(name, flags, &rid, &type)) { + if ((flags & LOOKUP_NAME_DOMAIN) && + lookup_global_sam_name(name, flags, &rid, &type)) + { domain = talloc_strdup(tmp_ctx, get_global_sam_name()); sid_copy(&sid, get_global_sam_sid()); sid_append_rid(&sid, rid); diff --git a/source/passdb/pdb_ldap.c b/source/passdb/pdb_ldap.c index afcb463a63..8c6fa81edb 100644 --- a/source/passdb/pdb_ldap.c +++ b/source/passdb/pdb_ldap.c @@ -1651,6 +1651,10 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods, pdb_get_username(newpwd), ldap_err2string(rc), ld_error?ld_error:"unknown")); SAFE_FREE(ld_error); ber_bvfree(bv); +#if defined(LDAP_CONSTRAINT_VIOLATION) + if (rc == LDAP_CONSTRAINT_VIOLATION) + return NT_STATUS_PASSWORD_RESTRICTION; +#endif return NT_STATUS_UNSUCCESSFUL; } else { DEBUG(3,("ldapsam_modify_entry: LDAP Password changed for user %s\n",pdb_get_username(newpwd))); @@ -2454,7 +2458,7 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods, goto done; } - rc = smbldap_search(conn, lp_ldap_user_suffix(), + rc = smbldap_search(conn, lp_ldap_suffix(), LDAP_SCOPE_SUBTREE, filter, sid_attrs, 0, &result); @@ -2510,7 +2514,7 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods, LDAP_OBJ_SAMBASAMACCOUNT, gidstr); - rc = smbldap_search(conn, lp_ldap_user_suffix(), + rc = smbldap_search(conn, lp_ldap_suffix(), LDAP_SCOPE_SUBTREE, filter, sid_attrs, 0, &result); @@ -2594,7 +2598,7 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods, goto done; } - rc = smbldap_search(conn, lp_ldap_user_suffix(), + rc = smbldap_search(conn, lp_ldap_suffix(), LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result); if (rc != LDAP_SUCCESS) diff --git a/source/passdb/secrets.c b/source/passdb/secrets.c index 3ac3a93233..cd6c751979 100644 --- a/source/passdb/secrets.c +++ b/source/passdb/secrets.c @@ -268,27 +268,19 @@ uint32 get_default_sec_channel(void) /************************************************************************ Routine to get the trust account password for a domain. + This only tries to get the legacy hashed version of the password. The user of this function must have locked the trust password file using the above secrets_lock_trust_account_password(). ************************************************************************/ -BOOL secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16], - time_t *pass_last_set_time, - uint32 *channel) +BOOL secrets_fetch_trust_account_password_legacy(const char *domain, + uint8 ret_pwd[16], + time_t *pass_last_set_time, + uint32 *channel) { struct machine_acct_pass *pass; - char *plaintext; size_t size = 0; - plaintext = secrets_fetch_machine_password(domain, pass_last_set_time, - channel); - if (plaintext) { - DEBUG(4,("Using cleartext machine password\n")); - E_md4hash(plaintext, ret_pwd); - SAFE_FREE(plaintext); - return True; - } - if (!(pass = (struct machine_acct_pass *)secrets_fetch( trust_keystr(domain), &size))) { DEBUG(5, ("secrets_fetch failed!\n")); @@ -321,6 +313,32 @@ BOOL secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16], return True; } +/************************************************************************ + Routine to get the trust account password for a domain. + The user of this function must have locked the trust password file using + the above secrets_lock_trust_account_password(). +************************************************************************/ + +BOOL secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16], + time_t *pass_last_set_time, + uint32 *channel) +{ + char *plaintext; + + plaintext = secrets_fetch_machine_password(domain, pass_last_set_time, + channel); + if (plaintext) { + DEBUG(4,("Using cleartext machine password\n")); + E_md4hash(plaintext, ret_pwd); + SAFE_FREE(plaintext); + return True; + } + + return secrets_fetch_trust_account_password_legacy(domain, ret_pwd, + pass_last_set_time, + channel); +} + /** * Pack SID passed by pointer * @@ -500,20 +518,6 @@ BOOL secrets_fetch_trusted_domain_password(const char *domain, char** pwd, return True; } -/************************************************************************ - Routine to set the trust account password for a domain. -************************************************************************/ - -BOOL secrets_store_trust_account_password(const char *domain, uint8 new_pwd[16]) -{ - struct machine_acct_pass pass; - - pass.mod_time = time(NULL); - memcpy(pass.hash, new_pwd, 16); - - return secrets_store(trust_keystr(domain), (void *)&pass, sizeof(pass)); -} - /** * Routine to store the password for trusted domain * @@ -655,54 +659,103 @@ char *secrets_fetch_machine_password(const char *domain, return ret; } +BOOL is_trusted_domain_situation(const char *domain_name) +{ + return IS_DC && + lp_allow_trusted_domains() && + !strequal(domain_name, lp_workgroup()); +} + /******************************************************************* - Wrapper around retrieving the trust account password + Wrapper around retrieving the clear text trust account password. + appropriate account name is stored in account_name. + Caller must free password, but not account_name. *******************************************************************/ - -BOOL get_trust_pw(const char *domain, uint8 ret_pwd[16], uint32 *channel) + +BOOL get_trust_pw_clear(const char *domain, char **ret_pwd, + const char **account_name, uint32 *channel) { - DOM_SID sid; char *pwd; time_t last_set_time; - + /* if we are a DC and this is not our domain, then lookup an account - for the domain trust */ - - if ( IS_DC && !strequal(domain, lp_workgroup()) && lp_allow_trusted_domains() ) { - if (!secrets_fetch_trusted_domain_password(domain, &pwd, &sid, - &last_set_time)) { + * for the domain trust */ + + if (is_trusted_domain_situation(domain)) { + if (!secrets_fetch_trusted_domain_password(domain, ret_pwd, + NULL, &last_set_time)) + { DEBUG(0, ("get_trust_pw: could not fetch trust " "account password for trusted domain %s\n", domain)); return False; } - - *channel = SEC_CHAN_DOMAIN; - E_md4hash(pwd, ret_pwd); - SAFE_FREE(pwd); + + if (channel != NULL) { + *channel = SEC_CHAN_DOMAIN; + } + + if (account_name != NULL) { + *account_name = lp_workgroup(); + } return True; } - + /* Just get the account for the requested domain. In the future this * might also cover to be member of more than one domain. */ - - if (secrets_fetch_trust_account_password(domain, ret_pwd, - &last_set_time, channel)) + + pwd = secrets_fetch_machine_password(domain, &last_set_time, channel); + + if (pwd != NULL) { + *ret_pwd = pwd; + if (account_name != NULL) { + *account_name = global_myname(); + } + return True; + } - DEBUG(5, ("get_trust_pw: could not fetch trust account " - "password for domain %s\n", domain)); + DEBUG(5, ("get_trust_pw_clear: could not fetch clear text trust " + "account password for domain %s\n", domain)); return False; } -/************************************************************************ - Routine to delete the machine trust account password file for a domain. -************************************************************************/ +/******************************************************************* + Wrapper around retrieving the trust account password. + appropriate account name is stored in account_name. +*******************************************************************/ -BOOL trust_password_delete(const char *domain) +BOOL get_trust_pw_hash(const char *domain, uint8 ret_pwd[16], + const char **account_name, uint32 *channel) { - return secrets_delete(trust_keystr(domain)); + char *pwd = NULL; + time_t last_set_time; + + if (get_trust_pw_clear(domain, &pwd, account_name, channel)) { + E_md4hash(pwd, ret_pwd); + SAFE_FREE(pwd); + return True; + } else if (is_trusted_domain_situation(domain)) { + return False; + } + + /* as a fallback, try to get the hashed pwd directly from the tdb... */ + + if (secrets_fetch_trust_account_password_legacy(domain, ret_pwd, + &last_set_time, + channel)) + { + if (account_name != NULL) { + *account_name = global_myname(); + } + + return True; + } + + DEBUG(5, ("get_trust_pw_hash: could not fetch trust account " + "password for domain %s\n", domain)); + return False; } /************************************************************************ diff --git a/source/python/py_samr.c b/source/python/py_samr.c index fced5b3ddd..e2600bc3f6 100644 --- a/source/python/py_samr.c +++ b/source/python/py_samr.c @@ -463,7 +463,7 @@ static PyObject *samr_create_dom_user(PyObject *self, PyObject *args, static char *kwlist[] = { "account_name", "acb_info", NULL }; char *account_name; NTSTATUS ntstatus; - uint32 unknown = 0xe005000b; /* Access mask? */ + uint32 acct_flags = 0; uint32 user_rid; PyObject *result = NULL; TALLOC_CTX *mem_ctx; @@ -479,9 +479,14 @@ static PyObject *samr_create_dom_user(PyObject *self, PyObject *args, return NULL; } + acct_flags = SAMR_GENERIC_READ | SAMR_GENERIC_WRITE | + SAMR_GENERIC_EXECUTE | SAMR_STANDARD_WRITEDAC | + SAMR_STANDARD_DELETE | SAMR_USER_SETPASS | SAMR_USER_GETATTR | + SAMR_USER_SETATTR; + DEBUG(10, ("Creating account with flags: %d\n",acct_flags)); ntstatus = rpccli_samr_create_dom_user( domain_hnd->cli, mem_ctx, &domain_hnd->domain_pol, - account_name, acb_info, unknown, &user_pol, &user_rid); + account_name, acb_info, acct_flags, &user_pol, &user_rid); if (!NT_STATUS_IS_OK(ntstatus)) { PyErr_SetObject(samr_ntstatus, py_ntstatus_tuple(ntstatus)); diff --git a/source/rpc_client/cli_pipe.c b/source/rpc_client/cli_pipe.c index 61f5ee51bd..43c3044ce4 100644 --- a/source/rpc_client/cli_pipe.c +++ b/source/rpc_client/cli_pipe.c @@ -1806,6 +1806,7 @@ static NTSTATUS rpc_finish_auth3_bind(struct rpc_pipe_client *cli, if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0,("rpc_finish_auth3_bind: NTLMSSP update using server blob failed.\n")); + data_blob_free(&server_response); return nt_status; } @@ -2363,8 +2364,8 @@ static struct rpc_pipe_client *cli_rpc_pipe_open_ntlmssp_internal(struct cli_sta goto err; } - DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to machine %s and" - "bound NTLMSSP as user %s\\%s.\n", + DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to " + "machine %s and bound NTLMSSP as user %s\\%s.\n", result->pipe_name, cli->desthost, domain, username )); @@ -2423,49 +2424,29 @@ struct rpc_pipe_client *cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli, } /**************************************************************************** - Open a netlogon pipe and get the schannel session key. - Now exposed to external callers. + Get a the schannel session key out of an already opened netlogon pipe. ****************************************************************************/ - -struct rpc_pipe_client *get_schannel_session_key(struct cli_state *cli, - const char *domain, - uint32 *pneg_flags, - NTSTATUS *perr) +static BOOL get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe, + struct cli_state *cli, + const char *domain, + uint32 *pneg_flags, + NTSTATUS *perr) { - struct rpc_pipe_client *netlogon_pipe = NULL; uint32 sec_chan_type = 0; unsigned char machine_pwd[16]; - fstring machine_account; - - netlogon_pipe = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, perr); - if (!netlogon_pipe) { - return NULL; - } + const char *machine_account; /* Get the machine account credentials from secrets.tdb. */ - if (!get_trust_pw(domain, machine_pwd, &sec_chan_type)) { + if (!get_trust_pw_hash(domain, machine_pwd, &machine_account, + &sec_chan_type)) + { DEBUG(0, ("get_schannel_session_key: could not fetch " "trust account password for domain '%s'\n", domain)); - cli_rpc_pipe_close(netlogon_pipe); *perr = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - return NULL; + return False; } - /* A DC should use DOMAIN$ as its account name. - A member server can only use it's machine name since it - does not have an account in a trusted domain. - - We don't check the domain against lp_workgroup() here since - 'net ads join' has to continue to work with only the realm - specified in smb.conf. -- jerry */ - - if ( IS_DC && !strequal(domain, lp_workgroup()) && lp_allow_trusted_domains()) { - fstrcpy( machine_account, lp_workgroup() ); - } else { - fstrcpy(machine_account, global_myname()); - } - *perr = rpccli_netlogon_setup_creds(netlogon_pipe, cli->desthost, /* server name */ domain, /* domain */ @@ -2476,18 +2457,44 @@ struct rpc_pipe_client *get_schannel_session_key(struct cli_state *cli, pneg_flags); if (!NT_STATUS_IS_OK(*perr)) { - DEBUG(3,("get_schannel_session_key: rpccli_netlogon_setup_creds " + DEBUG(3,("get_schannel_session_key_common: rpccli_netlogon_setup_creds " "failed with result %s to server %s, domain %s, machine account %s.\n", nt_errstr(*perr), cli->desthost, domain, machine_account )); - cli_rpc_pipe_close(netlogon_pipe); - return NULL; + return False; } if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) { DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n", cli->desthost)); - cli_rpc_pipe_close(netlogon_pipe); *perr = NT_STATUS_INVALID_NETWORK_RESPONSE; + return False; + } + + return True; +} + +/**************************************************************************** + Open a netlogon pipe and get the schannel session key. + Now exposed to external callers. + ****************************************************************************/ + + +struct rpc_pipe_client *get_schannel_session_key(struct cli_state *cli, + const char *domain, + uint32 *pneg_flags, + NTSTATUS *perr) +{ + struct rpc_pipe_client *netlogon_pipe = NULL; + + netlogon_pipe = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, perr); + if (!netlogon_pipe) { + return NULL; + } + + if (!get_schannel_session_key_common(netlogon_pipe, cli, domain, + pneg_flags, perr)) + { + cli_rpc_pipe_close(netlogon_pipe); return NULL; } @@ -2559,61 +2566,16 @@ static struct rpc_pipe_client *get_schannel_session_key_auth_ntlmssp(struct cli_ NTSTATUS *perr) { struct rpc_pipe_client *netlogon_pipe = NULL; - uint32 sec_chan_type = 0; - unsigned char machine_pwd[16]; - fstring machine_account; netlogon_pipe = cli_rpc_pipe_open_spnego_ntlmssp(cli, PI_NETLOGON, PIPE_AUTH_LEVEL_PRIVACY, domain, username, password, perr); if (!netlogon_pipe) { return NULL; } - /* Get the machine account credentials from secrets.tdb. */ - if (!get_trust_pw(domain, machine_pwd, &sec_chan_type)) { - DEBUG(0, ("get_schannel_session_key_auth_ntlmssp: could not fetch " - "trust account password for domain '%s'\n", - domain)); - cli_rpc_pipe_close(netlogon_pipe); - *perr = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - return NULL; - } - - /* if we are a DC and this is a trusted domain, then we need to use our - domain name in the net_req_auth2() request */ - - if ( IS_DC && !strequal(domain, lp_workgroup()) && lp_allow_trusted_domains()) { - fstrcpy( machine_account, lp_workgroup() ); - } else { - /* Hmmm. Is this correct for trusted domains when we're a member server ? JRA. */ - if (strequal(domain, lp_workgroup())) { - fstrcpy(machine_account, global_myname()); - } else { - fstrcpy(machine_account, domain); - } - } - - *perr = rpccli_netlogon_setup_creds(netlogon_pipe, - cli->desthost, /* server name */ - domain, /* domain */ - global_myname(), /* client name */ - machine_account, /* machine account name */ - machine_pwd, - sec_chan_type, - pneg_flags); - - if (!NT_STATUS_IS_OK(*perr)) { - DEBUG(3,("get_schannel_session_key_auth_ntlmssp: rpccli_netlogon_setup_creds " - "failed with result %s\n", - nt_errstr(*perr) )); - cli_rpc_pipe_close(netlogon_pipe); - return NULL; - } - - if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) { - DEBUG(3, ("get_schannel_session_key_auth_ntlmssp: Server %s did not offer schannel\n", - cli->desthost)); + if (!get_schannel_session_key_common(netlogon_pipe, cli, domain, + pneg_flags, perr)) + { cli_rpc_pipe_close(netlogon_pipe); - *perr = NT_STATUS_INVALID_NETWORK_RESPONSE; return NULL; } @@ -2634,7 +2596,7 @@ struct rpc_pipe_client *cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state const char *password, NTSTATUS *perr) { - uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS|NETLOGON_NEG_SCHANNEL; + uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS|NETLOGON_NEG_SCHANNEL; struct rpc_pipe_client *netlogon_pipe = NULL; struct rpc_pipe_client *result = NULL; @@ -2668,7 +2630,7 @@ struct rpc_pipe_client *cli_rpc_pipe_open_schannel(struct cli_state *cli, const char *domain, NTSTATUS *perr) { - uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS|NETLOGON_NEG_SCHANNEL; + uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS|NETLOGON_NEG_SCHANNEL; struct rpc_pipe_client *netlogon_pipe = NULL; struct rpc_pipe_client *result = NULL; diff --git a/source/rpc_parse/parse_samr.c b/source/rpc_parse/parse_samr.c index 4410348abe..d452c1fe82 100644 --- a/source/rpc_parse/parse_samr.c +++ b/source/rpc_parse/parse_samr.c @@ -5182,7 +5182,7 @@ reads or writes a structure. void init_samr_q_create_user(SAMR_Q_CREATE_USER * q_u, POLICY_HND *pol, const char *name, - uint32 acb_info, uint32 access_mask) + uint32 acb_info, uint32 acct_flags) { DEBUG(5, ("samr_init_samr_q_create_user\n")); @@ -5192,7 +5192,7 @@ void init_samr_q_create_user(SAMR_Q_CREATE_USER * q_u, init_uni_hdr(&q_u->hdr_name, &q_u->uni_name); q_u->acb_info = acb_info; - q_u->access_mask = access_mask; + q_u->acct_flags = acct_flags; } /******************************************************************* @@ -5223,7 +5223,7 @@ BOOL samr_io_q_create_user(const char *desc, SAMR_Q_CREATE_USER * q_u, return False; if(!prs_uint32("acb_info ", ps, depth, &q_u->acb_info)) return False; - if(!prs_uint32("access_mask", ps, depth, &q_u->access_mask)) + if(!prs_uint32("acct_flags", ps, depth, &q_u->acct_flags)) return False; return True; @@ -5870,6 +5870,25 @@ void init_sam_user_info23A(SAM_USER_INFO_23 * usr, NTTIME * logon_time, /* all z } } + +/************************************************************************* + init_samr_user_info25P + fields_present = ACCT_NT_PWD_SET | ACCT_LM_PWD_SET | ACCT_FLAGS +*************************************************************************/ + +void init_sam_user_info25P(SAM_USER_INFO_25 * usr, + uint32 fields_present, uint32 acb_info, + char newpass[532]) +{ + usr->fields_present = fields_present; + ZERO_STRUCT(usr->padding1); + ZERO_STRUCT(usr->padding2); + + usr->acb_info = acb_info; + memcpy(usr->pass, newpass, sizeof(usr->pass)); +} + + /******************************************************************* reads or writes a structure. ********************************************************************/ diff --git a/source/rpc_server/srv_lsa_nt.c b/source/rpc_server/srv_lsa_nt.c index 7a47cedf4a..c105edf19d 100644 --- a/source/rpc_server/srv_lsa_nt.c +++ b/source/rpc_server/srv_lsa_nt.c @@ -1032,6 +1032,31 @@ NTSTATUS _lsa_lookup_sids3(pipes_struct *p, return r_u->status; } +static int lsa_lookup_level_to_flags(uint16 level) +{ + int flags; + + switch (level) { + case 1: + flags = LOOKUP_NAME_ALL; + break; + case 2: + flags = LOOKUP_NAME_DOMAIN|LOOKUP_NAME_REMOTE|LOOKUP_NAME_ISOLATED; + break; + case 3: + flags = LOOKUP_NAME_DOMAIN|LOOKUP_NAME_ISOLATED; + break; + case 4: + case 5: + case 6: + default: + flags = LOOKUP_NAME_NONE; + break; + } + + return flags; +} + /*************************************************************************** lsa_reply_lookup_names ***************************************************************************/ @@ -1051,10 +1076,7 @@ NTSTATUS _lsa_lookup_names(pipes_struct *p,LSA_Q_LOOKUP_NAMES *q_u, LSA_R_LOOKUP DEBUG(5,("_lsa_lookup_names: truncating name lookup list to %d\n", num_entries)); } - /* Probably the lookup_level is some sort of bitmask. */ - if (q_u->lookup_level == 1) { - flags = LOOKUP_NAME_ALL; - } + flags = lsa_lookup_level_to_flags(q_u->lookup_level); ref = TALLOC_ZERO_P(p->mem_ctx, DOM_R_REF); if (!ref) { @@ -1120,11 +1142,8 @@ NTSTATUS _lsa_lookup_names2(pipes_struct *p, LSA_Q_LOOKUP_NAMES2 *q_u, LSA_R_LOO num_entries = MAX_LOOKUP_SIDS; DEBUG(5,("_lsa_lookup_names2: truncating name lookup list to %d\n", num_entries)); } - - /* Probably the lookup_level is some sort of bitmask. */ - if (q_u->lookup_level == 1) { - flags = LOOKUP_NAME_ALL; - } + + flags = lsa_lookup_level_to_flags(q_u->lookup_level); ref = TALLOC_ZERO_P(p->mem_ctx, DOM_R_REF); if (ref == NULL) { diff --git a/source/rpc_server/srv_samr_nt.c b/source/rpc_server/srv_samr_nt.c index 3343f16f35..cc289cad05 100644 --- a/source/rpc_server/srv_samr_nt.c +++ b/source/rpc_server/srv_samr_nt.c @@ -2507,9 +2507,9 @@ static NTSTATUS can_create(TALLOC_CTX *mem_ctx, const char *new_name) DEBUG(10, ("Checking whether [%s] can be created\n", new_name)); become_root(); - /* Lookup in our local databases (only LOOKUP_NAME_ISOLATED set) + /* Lookup in our local databases (LOOKUP_NAME_REMOTE not set) * whether the name already exists */ - result = lookup_name(mem_ctx, new_name, LOOKUP_NAME_ISOLATED, + result = lookup_name(mem_ctx, new_name, LOOKUP_NAME_LOCAL, NULL, NULL, NULL, &type); unbecome_root(); diff --git a/source/rpc_server/srv_spoolss_nt.c b/source/rpc_server/srv_spoolss_nt.c index 4cf43f04e4..0bc7a39dd0 100644 --- a/source/rpc_server/srv_spoolss_nt.c +++ b/source/rpc_server/srv_spoolss_nt.c @@ -1403,8 +1403,8 @@ static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode) len = unistrlen(devmode->formname.buffer); if (len != -1) { - d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len); - if (!d->devicename.buffer) { + d->formname.buffer = TALLOC_ARRAY(ctx, uint16, len); + if (!d->formname.buffer) { return NULL; } if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len) diff --git a/source/rpc_server/srv_srvsvc_nt.c b/source/rpc_server/srv_srvsvc_nt.c index d03ab66b50..173979f8c6 100644 --- a/source/rpc_server/srv_srvsvc_nt.c +++ b/source/rpc_server/srv_srvsvc_nt.c @@ -203,9 +203,6 @@ static WERROR net_enum_files( TALLOC_CTX *ctx, FILE_INFO_3 **info, ********************************************************************/ static uint32 get_share_type(int snum) { - char *net_name = lp_servicename(snum); - int len_net_name = strlen(net_name); - /* work out the share type */ uint32 type = STYPE_DISKTREE; @@ -213,7 +210,7 @@ static uint32 get_share_type(int snum) type = STYPE_PRINTQ; if (strequal(lp_fstype(snum), "IPC")) type = STYPE_IPC; - if (net_name[len_net_name-1] == '$') + if (lp_administrative_share(snum)) type |= STYPE_HIDDEN; return type; diff --git a/source/rpcclient/cmd_samr.c b/source/rpcclient/cmd_samr.c index dd55e65fb9..8487d2b8c7 100644 --- a/source/rpcclient/cmd_samr.c +++ b/source/rpcclient/cmd_samr.c @@ -1450,7 +1450,7 @@ static NTSTATUS cmd_samr_create_dom_user(struct rpc_pipe_client *cli, NTSTATUS result = NT_STATUS_UNSUCCESSFUL; const char *acct_name; uint32 acb_info; - uint32 unknown, user_rid; + uint32 acct_flags, user_rid; uint32 access_mask = MAXIMUM_ALLOWED_ACCESS; if ((argc < 2) || (argc > 3)) { @@ -1483,10 +1483,13 @@ static NTSTATUS cmd_samr_create_dom_user(struct rpc_pipe_client *cli, /* Create domain user */ acb_info = ACB_NORMAL; - unknown = 0xe005000b; /* No idea what this is - a permission mask? */ - + acct_flags = SAMR_GENERIC_READ | SAMR_GENERIC_WRITE | + SAMR_GENERIC_EXECUTE | SAMR_STANDARD_WRITEDAC | + SAMR_STANDARD_DELETE | SAMR_USER_SETPASS | SAMR_USER_GETATTR | + SAMR_USER_SETATTR; + DEBUG(10, ("Creating account with flags: %d\n",acct_flags)); result = rpccli_samr_create_dom_user(cli, mem_ctx, &domain_pol, - acct_name, acb_info, unknown, + acct_name, acb_info, acct_flags, &user_pol, &user_rid); if (!NT_STATUS_IS_OK(result)) diff --git a/source/rpcclient/rpcclient.c b/source/rpcclient/rpcclient.c index f671e892a0..0f7ff63aa0 100644 --- a/source/rpcclient/rpcclient.c +++ b/source/rpcclient/rpcclient.c @@ -568,7 +568,7 @@ static NTSTATUS do_cmd(struct cli_state *cli, } if (cmd_entry->pipe_idx == PI_NETLOGON) { - uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS; + uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS; uint32 sec_channel_type; uchar trust_password[16]; diff --git a/source/smbd/chgpasswd.c b/source/smbd/chgpasswd.c index 7c6886b81c..2a4d96598b 100644 --- a/source/smbd/chgpasswd.c +++ b/source/smbd/chgpasswd.c @@ -126,6 +126,7 @@ static int dochild(int master, const char *slavedev, const struct passwd *pass, struct termios stermios; gid_t gid; uid_t uid; + char * const eptrs[1] = { NULL }; if (pass == NULL) { @@ -153,19 +154,19 @@ static int dochild(int master, const char *slavedev, const struct passwd *pass, DEBUG(3, ("More weirdness, could not open %s\n", slavedev)); return (False); } -#if defined(I_PUSH) && defined(I_FIND) +#if defined(TIOCSCTTY) + if (ioctl(slave, TIOCSCTTY, 0) < 0) + { + DEBUG(3, ("Error in ioctl call for slave pty\n")); + /* return(False); */ + } +#elif defined(I_PUSH) && defined(I_FIND) if (ioctl(slave, I_FIND, "ptem") == 0) { ioctl(slave, I_PUSH, "ptem"); } if (ioctl(slave, I_FIND, "ldterm") == 0) { ioctl(slave, I_PUSH, "ldterm"); } -#elif defined(TIOCSCTTY) - if (ioctl(slave, TIOCSCTTY, 0) < 0) - { - DEBUG(3, ("Error in ioctl call for slave pty\n")); - /* return(False); */ - } #endif /* Close master. */ @@ -222,7 +223,7 @@ static int dochild(int master, const char *slavedev, const struct passwd *pass, passwordprogram)); /* execl() password-change application */ - if (execl("/bin/sh", "sh", "-c", passwordprogram, NULL) < 0) + if (execle("/bin/sh", "sh", "-c", passwordprogram, NULL, eptrs) < 0) { DEBUG(3, ("Bad status returned from %s\n", passwordprogram)); return (False); @@ -498,6 +499,9 @@ BOOL chgpasswd(const char *name, const struct passwd *pass, #ifdef WITH_PAM if (lp_pam_password_change()) { BOOL ret; +#ifdef HAVE_SETLOCALE + char *prevlocale = setlocale(LC_ALL, "C"); +#endif if (as_root) become_root(); @@ -511,6 +515,10 @@ BOOL chgpasswd(const char *name, const struct passwd *pass, if (as_root) unbecome_root(); +#ifdef HAVE_SETLOCALE + setlocale(LC_ALL, prevlocale); +#endif + return ret; } #endif diff --git a/source/smbd/dosmode.c b/source/smbd/dosmode.c index 71d4fa179d..28d8a77a96 100644 --- a/source/smbd/dosmode.c +++ b/source/smbd/dosmode.c @@ -438,12 +438,19 @@ int file_set_dosmode(connection_struct *conn, const char *fname, dosmode &= SAMBA_ATTRIBUTES_MASK; DEBUG(10,("file_set_dosmode: setting dos mode 0x%x on file %s\n", dosmode, fname)); - if (!st || (st && !VALID_STAT(*st))) { + + if (st == NULL) { + SET_STAT_INVALID(st1); st = &st1; + } + + if (!VALID_STAT(*st)) { if (SMB_VFS_STAT(conn,fname,st)) return(-1); } + unixmode = st->st_mode; + get_acl_group_bits(conn, fname, &st->st_mode); if (S_ISDIR(st->st_mode)) @@ -451,11 +458,14 @@ int file_set_dosmode(connection_struct *conn, const char *fname, else dosmode &= ~aDIR; - if (dos_mode(conn,fname,st) == dosmode) + if (dos_mode(conn,fname,st) == dosmode) { + st->st_mode = unixmode; return(0); + } /* Store the DOS attributes in an EA by preference. */ if (set_ea_dos_attribute(conn, fname, st, dosmode)) { + st->st_mode = unixmode; return 0; } @@ -494,6 +504,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname, if ((ret = SMB_VFS_CHMOD(conn,fname,unixmode)) == 0) { notify_fname(conn, NOTIFY_ACTION_MODIFIED, FILE_NOTIFY_CHANGE_ATTRIBUTES, fname); + st->st_mode = unixmode; return 0; } @@ -526,6 +537,9 @@ int file_set_dosmode(connection_struct *conn, const char *fname, close_file_fchmod(fsp); notify_fname(conn, NOTIFY_ACTION_MODIFIED, FILE_NOTIFY_CHANGE_ATTRIBUTES, fname); + if (ret == 0) { + st->st_mode = unixmode; + } } return( ret ); diff --git a/source/smbd/notify.c b/source/smbd/notify.c index df9d8ad137..6e244663f2 100644 --- a/source/smbd/notify.c +++ b/source/smbd/notify.c @@ -66,6 +66,8 @@ static BOOL notify_marshall_changes(int num_changes, int i; UNISTR uni_name; + uni_name.buffer = NULL; + for (i=0; i<num_changes; i++) { struct notify_change *c; size_t namelen; diff --git a/source/smbd/notify_inotify.c b/source/smbd/notify_inotify.c index 1b1bad7e96..a9eb221cb9 100644 --- a/source/smbd/notify_inotify.c +++ b/source/smbd/notify_inotify.c @@ -30,10 +30,12 @@ #include <asm/types.h> #endif +#ifndef HAVE_INOTIFY_INIT + #include <linux/inotify.h> #include <asm/unistd.h> -#ifndef HAVE_INOTIFY_INIT + /* glibc doesn't define these functions yet (as of March 2006) */ @@ -51,6 +53,10 @@ static int inotify_rm_watch(int fd, int wd) { return syscall(__NR_inotify_rm_watch, fd, wd); } +#else + +#include <sys/inotify.h> + #endif diff --git a/source/smbd/open.c b/source/smbd/open.c index 0fa11a56c8..69551405bf 100644 --- a/source/smbd/open.c +++ b/source/smbd/open.c @@ -1375,7 +1375,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } #endif /* O_SYNC */ - if (posix_open & (access_mask & FILE_APPEND_DATA)) { + if (posix_open && (access_mask & FILE_APPEND_DATA)) { flags2 |= O_APPEND; } @@ -1818,9 +1818,15 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, if (lp_map_archive(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) { if (!posix_open) { - file_set_dosmode(conn, fname, - new_dos_attributes | aARCH, NULL, - parent_dir); + SMB_STRUCT_STAT tmp_sbuf; + SET_STAT_INVALID(tmp_sbuf); + if (file_set_dosmode( + conn, fname, + new_dos_attributes | aARCH, + &tmp_sbuf, + parent_dir) == 0) { + unx_mode = tmp_sbuf.st_mode; + } } } } diff --git a/source/smbd/password.c b/source/smbd/password.c index bf4e9258ff..a617d3c5b1 100644 --- a/source/smbd/password.c +++ b/source/smbd/password.c @@ -91,11 +91,15 @@ void invalidate_vuid(uint16 vuid) if (vuser == NULL) return; - + SAFE_FREE(vuser->homedir); SAFE_FREE(vuser->unix_homedir); SAFE_FREE(vuser->logon_script); - + + if (vuser->auth_ntlmssp_state) { + auth_ntlmssp_end(&vuser->auth_ntlmssp_state); + } + session_yield(vuser); SAFE_FREE(vuser->session_keystr); @@ -116,6 +120,23 @@ void invalidate_vuid(uint16 vuid) num_validated_vuids--; } +void invalidate_intermediate_vuid(uint16 vuid) +{ + user_struct *vuser = get_partial_auth_user_struct(vuid); + + if (vuser == NULL) + return; + + if (vuser->auth_ntlmssp_state) { + auth_ntlmssp_end(&vuser->auth_ntlmssp_state); + } + + DLIST_REMOVE(validated_users, vuser); + + SAFE_FREE(vuser); + num_validated_vuids--; +} + /**************************************************************************** Invalidate all vuid entries for this process. ****************************************************************************/ @@ -163,19 +184,22 @@ int register_vuid(auth_serversupplied_info *server_info, /* Limit allowed vuids to 16bits - VUID_OFFSET. */ if (num_validated_vuids >= 0xFFFF-VUID_OFFSET) { data_blob_free(&session_key); + TALLOC_FREE(server_info); return UID_FIELD_INVALID; } if((vuser = SMB_MALLOC_P(user_struct)) == NULL) { DEBUG(0,("Failed to malloc users struct!\n")); data_blob_free(&session_key); + TALLOC_FREE(server_info); return UID_FIELD_INVALID; } ZERO_STRUCTP(vuser); /* Allocate a free vuid. Yes this is a linear search... :-) */ - while( get_valid_user_struct(next_vuid) != NULL ) { + while( (get_valid_user_struct(next_vuid) != NULL) + || (get_partial_auth_user_struct(next_vuid) != NULL) ) { next_vuid++; /* Check for vuid wrap. */ if (next_vuid == UID_FIELD_INVALID) diff --git a/source/smbd/posix_acls.c b/source/smbd/posix_acls.c index 1088e8ebfb..f40a344124 100644 --- a/source/smbd/posix_acls.c +++ b/source/smbd/posix_acls.c @@ -1336,12 +1336,12 @@ static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst, psa1->flags |= (psa2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT)); psa2->flags &= ~(SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT); - + } else if (psa2->flags & SEC_ACE_FLAG_INHERIT_ONLY) { psa2->flags |= (psa1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT)); psa1->flags &= ~(SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT); - + } } } @@ -1402,10 +1402,22 @@ static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst, } else if (sid_to_uid( ¤t_ace->trustee, ¤t_ace->unix_ug.uid)) { current_ace->owner_type = UID_ACE; - current_ace->type = SMB_ACL_USER; + /* If it's the owning user, this is a user_obj, not + * a user. */ + if (current_ace->unix_ug.uid == pst->st_uid) { + current_ace->type = SMB_ACL_USER_OBJ; + } else { + current_ace->type = SMB_ACL_USER; + } } else if (sid_to_gid( ¤t_ace->trustee, ¤t_ace->unix_ug.gid)) { current_ace->owner_type = GID_ACE; - current_ace->type = SMB_ACL_GROUP; + /* If it's the primary group, this is a group_obj, not + * a group. */ + if (current_ace->unix_ug.gid == pst->st_gid) { + current_ace->type = SMB_ACL_GROUP_OBJ; + } else { + current_ace->type = SMB_ACL_GROUP; + } } else { fstring str; @@ -3099,57 +3111,8 @@ int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid) return ret; } -static NTSTATUS append_ugw_ace(files_struct *fsp, - SMB_STRUCT_STAT *psbuf, - mode_t unx_mode, - int ugw, - SEC_ACE *se) -{ - mode_t perms; - SEC_ACCESS acc; - int nt_acl_type; /* Tru64 has "acl_type" as a macro.. */ - DOM_SID trustee; - - switch (ugw) { - case S_IRUSR: - perms = unix_perms_to_acl_perms(unx_mode, - S_IRUSR, - S_IWUSR, - S_IXUSR); - uid_to_sid(&trustee, psbuf->st_uid ); - break; - case S_IRGRP: - perms = unix_perms_to_acl_perms(unx_mode, - S_IRGRP, - S_IWGRP, - S_IXGRP); - gid_to_sid(&trustee, psbuf->st_gid ); - break; - case S_IROTH: - perms = unix_perms_to_acl_perms(unx_mode, - S_IROTH, - S_IWOTH, - S_IXOTH); - sid_copy(&trustee, &global_sid_World); - break; - default: - return NT_STATUS_INVALID_PARAMETER; - } - acc = map_canon_ace_perms(SNUM(fsp->conn), - &nt_acl_type, - perms, - fsp->is_directory); - - init_sec_ace(se, - &trustee, - nt_acl_type, - acc, - 0); - return NT_STATUS_OK; -} - /**************************************************************************** - If this is an + Take care of parent ACL inheritance. ****************************************************************************/ static NTSTATUS append_parent_acl(files_struct *fsp, @@ -3168,7 +3131,7 @@ static NTSTATUS append_parent_acl(files_struct *fsp, int info; size_t sd_size; unsigned int i, j; - mode_t unx_mode; + BOOL is_dacl_protected = (psd->type & SE_DESC_DACL_PROTECTED); ZERO_STRUCT(sbuf); @@ -3183,12 +3146,6 @@ static NTSTATUS append_parent_acl(files_struct *fsp, return NT_STATUS_NO_MEMORY; } - /* Create a default mode for u/g/w. */ - unx_mode = unix_mode(fsp->conn, - aARCH | (fsp->is_directory ? aDIR : 0), - fsp->fsp_name, - parent_name); - status = open_directory(fsp->conn, parent_name, &sbuf, @@ -3213,22 +3170,25 @@ static NTSTATUS append_parent_acl(files_struct *fsp, return NT_STATUS_ACCESS_DENIED; } - /* + /* * Make room for potentially all the ACLs from - * the parent, plus the user/group/other triple. + * the parent. We used to add the ugw triple here, + * as we knew we were dealing with POSIX ACLs. + * We no longer need to do so as we can guarentee + * that a default ACL from the parent directory will + * be well formed for POSIX ACLs if it came from a + * POSIX ACL source, and if we're not writing to a + * POSIX ACL sink then we don't care if it's not well + * formed. JRA. */ - num_aces += parent_sd->dacl->num_aces + 3; + num_aces += parent_sd->dacl->num_aces; if((new_ace = TALLOC_ZERO_ARRAY(mem_ctx, SEC_ACE, num_aces)) == NULL) { return NT_STATUS_NO_MEMORY; } - DEBUG(10,("append_parent_acl: parent ACL has %u entries. New " - "ACL has %u entries\n", - parent_sd->dacl->num_aces, num_aces )); - /* Start by copying in all the given ACE entries. */ for (i = 0; i < psd->dacl->num_aces; i++) { sec_ace_copy(&new_ace[i], &psd->dacl->aces[i]); @@ -3239,49 +3199,97 @@ static NTSTATUS append_parent_acl(files_struct *fsp, * as that really only applies to newly created files. JRA. */ - /* - * Append u/g/w. - */ - - status = append_ugw_ace(fsp, psbuf, unx_mode, S_IRUSR, &new_ace[i++]); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - status = append_ugw_ace(fsp, psbuf, unx_mode, S_IRGRP, &new_ace[i++]); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - status = append_ugw_ace(fsp, psbuf, unx_mode, S_IROTH, &new_ace[i++]); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - /* Finally append any inherited ACEs. */ for (j = 0; j < parent_sd->dacl->num_aces; j++) { SEC_ACE *se = &parent_sd->dacl->aces[j]; - uint32 i_flags = se->flags & (SEC_ACE_FLAG_OBJECT_INHERIT| - SEC_ACE_FLAG_CONTAINER_INHERIT| - SEC_ACE_FLAG_INHERIT_ONLY); if (fsp->is_directory) { - if (i_flags == SEC_ACE_FLAG_OBJECT_INHERIT) { - /* Should only apply to a file - ignore. */ + if (!(se->flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) { + /* Doesn't apply to a directory - ignore. */ + DEBUG(10,("append_parent_acl: directory %s " + "ignoring non container " + "inherit flags %u on ACE with sid %s " + "from parent %s\n", + fsp->fsp_name, + (unsigned int)se->flags, + sid_string_static(&se->trustee), + parent_name)); continue; } } else { - if ((i_flags & (SEC_ACE_FLAG_OBJECT_INHERIT| - SEC_ACE_FLAG_INHERIT_ONLY)) != - SEC_ACE_FLAG_OBJECT_INHERIT) { - /* Should not apply to a file - ignore. */ + if (!(se->flags & SEC_ACE_FLAG_OBJECT_INHERIT)) { + /* Doesn't apply to a file - ignore. */ + DEBUG(10,("append_parent_acl: file %s " + "ignoring non object " + "inherit flags %u on ACE with sid %s " + "from parent %s\n", + fsp->fsp_name, + (unsigned int)se->flags, + sid_string_static(&se->trustee), + parent_name)); continue; } } + + if (is_dacl_protected) { + /* If the DACL is protected it means we must + * not overwrite an existing ACE entry with the + * same SID. This is order N^2. Ouch :-(. JRA. */ + unsigned int k; + for (k = 0; k < psd->dacl->num_aces; k++) { + if (sid_equal(&psd->dacl->aces[k].trustee, + &se->trustee)) { + break; + } + } + if (k < psd->dacl->num_aces) { + /* SID matched. Ignore. */ + DEBUG(10,("append_parent_acl: path %s " + "ignoring ACE with protected sid %s " + "from parent %s\n", + fsp->fsp_name, + sid_string_static(&se->trustee), + parent_name)); + continue; + } + } + sec_ace_copy(&new_ace[i], se); if (se->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) { new_ace[i].flags &= ~(SEC_ACE_FLAG_VALID_INHERIT); } new_ace[i].flags |= SEC_ACE_FLAG_INHERITED_ACE; + + if (fsp->is_directory) { + /* + * Strip off any inherit only. It's applied. + */ + new_ace[i].flags &= ~(SEC_ACE_FLAG_INHERIT_ONLY); + if (se->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) { + /* No further inheritance. */ + new_ace[i].flags &= + ~(SEC_ACE_FLAG_CONTAINER_INHERIT| + SEC_ACE_FLAG_OBJECT_INHERIT); + } + } else { + /* + * Strip off any container or inherit + * flags, they can't apply to objects. + */ + new_ace[i].flags &= ~(SEC_ACE_FLAG_CONTAINER_INHERIT| + SEC_ACE_FLAG_INHERIT_ONLY| + SEC_ACE_FLAG_NO_PROPAGATE_INHERIT); + } + i++; + + DEBUG(10,("append_parent_acl: path %s " + "inheriting ACE with sid %s " + "from parent %s\n", + fsp->fsp_name, + sid_string_static(&se->trustee), + parent_name)); + } parent_sd->dacl->aces = new_ace; diff --git a/source/smbd/reply.c b/source/smbd/reply.c index 54bf88844d..b954395278 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -5169,11 +5169,13 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, status = check_name(conn, fname); if (!NT_STATUS_IS_OK(status)) { + CloseDir(dir_hnd); return ERROR_NT(status); } status = check_name(conn, destname); if (!NT_STATUS_IS_OK(status)) { + CloseDir(dir_hnd); return ERROR_NT(status); } diff --git a/source/smbd/server.c b/source/smbd/server.c index 89cceae2a6..c90d5e727f 100644 --- a/source/smbd/server.c +++ b/source/smbd/server.c @@ -30,7 +30,7 @@ static int am_parent = 1; int last_message = -1; /* a useful macro to debug the last message processed */ -#define LAST_MESSAGE() smb_fn_name(last_message) +#define LAST_MESSAGE() (last_message != -1 ? smb_fn_name(last_message) : "") extern struct auth_context *negprot_global_auth_context; extern pstring user_socket_options; diff --git a/source/smbd/sesssetup.c b/source/smbd/sesssetup.c index 058faedd5e..378d8aa20c 100644 --- a/source/smbd/sesssetup.c +++ b/source/smbd/sesssetup.c @@ -624,7 +624,7 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out /* NB. This is *NOT* an error case. JRA */ auth_ntlmssp_end(auth_ntlmssp_state); /* Kill the intermediate vuid */ - invalidate_vuid(vuid); + invalidate_intermediate_vuid(vuid); } return ret; @@ -690,7 +690,7 @@ static int reply_spnego_negotiate(connection_struct *conn, status = parse_spnego_mechanisms(blob1, &secblob, &got_kerberos_mechanism); if (!NT_STATUS_IS_OK(status)) { /* Kill the intermediate vuid */ - invalidate_vuid(vuid); + invalidate_intermediate_vuid(vuid); return ERROR_NT(nt_status_squash(status)); } @@ -704,12 +704,21 @@ static int reply_spnego_negotiate(connection_struct *conn, data_blob_free(&secblob); if (destroy_vuid) { /* Kill the intermediate vuid */ - invalidate_vuid(vuid); + invalidate_intermediate_vuid(vuid); } return ret; } #endif + if (got_kerberos_mechanism) { + invalidate_intermediate_vuid(vuid); + DEBUG(3,("reply_spnego_negotiate: network " + "misconfiguration, client sent us a " + "krb5 ticket and kerberos security " + "not enabled")); + return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); + } + if (*auth_ntlmssp_state) { auth_ntlmssp_end(auth_ntlmssp_state); } @@ -717,7 +726,7 @@ static int reply_spnego_negotiate(connection_struct *conn, status = auth_ntlmssp_start(auth_ntlmssp_state); if (!NT_STATUS_IS_OK(status)) { /* Kill the intermediate vuid */ - invalidate_vuid(vuid); + invalidate_intermediate_vuid(vuid); return ERROR_NT(nt_status_squash(status)); } @@ -755,9 +764,9 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, file_save("auth.dat", blob1.data, blob1.length); #endif /* Kill the intermediate vuid */ - invalidate_vuid(vuid); + invalidate_intermediate_vuid(vuid); - return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER)); + return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); } if (auth.data[0] == ASN1_APPLICATION(0)) { @@ -776,7 +785,7 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, data_blob_free(&auth); if (destroy_vuid) { /* Kill the intermediate vuid */ - invalidate_vuid(vuid); + invalidate_intermediate_vuid(vuid); } return ret; } @@ -786,24 +795,24 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, /* If we get here it wasn't a negTokenTarg auth packet. */ data_blob_free(&secblob); - + if (!*auth_ntlmssp_state) { /* Kill the intermediate vuid */ - invalidate_vuid(vuid); + invalidate_intermediate_vuid(vuid); /* auth before negotiatiate? */ - return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER)); + return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - - status = auth_ntlmssp_update(*auth_ntlmssp_state, + + status = auth_ntlmssp_update(*auth_ntlmssp_state, auth, &auth_reply); data_blob_free(&auth); - reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, + reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state, &auth_reply, status, True); - + data_blob_free(&auth_reply); /* and tell smbd that we have already replied to this packet */ @@ -1112,7 +1121,7 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, if (!NT_STATUS_IS_OK(status)) { if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { /* Real error - kill the intermediate vuid */ - invalidate_vuid(vuid); + invalidate_intermediate_vuid(vuid); } data_blob_free(&blob1); return ERROR_NT(nt_status_squash(status)); @@ -1140,7 +1149,7 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state); if (!NT_STATUS_IS_OK(status)) { /* Kill the intermediate vuid */ - invalidate_vuid(vuid); + invalidate_intermediate_vuid(vuid); data_blob_free(&blob1); return ERROR_NT(nt_status_squash(status)); } diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c index 0d9dac3e5f..a60f306c7b 100644 --- a/source/smbd/trans2.c +++ b/source/smbd/trans2.c @@ -2223,6 +2223,41 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd return(-1); } +static void samba_extended_info_version(struct smb_extended_info *extended_info) +{ + SMB_ASSERT(extended_info != NULL); + + extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC; + extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24) + | ((SAMBA_VERSION_MINOR & 0xff) << 16) + | ((SAMBA_VERSION_RELEASE & 0xff) << 8); +#ifdef SAMBA_VERSION_REVISION + extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff; +#endif + extended_info->samba_subversion = 0; +#ifdef SAMBA_VERSION_RC_RELEASE + extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24; +#else +#ifdef SAMBA_VERSION_PRE_RELEASE + extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16; +#endif +#endif +#ifdef SAMBA_VERSION_VENDOR_PATCH + extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff); +#endif + extended_info->samba_subversion = 0; +#ifdef SAMBA_VERSION_GIT_COMMIT_TIME + unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME); +#endif + + memset(extended_info->samba_version_string, 0, + sizeof(extended_info->samba_version_string)); + + snprintf (extended_info->samba_version_string, + sizeof(extended_info->samba_version_string), + "%s", samba_version_string()); +} + /**************************************************************************** Reply to a TRANS2_QFSINFO (query filesystem info). ****************************************************************************/ @@ -2330,6 +2365,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsi SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH| (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)| + FILE_UNICODE_ON_DISK| quota_flag); /* FS ATTRIBUTES */ SIVAL(pdata,4,255); /* Max filename component length */ @@ -2511,8 +2547,20 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned } #endif /* HAVE_SYS_QUOTAS */ case SMB_FS_OBJECTID_INFORMATION: + { + /* + * No object id, but we transmit version information. + */ + struct smb_extended_info extended_info; + samba_extended_info_version (&extended_info); + SIVAL(pdata,16,extended_info.samba_magic); + SIVAL(pdata,20,extended_info.samba_version); + SIVAL(pdata,24,extended_info.samba_subversion); + SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate); + memcpy(pdata+36,extended_info.samba_version_string,28); data_len = 64; break; + } /* * Query the version and capabilities of the CIFS UNIX extensions @@ -3299,17 +3347,6 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * } } - nlink = sbuf.st_nlink; - - if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) { - /* NTFS does not seem to count ".." */ - nlink -= 1; - } - - if ((nlink > 0) && delete_pending) { - nlink -= 1; - } - if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) { return ERROR_NT(NT_STATUS_INVALID_LEVEL); } @@ -3327,6 +3364,16 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * if (!mode) mode = FILE_ATTRIBUTE_NORMAL; + nlink = sbuf.st_nlink; + + if (nlink && (mode&aDIR)) { + nlink = 1; + } + + if ((nlink > 0) && delete_pending) { + nlink -= 1; + } + fullpathname = fname; if (!(mode & aDIR)) file_size = get_file_size(sbuf); diff --git a/source/tdb/common/io.c b/source/tdb/common/io.c index 01ada7647b..4b7e33ab65 100644 --- a/source/tdb/common/io.c +++ b/source/tdb/common/io.c @@ -95,7 +95,7 @@ static int tdb_write(struct tdb_context *tdb, tdb_off_t off, /* try once more */ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_write: wrote only " "%d of %d bytes at %d, trying once more\n", - written, len, off)); + (uint32_t)written, len, off)); errno = ENOSPC; written = pwrite(tdb->fd, (void *)((char *)buf+written), len-written, @@ -275,11 +275,12 @@ static int tdb_expand_file(struct tdb_context *tdb, tdb_off_t size, tdb_off_t ad return -1; } else if (written == -1) { TDB_LOG((tdb, TDB_DEBUG_FATAL, "expand_file write of " - "%d bytes failed (%s)\n", n, strerror(errno))); + "%d bytes failed (%s)\n", (uint32_t)n, strerror(errno))); return -1; } else if (written != n) { TDB_LOG((tdb, TDB_DEBUG_WARNING, "expand_file: wrote " - "only %d of %d bytes - retrying\n", written,n)); + "only %d of %d bytes - retrying\n", + (uint32_t)written, (uint32_t)n)); } addition -= written; size += written; diff --git a/source/tdb/tools/tdbtool.c b/source/tdb/tools/tdbtool.c index 2f549ef91b..4bddf76a23 100644 --- a/source/tdb/tools/tdbtool.c +++ b/source/tdb/tools/tdbtool.c @@ -151,7 +151,7 @@ static void print_data(const char *buf,int len) if (len<=0) return; printf("[%03X] ",i); for (i=0;i<len;) { - printf("%02X ",(int)buf[i]); + printf("%02X ",(int)((unsigned char)buf[i])); i++; if (i%8 == 0) printf(" "); if (i%16 == 0) { diff --git a/source/torture/torture.c b/source/torture/torture.c index 8ca2eb5898..aa83f52c23 100644 --- a/source/torture/torture.c +++ b/source/torture/torture.c @@ -4781,6 +4781,47 @@ static BOOL run_error_map_extract(int dummy) { return True; } +static BOOL run_sesssetup_bench(int dummy) +{ + static struct cli_state *c; + NTSTATUS status; + int i; + + if (!(c = open_nbt_connection())) { + return false; + } + + if (!cli_negprot(c)) { + printf("%s rejected the NT-error negprot (%s)\n", host, + cli_errstr(c)); + cli_shutdown(c); + return false; + } + + for (i=0; i<torture_numops; i++) { + status = cli_session_setup( + c, username, + password, strlen(password), + password, strlen(password), + workgroup); + if (!NT_STATUS_IS_OK(status)) { + d_printf("(%s) cli_session_setup failed: %s\n", + __location__, nt_errstr(status)); + return false; + } + + if (!cli_ulogoff(c)) { + d_printf("(%s) cli_ulogoff failed: %s\n", + __location__, cli_errstr(c)); + return false; + } + + c->vuid = 0; + } + + return True; +} + static BOOL run_local_substitute(int dummy) { TALLOC_CTX *mem_ctx; @@ -5026,6 +5067,7 @@ static struct { {"CHKPATH", torture_chkpath_test, 0}, {"FDSESS", run_fdsesstest, 0}, { "EATEST", run_eatest, 0}, + { "SESSSETUP_BENCH", run_sesssetup_bench, 0}, { "LOCAL-SUBSTITUTE", run_local_substitute, 0}, { "LOCAL-GENCACHE", run_local_gencache, 0}, {NULL, NULL, 0}}; diff --git a/source/utils/net.c b/source/utils/net.c index a030531947..99384ad61a 100644 --- a/source/utils/net.c +++ b/source/utils/net.c @@ -677,6 +677,16 @@ static int net_getdomainsid(int argc, const char **argv) "backend knowlege (such as the sid stored in LDAP)\n")); } + /* first check to see if we can even access secrets, so we don't + panic when we can't. */ + + if (!secrets_init()) { + d_fprintf(stderr, "Unable to open secrets.tdb. " + "Can't fetch domainSID for name: %s\n", + get_global_sam_name()); + return 1; + } + /* Generate one, if it doesn't exist */ get_global_sam_sid(); diff --git a/source/utils/net_domain.c b/source/utils/net_domain.c index 5b330d8765..533bb9c698 100644 --- a/source/utils/net_domain.c +++ b/source/utils/net_domain.c @@ -209,10 +209,15 @@ NTSTATUS netdom_join_domain( TALLOC_CTX *mem_ctx, struct cli_state *cli, uint32 num_rids, *name_types, *user_rids; uint32 flags = 0x3e8; uint32 acb_info = ACB_WSTRUST; - uchar pwbuf[516]; + uint32 acct_flags=0; + uint32 fields_present; + uchar pwbuf[532]; SAM_USERINFO_CTR ctr; - SAM_USER_INFO_24 p24; - SAM_USER_INFO_16 p16; + SAM_USER_INFO_25 p25; + const int infolevel = 25; + struct MD5Context md5ctx; + uchar md5buffer[16]; + DATA_BLOB digested_session_key; uchar md4_trust_password[16]; /* Open the domain */ @@ -242,8 +247,13 @@ NTSTATUS netdom_join_domain( TALLOC_CTX *mem_ctx, struct cli_state *cli, /* Don't try to set any acb_info flags other than ACB_WSTRUST */ + acct_flags = SAMR_GENERIC_READ | SAMR_GENERIC_WRITE | + SAMR_GENERIC_EXECUTE | SAMR_STANDARD_WRITEDAC | + SAMR_STANDARD_DELETE | SAMR_USER_SETPASS | SAMR_USER_GETATTR | + SAMR_USER_SETATTR; + DEBUG(10, ("Creating account with flags: %d\n",acct_flags)); status = rpccli_samr_create_dom_user(pipe_hnd, mem_ctx, &domain_pol, - acct_name, acb_info, 0xe005000b, &user_pol, &user_rid); + acct_name, acb_info, acct_flags, &user_pol, &user_rid); if ( !NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) @@ -283,44 +293,25 @@ NTSTATUS netdom_join_domain( TALLOC_CTX *mem_ctx, struct cli_state *cli, status = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol, SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid, &user_pol); - - /* Create a random machine account password */ - - E_md4hash( clear_pw, md4_trust_password); - encode_pw_buffer(pwbuf, clear_pw, STR_UNICODE); - - /* Set password on machine account */ - - ZERO_STRUCT(ctr); - ZERO_STRUCT(p24); - - init_sam_user_info24(&p24, (char *)pwbuf,24); - - ctr.switch_value = 24; - ctr.info.id24 = &p24; - - status = rpccli_samr_set_userinfo(pipe_hnd, mem_ctx, &user_pol, - 24, &cli->user_session_key, &ctr); - - if ( !NT_STATUS_IS_OK(status) ) { - d_fprintf( stderr, "Failed to set password for machine account (%s)\n", - nt_errstr(status)); + if (!NT_STATUS_IS_OK(status)) { return status; } + + /* Create a random machine account password and generate the hash */ - - /* Why do we have to try to (re-)set the ACB to be the same as what - we passed in the samr_create_dom_user() call? When a NT - workstation is joined to a domain by an administrator the - acb_info is set to 0x80. For a normal user with "Add - workstations to the domain" rights the acb_info is 0x84. I'm - not sure whether it is supposed to make a difference or not. NT - seems to cope with either value so don't bomb out if the set - userinfo2 level 0x10 fails. -tpot */ - - ZERO_STRUCT(ctr); - ctr.switch_value = 16; - ctr.info.id16 = &p16; + E_md4hash(clear_pw, md4_trust_password); + encode_pw_buffer(pwbuf, clear_pw, STR_UNICODE); + + generate_random_buffer((uint8*)md5buffer, sizeof(md5buffer)); + digested_session_key = data_blob_talloc(mem_ctx, 0, 16); + + MD5Init(&md5ctx); + MD5Update(&md5ctx, md5buffer, sizeof(md5buffer)); + MD5Update(&md5ctx, cli->user_session_key.data, cli->user_session_key.length); + MD5Final(digested_session_key.data, &md5ctx); + + SamOEMhashBlob(pwbuf, sizeof(pwbuf), &digested_session_key); + memcpy(&pwbuf[516], md5buffer, sizeof(md5buffer)); /* Fill in the additional account flags now */ @@ -332,10 +323,25 @@ NTSTATUS netdom_join_domain( TALLOC_CTX *mem_ctx, struct cli_state *cli, ;; } - init_sam_user_info16(&p16, acb_info); + /* Set password and account flags on machine account */ - status = rpccli_samr_set_userinfo2(pipe_hnd, mem_ctx, &user_pol, 16, - &cli->user_session_key, &ctr); + ZERO_STRUCT(ctr); + ZERO_STRUCT(p25); + + fields_present = ACCT_NT_PWD_SET | ACCT_LM_PWD_SET | ACCT_FLAGS; + init_sam_user_info25P(&p25, fields_present, acb_info, (char *)pwbuf); + + ctr.switch_value = infolevel; + ctr.info.id25 = &p25; + + status = rpccli_samr_set_userinfo2(pipe_hnd, mem_ctx, &user_pol, + infolevel, &cli->user_session_key, &ctr); + + if ( !NT_STATUS_IS_OK(status) ) { + d_fprintf( stderr, "Failed to set password for machine account (%s)\n", + nt_errstr(status)); + return status; + } rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol); cli_rpc_pipe_close(pipe_hnd); /* Done with this pipe */ diff --git a/source/utils/net_rpc.c b/source/utils/net_rpc.c index fee994b751..9944ef0701 100644 --- a/source/utils/net_rpc.c +++ b/source/utils/net_rpc.c @@ -381,7 +381,7 @@ static int rpc_join_usage(int argc, const char **argv) * @param argc Standard main() style argv. Initial components are already * stripped * - * Main 'net_rpc_join()' (where the admain username/password is used) is + * Main 'net_rpc_join()' (where the admin username/password is used) is * in net_rpc_join.c * Try to just change the password, but if that doesn't work, use/prompt * for a username/password. @@ -581,7 +581,8 @@ static NTSTATUS rpc_user_add_internals(const DOM_SID *domain_sid, NTSTATUS result = NT_STATUS_UNSUCCESSFUL; const char *acct_name; uint32 acb_info; - uint32 unknown, user_rid; + uint32 acct_flags=0; + uint32 user_rid; if (argc < 1) { d_printf("User must be specified\n"); @@ -611,10 +612,14 @@ static NTSTATUS rpc_user_add_internals(const DOM_SID *domain_sid, /* Create domain user */ acb_info = ACB_NORMAL; - unknown = 0xe005000b; /* No idea what this is - a permission mask? */ + acct_flags = SAMR_GENERIC_READ | SAMR_GENERIC_WRITE | + SAMR_GENERIC_EXECUTE | SAMR_STANDARD_WRITEDAC | + SAMR_STANDARD_DELETE | SAMR_USER_SETPASS | SAMR_USER_GETATTR | + SAMR_USER_SETATTR; + DEBUG(10, ("Creating account with flags: %d\n",acct_flags)); result = rpccli_samr_create_dom_user(pipe_hnd, mem_ctx, &domain_pol, - acct_name, acb_info, unknown, + acct_name, acb_info, acct_flags, &user_pol, &user_rid); if (!NT_STATUS_IS_OK(result)) { goto done; @@ -5335,7 +5340,8 @@ static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid, NTSTATUS result = NT_STATUS_UNSUCCESSFUL; char *acct_name; uint32 acb_info; - uint32 unknown, user_rid; + uint32 user_rid; + uint32 acct_flags=0; if (argc != 2) { d_printf("Usage: net rpc trustdom add <domain_name> <pw>\n"); @@ -5369,11 +5375,13 @@ static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid, /* Create trusting domain's account */ acb_info = ACB_NORMAL; - unknown = 0xe00500b0; /* No idea what this is - a permission mask? - mimir: yes, most probably it is */ + acct_flags = SAMR_GENERIC_READ | SAMR_GENERIC_WRITE | + SAMR_GENERIC_EXECUTE | SAMR_STANDARD_WRITEDAC | + SAMR_STANDARD_DELETE | SAMR_USER_SETPASS | SAMR_USER_GETATTR | + SAMR_USER_SETATTR; result = rpccli_samr_create_dom_user(pipe_hnd, mem_ctx, &domain_pol, - acct_name, acb_info, unknown, + acct_name, acb_info, acct_flags, &user_pol, &user_rid); if (!NT_STATUS_IS_OK(result)) { goto done; diff --git a/source/utils/net_rpc_join.c b/source/utils/net_rpc_join.c index d23bd76751..fe5cef1803 100644 --- a/source/utils/net_rpc_join.c +++ b/source/utils/net_rpc_join.c @@ -43,7 +43,7 @@ **/ int net_rpc_join_ok(const char *domain, const char *server, struct in_addr *ip ) { - uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS|NETLOGON_NEG_SCHANNEL; + uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS|NETLOGON_NEG_SCHANNEL; struct cli_state *cli = NULL; struct rpc_pipe_client *pipe_hnd = NULL; struct rpc_pipe_client *netlogon_pipe = NULL; @@ -114,7 +114,7 @@ int net_rpc_join_newstyle(int argc, const char **argv) struct cli_state *cli; TALLOC_CTX *mem_ctx; uint32 acb_info = ACB_WSTRUST; - uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS|(lp_client_schannel() ? NETLOGON_NEG_SCHANNEL : 0); + uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS|(lp_client_schannel() ? NETLOGON_NEG_SCHANNEL : 0); uint32 sec_channel_type; struct rpc_pipe_client *pipe_hnd = NULL; @@ -142,6 +142,7 @@ int net_rpc_join_newstyle(int argc, const char **argv) uint32 flags = 0x3e8; char *acct_name; const char *const_acct_name; + uint32 acct_flags=0; /* check what type of join */ if (argc >= 0) { @@ -229,9 +230,14 @@ int net_rpc_join_newstyle(int argc, const char **argv) strlower_m(acct_name); const_acct_name = acct_name; + acct_flags = SAMR_GENERIC_READ | SAMR_GENERIC_WRITE | + SAMR_GENERIC_EXECUTE | SAMR_STANDARD_WRITEDAC | + SAMR_STANDARD_DELETE | SAMR_USER_SETPASS | SAMR_USER_GETATTR | + SAMR_USER_SETATTR; + DEBUG(10, ("Creating account with flags: %d\n",acct_flags)); result = rpccli_samr_create_dom_user(pipe_hnd, mem_ctx, &domain_pol, acct_name, acb_info, - 0xe005000b, &user_pol, + acct_flags, &user_pol, &user_rid); if (!NT_STATUS_IS_OK(result) && diff --git a/source/utils/net_rpc_samsync.c b/source/utils/net_rpc_samsync.c index d8ddff20bc..bd209de0c1 100644 --- a/source/utils/net_rpc_samsync.c +++ b/source/utils/net_rpc_samsync.c @@ -238,7 +238,7 @@ NTSTATUS rpc_samdump_internals(const DOM_SID *domain_sid, NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; uchar trust_password[16]; - uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS; + uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS; uint32 sec_channel_type = 0; if (!secrets_fetch_trust_account_password(domain_name, diff --git a/source/utils/net_sam.c b/source/utils/net_sam.c index bf397803bc..e01142e6d1 100644 --- a/source/utils/net_sam.c +++ b/source/utils/net_sam.c @@ -42,7 +42,7 @@ static int net_sam_userset(int argc, const char **argv, const char *field, return -1; } - if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_ISOLATED, + if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_LOCAL, &dom, &name, &sid, &type)) { d_fprintf(stderr, "Could not find name %s\n", argv[0]); return -1; @@ -139,7 +139,7 @@ static int net_sam_set_userflag(int argc, const char **argv, const char *field, return -1; } - if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_ISOLATED, + if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_LOCAL, &dom, &name, &sid, &type)) { d_fprintf(stderr, "Could not find name %s\n", argv[0]); return -1; @@ -223,7 +223,7 @@ static int net_sam_set_pwdmustchangenow(int argc, const char **argv) return -1; } - if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_ISOLATED, + if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_LOCAL, &dom, &name, &sid, &type)) { d_fprintf(stderr, "Could not find name %s\n", argv[0]); return -1; @@ -284,7 +284,7 @@ static int net_sam_set_comment(int argc, const char **argv) return -1; } - if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_ISOLATED, + if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_LOCAL, &dom, &name, &sid, &type)) { d_fprintf(stderr, "Could not find name %s\n", argv[0]); return -1; @@ -639,7 +639,7 @@ static int net_sam_addmem(int argc, const char **argv) return -1; } - if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_ISOLATED, + if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_LOCAL, &groupdomain, &groupname, &group, &grouptype)) { d_fprintf(stderr, "Could not find group %s\n", argv[0]); return -1; @@ -647,7 +647,7 @@ static int net_sam_addmem(int argc, const char **argv) /* check to see if the member to be added is a name or a SID */ - if (!lookup_name(tmp_talloc_ctx(), argv[1], LOOKUP_NAME_ISOLATED, + if (!lookup_name(tmp_talloc_ctx(), argv[1], LOOKUP_NAME_LOCAL, &memberdomain, &membername, &member, &membertype)) { /* try it as a SID */ @@ -712,13 +712,13 @@ static int net_sam_delmem(int argc, const char **argv) return -1; } - if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_ISOLATED, + if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_LOCAL, &groupdomain, &groupname, &group, &grouptype)) { d_fprintf(stderr, "Could not find group %s\n", argv[0]); return -1; } - if (!lookup_name(tmp_talloc_ctx(), argv[1], LOOKUP_NAME_ISOLATED, + if (!lookup_name(tmp_talloc_ctx(), argv[1], LOOKUP_NAME_LOCAL, &memberdomain, &membername, &member, NULL)) { if (!string_to_sid(&member, argv[1])) { d_fprintf(stderr, "Could not find member %s\n", @@ -770,7 +770,7 @@ static int net_sam_listmem(int argc, const char **argv) return -1; } - if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_ISOLATED, + if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_LOCAL, &groupdomain, &groupname, &group, &grouptype)) { d_fprintf(stderr, "Could not find group %s\n", argv[0]); return -1; @@ -918,7 +918,7 @@ static int net_sam_show(int argc, const char **argv) return -1; } - if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_ISOLATED, + if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_LOCAL, &dom, &name, &sid, &type)) { d_fprintf(stderr, "Could not find name %s\n", argv[0]); return -1; diff --git a/source/utils/smbcacls.c b/source/utils/smbcacls.c index 82cae03720..6d4fbaa5d1 100644 --- a/source/utils/smbcacls.c +++ b/source/utils/smbcacls.c @@ -788,7 +788,8 @@ static struct cli_state *connect_one(const char *share) &ip, 0, share, "?????", cmdline_auth_info.username, lp_workgroup(), - cmdline_auth_info.password, 0, + cmdline_auth_info.password, + cmdline_auth_info.use_kerberos ? CLI_FULL_CONNECTION_USE_KERBEROS : 0, cmdline_auth_info.signing_state, NULL))) { return c; } else { diff --git a/source/utils/smbpasswd.c b/source/utils/smbpasswd.c index 7460662441..ef4e20bb7f 100644 --- a/source/utils/smbpasswd.c +++ b/source/utils/smbpasswd.c @@ -96,6 +96,12 @@ static int process_options(int argc, char **argv, int local_flags) while ((ch = getopt(argc, argv, "c:axdehminjr:sw:R:D:U:LW")) != EOF) { switch(ch) { case 'L': +#if !defined(DEVELOPER) + if (getuid() != 0) { + fprintf(stderr, "smbpasswd -L can only be used by root.\n"); + exit(1); + } +#endif local_flags |= LOCAL_AM_ROOT; break; case 'c': diff --git a/source/utils/status.c b/source/utils/status.c index df742f73e7..0dc1253a97 100644 --- a/source/utils/status.c +++ b/source/utils/status.c @@ -367,6 +367,16 @@ static int traverse_sessionid(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, vo if ( show_locks ) { int ret; + tdb = tdb_open_log(lock_path("locking.tdb"), 0, TDB_DEFAULT, O_RDONLY, 0); + + if (!tdb) { + d_printf("%s not initialised\n", lock_path("locking.tdb")); + d_printf("This is normal if an SMB client has never connected to your server.\n"); + exit(0); + } else { + tdb_close(tdb); + } + if (!locking_init(1)) { d_printf("Can't initialise locking module - exiting\n"); exit(1); |