From b3651817a4da8c53128cfd07188e809e65d459d4 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 2 Dec 2005 14:18:11 +0000 Subject: r12018: more 3.0.21 changes. This is a full sync except for changes to rpc-server/rpc_samr*.c --- examples/logon/mklogon/mklogon.conf | 75 ++++---- examples/logon/mklogon/mklogon.pl | 50 +++--- examples/perfcounter/perf_writer_util.c | 6 +- source/Makefile.in | 4 +- source/auth/auth_rhosts.c | 30 ++++ source/auth/auth_util.c | 30 ---- source/client/client.c | 13 +- source/client/mount.cifs.c | 164 ++++++++++++----- source/client/smbspool.c | 15 +- source/include/passdb.h | 15 +- source/include/rpc_dce.h | 30 +++- source/include/rpc_netlogon.h | 49 +++++ source/include/rpc_samr.h | 87 ++++++++- source/include/talloc.h | 38 ++-- source/lib/talloc.c | 295 +++++++++++++++++++++++------- source/lib/tallocmsg.c | 15 +- source/lib/util_unistr.c | 28 +++ source/libsmb/cliconnect.c | 1 + source/libsmb/clientgen.c | 34 ++++ source/nsswitch/wbinfo.c | 21 ++- source/param/loadparm.c | 4 + source/passdb/lookup_sid.c | 55 ++++-- source/passdb/passdb.c | 75 ++++---- source/passdb/pdb_interface.c | 73 ++++---- source/passdb/pdb_ldap.c | 43 ++--- source/passdb/util_sam_sid.c | 25 ++- source/printing/print_svid.c | 29 +++ source/registry/reg_eventlog.c | 8 + source/registry/reg_printing.c | 11 +- source/rpc_client/cli_netlogon.c | 164 +++++++++++++++++ source/rpc_client/cli_samr.c | 99 +++++++++- source/rpc_parse/parse_lsa.c | 42 +++++ source/rpc_parse/parse_net.c | 308 ++++++++++++++++++++++++++++++++ source/rpc_parse/parse_samr.c | 294 ++++++++++++++++++++++++++++-- source/rpc_server/srv_netlog_nt.c | 29 +++ source/rpc_server/srv_pipe.c | 49 +++++ source/rpc_server/srv_pipe_hnd.c | 81 ++++++++- source/rpc_server/srv_samr_nt.c | 141 ++++++++++----- source/rpc_server/srv_spoolss_nt.c | 30 ++-- source/rpc_server/srv_srvsvc_nt.c | 5 +- source/rpc_server/srv_util.c | 29 --- source/rpcclient/cmd_lsarpc.c | 16 +- source/rpcclient/cmd_netlogon.c | 56 ++++++ source/rpcclient/cmd_samr.c | 107 ++++++++--- source/smbd/dosmode.c | 7 +- source/smbd/filename.c | 13 ++ source/utils/smbcontrol.c | 4 +- source/utils/testparm.c | 5 + 48 files changed, 2322 insertions(+), 480 deletions(-) diff --git a/examples/logon/mklogon/mklogon.conf b/examples/logon/mklogon/mklogon.conf index 1f1faa77e38..b04708977c4 100644 --- a/examples/logon/mklogon/mklogon.conf +++ b/examples/logon/mklogon/mklogon.conf @@ -6,72 +6,73 @@ # infront of your # on a comment it breaks ... # logging = yes # Should Logging be enabled (YES,ON,1 or NO,OFF,0)(if not specified defaults to no) # logdir = "/root/perl" # What is the base directory the logs should be stored. -# logfile = "userlogs.txt" # What should the file be named. -# logtype = file (default) # file will log to the file specified, syslog is well... the system logs ;) +# logfile = "userlist.txt" # What should the file be named. +# VERY IMPORTANT anything that has a "\" (backslash) in it ex. "C:\" MUST be changed to a double "\\" for +# it to be used in the script. ex. "C:\\" [global] logging = yes logdir = "/home/samba/netlogon" logfile = "UserLogs.txt" -logtype = system mkprofile = 1 timesync = yes sambaconf = "/etc/samba/smb.conf" +logtype = file # Change and uncomment the below value to force the servername, some clients ocassionally # have trouble picking up the right servername so it may need to be set. It CANNOT be left blank AND uncommented. -# servername = staticservername +servername = "TIGER" [common] public = P:, public home = H:, /home [groupmap] -admin = Y:, UTILS -adm = R:, NETLOGON +adm = R:, NETLOGON, Y:, ARCHIVES +teachers = S:, RECORDS, X:, SIS +plato = T:, PLATO +webpage = W:, WEB +hsoffice = N:, HSOFFICE, Q:, COMMON, X:, SIS +suoffice = N:, super, Q:, COMMON, X:, SIS +emoffice = N:, emOFFICE, Q:, COMMON, X:, SIS +tech = O:, utils +yearbook = Y:, yearbook [usermap] -user1 = G:, GHOST -beanbags = Q:, STAR -avinst = P:\\vexira\\vexprof.bat +rnance = G:, GHOST, I:, TTL, Y:, ARCHIVES, R:, NETLOGON, X:, SIS +lwatts = G:, GHOST, I:, TTL, Y:, ARCHIVES, R:, NETLOGON, X:, SIS +droot = U:, stuhomes +2007mbk = Y:, yearbook +2008mll = Y:, yearbook +2008jtj = Y:, yearbook +2007tja = Y:, yearbook +2007hms = Y:, yearbook +2006dpv = Y:, yearbook +2006jwb2 = Y:, yearbook +2007npd = Y:, yearbook +astewart = Y:, yearbook + + # Here is where things get confusing, you can assign a computer, or make a group of computers. -# The same context will go for ip address's as well. +# The same context will go for ip address's as well, however you can also specify ip ranges, +# but I have not yet figured out how to do multiple ranges. # Use the following examples for help. # To define a single computer to do commands # mymachinename = command1, command2 # To define a group of computers to do commands # mymachinegroup = machinename1, machinename2 -# [preformcommands] +# [performcommands] # mymachinegroup = command1,command2 +# iprangegroup1 = 10.1.2.1 - 10.1.3.1 -[machines] -#emints 1 is jf -emints1 = school-w88zfod9, school-o8axvv6t, school-mmtudgbo, school-dpokmajd, school-m84hx4iw, school-74548k1j, school-vou4gdap, school-qfuw5uho -#emints 2 is kh -emints2 = school-w7loulcx, school-2tbh64eu, school-uunqieuz, school-pow35do4, school-x0v0cbiz, school-zu5qyjhw, school-l4q4j32o -[ip] -ipgroup1 = 10.5.1.1 - 10.5.1.10, 10.1.1.255/24 -ipgroup2 = 10.1.1.1 -# This is the section where you can specify things according to the operating system of the client. -# The clients OS -- Windows 95/98/ME (Win95), Windows NT (WinNT), -# Windows 2000 (Win2K), Windows XP (WinXP), and Windows 2003 -# (Win2K3). Anything else will be known as ``UNKNOWN'' -# That snippet is directly from man smb.conf. -# +[machines] -[os] -Win95 = REM your computer is windows 9x based -WinNT = -Win2K = -WinXP = -Win2K3 = -UNKNOWN = +[ip] +sixthemints = 10.1.5.201 - 10.1.5.215 -[preformcommands] -emints1 = START \\\\JF-TEACHER\\Brother, START \\\\JF-TEACHER\\Canon, REGEDIT /S P:\\SETHOME-JF.REG, your in emints 1 -emints2 = START \\\\s0034292474\\Brother, START \\\\s0034292474\\Canon, REGEDIT /S P:\\SETHOME-KH.REG -ipgroup1 = echo your in the ip group -ipgroup2 = echo your in the ip group 2, start command.com +[performcommands] +common = "XCOPY P:\\TYPEN32.INI C:\\WINDOWS\\ /Y \>NUL", "XCOPY P:\\ARPROGRAMS\\DBLOCATION\\\*\.\* C:\\WINDOWS\\ /Y \>NUL", "XCOPY P:\\EMACTIVITIES\\EMGAMESPREFS.INI C:\\WINDOWS\\ /Y \>NUL", "PATH\=\%PATH\%;p:\\PXPerl\parrot\\bin;p:\\PXPerl\\bin" +sixthemints = "start \\\\10.1.5.20\\printer" diff --git a/examples/logon/mklogon/mklogon.pl b/examples/logon/mklogon/mklogon.pl index 88ee97c9799..8bea7b22d36 100644 --- a/examples/logon/mklogon/mklogon.pl +++ b/examples/logon/mklogon/mklogon.pl @@ -22,8 +22,8 @@ # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # -# Version: 1.1 Beta -# Revised: 06/28/2005 +# Version: 1.0 (Stable) +# Revised: 07/28/2005 # Comments... # Working on logging to the system logs, Logs user activity, but not errors yet. @@ -144,11 +144,11 @@ if ( defined($smbprof) ) { print "$smbprof \n"; print "$dir2 \n"; if ( !-e $dir2 ) { - print "Creating " . $user . "'s profile \n"; + print "Creating " . $user . "'s profile with a uid of $uid\n"; mkdir $smbprof; mkdir $dir2; chomp($user); - chown $uid, $gid, $smbprof; +# chown $uid, $gid, $smbprof; chown $uid, $gid, $dir2; } else { print $user . "'s profile already exists \n"; @@ -174,6 +174,13 @@ for my $key ( keys %$common ) { drive_map( @{ $common->{$key} } ); } +my @perform_common = $cfg->param("performcommands.common"); +if ( defined( $perform_common[0] ) ) { + foreach (@perform_common) { + print LOGON "$_ \r\n"; + } +} + # Map shares on a per user basis. drive_map(@username); @@ -195,30 +202,33 @@ for my $key ( keys %$compname ) { if ( ref $test eq 'ARRAY' ) { foreach (@$test) { if ( $_ eq $machine ) { - my $preformit = $cfg->param("preformcommands.$key"); - if ( defined($preformit) ) { - if ( ref $preformit ) { - foreach (@$preformit) { print LOGON "$_ \r\n"; } + my $performit = $cfg->param("performcommands.$key"); + if ( defined($performit) ) { + if ( ref $performit ) { + foreach (@$performit) { print LOGON "$_ \r\n"; } } else { - print LOGON "$preformit \r\n"; + print LOGON "$performit \r\n"; } } } } } elsif ( $test eq $machine ) { - my $preformit = $cfg->param("preformcommands.$key"); - if ( defined($preformit) ) { - if ( ref $preformit ) { - foreach (@$preformit) { print LOGON "$_ \r\n"; } + my $performit = $cfg->param("performcommands.$key"); + if ( defined($performit) ) { + if ( ref $performit ) { + foreach (@$performit) { print LOGON "$_ \r\n"; } } else { - print LOGON "$preformit \r\n"; + print LOGON "$performit \r\n"; } } } } # Here is where we test the ip address against the client to see if they have "Special Mapping" +# A huge portion of the ip matching code was made by +# Carsten Schaub (rcsu in the #samba chan on freenode.net) + my $val; for my $key ( sort keys %$ipname ) { if ( ref $ipname->{$key} eq 'ARRAY' ) { @@ -234,12 +244,12 @@ sub getipval { my ( $range, $rangename ) = @_; if ( parse( $ip, ipmap($range) ) ) { if ( $val eq 'true' ) { - my $preformit = $cfg->param("preformcommands.$rangename"); - if ( defined($preformit) ) { - if ( ref $preformit ) { - foreach (@$preformit) { print LOGON "$_ \r\n"; } + my $performit = $cfg->param("performcommands.$rangename"); + if ( defined($performit) ) { + if ( ref $performit ) { + foreach (@$performit) { print LOGON "$_ \r\n"; } } else { - print LOGON "$preformit \r\n"; + print LOGON "$performit \r\n"; } } } elsif ( $val eq 'false' ) { @@ -307,7 +317,7 @@ sub drive_map { my $sharename = $data[$i]; $i++; if ( $sharename eq '/home' ) { - print LOGON uc("NET USE $driveletter $sharename \/Y \r\n"); + print LOGON uc("NET USE $driveletter \\\\$server\\$user \/Y \r\n"); } else { print LOGON uc("NET USE $driveletter \\\\$server\\$sharename \/Y \r\n"); diff --git a/examples/perfcounter/perf_writer_util.c b/examples/perfcounter/perf_writer_util.c index bb6422bac23..78a99fef494 100644 --- a/examples/perfcounter/perf_writer_util.c +++ b/examples/perfcounter/perf_writer_util.c @@ -77,7 +77,7 @@ void usage(char *progname) fprintf(stderr, "Usage: %s [-d] [-f ].\n", progname); fprintf(stderr, "\t-d: run as a daemon.\n"); fprintf(stderr, "\t-f : path where the TDB files reside.\n"); - fprintf(stderr, "\t\tDEFAULT is /tmp/counters\n"); + fprintf(stderr, "\t\tDEFAULT is /var/lib/samba/perfmon\n"); exit(1); } @@ -116,13 +116,13 @@ void setup_file_paths(RuntimeSettings *rt) if(strlen(rt->dbDir) == 0) { /* No file path was passed in, use default */ - sprintf(rt->dbDir, "/tmp/counters"); + sprintf(rt->dbDir, "/var/lib/samba/perfmon"); } sprintf(rt->nameFile, "%s/names.tdb", rt->dbDir); sprintf(rt->counterFile, "%s/data.tdb", rt->dbDir); - mkdir(rt->dbDir, O_RDWR); + mkdir(rt->dbDir, 0755); rt->cnames = tdb_open(rt->nameFile, 0, TDB_CLEAR_IF_FIRST, O_RDWR | O_CREAT, 0644); rt->cdata = tdb_open(rt->counterFile, 0, TDB_CLEAR_IF_FIRST, O_RDWR | O_CREAT, 0644); diff --git a/source/Makefile.in b/source/Makefile.in index cca0715a3aa..888a0ebe344 100644 --- a/source/Makefile.in +++ b/source/Makefile.in @@ -106,7 +106,7 @@ LIBSMBSHAREMODES=bin/libsmbsharemodes.a @LIBSMBSHAREMODES_SHARED@ LIBSMBSHAREMODES_MAJOR=0 LIBSMBSHAREMODES_MINOR=1 -FLAGS1 = $(CFLAGS) @FLAGS1@ -Iinclude -I$(srcdir)/include -I$(srcdir)/ubiqx -I$(srcdir)/tdb @SMBWRAP_INC@ -I. $(CPPFLAGS) -I$(srcdir) +FLAGS1 = $(CFLAGS) @FLAGS1@ -Iinclude -I$(srcdir)/include -I$(srcdir)/ubiqx -I$(srcdir)/tdb @SMBWRAP_INC@ -I. $(CPPFLAGS) -I$(srcdir) -D_SAMBA_BUILD_ FLAGS2 = FLAGS3 = FLAGS4 = @@ -298,7 +298,7 @@ RPC_SPOOLSS_OBJ = rpc_server/srv_spoolss.o rpc_server/srv_spoolss_nt.o RPC_EVENTLOG_OBJ = rpc_server/srv_eventlog.o rpc_server/srv_eventlog_nt.o rpc_server/srv_eventlog_lib.o -RPC_PIPE_OBJ = rpc_server/srv_pipe_hnd.o rpc_server/srv_util.o \ +RPC_PIPE_OBJ = rpc_server/srv_pipe_hnd.o \ rpc_server/srv_pipe.o rpc_server/srv_lsa_hnd.o RPC_ECHO_OBJ = rpc_server/srv_echo.o rpc_server/srv_echo_nt.o diff --git a/source/auth/auth_rhosts.c b/source/auth/auth_rhosts.c index b295df9328f..b561e3d42be 100644 --- a/source/auth/auth_rhosts.c +++ b/source/auth/auth_rhosts.c @@ -23,6 +23,36 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_AUTH +/**************************************************************************** + Create a SAM_ACCOUNT - either by looking in the pdb, or by faking it up from + unix info. +****************************************************************************/ + +static NTSTATUS auth_get_sam_account(const char *user, SAM_ACCOUNT **account) +{ + BOOL pdb_ret; + NTSTATUS nt_status; + if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam(account))) { + return nt_status; + } + + become_root(); + pdb_ret = pdb_getsampwnam(*account, user); + unbecome_root(); + + if (!pdb_ret) { + + struct passwd *pass = Get_Pwnam(user); + if (!pass) + return NT_STATUS_NO_SUCH_USER; + + if (!NT_STATUS_IS_OK(nt_status = pdb_fill_sam_pw(*account, pass))) { + return nt_status; + } + } + return NT_STATUS_OK; +} + /**************************************************************************** Read the a hosts.equiv or .rhosts file and check if it allows this user from this machine. diff --git a/source/auth/auth_util.c b/source/auth/auth_util.c index 6a92c8782e8..61cb7f31cc7 100644 --- a/source/auth/auth_util.c +++ b/source/auth/auth_util.c @@ -50,36 +50,6 @@ static int smb_create_user(const char *domain, const char *unix_username, const return ret; } -/**************************************************************************** - Create a SAM_ACCOUNT - either by looking in the pdb, or by faking it up from - unix info. -****************************************************************************/ - -NTSTATUS auth_get_sam_account(const char *user, SAM_ACCOUNT **account) -{ - BOOL pdb_ret; - NTSTATUS nt_status; - if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam(account))) { - return nt_status; - } - - become_root(); - pdb_ret = pdb_getsampwnam(*account, user); - unbecome_root(); - - if (!pdb_ret) { - - struct passwd *pass = Get_Pwnam(user); - if (!pass) - return NT_STATUS_NO_SUCH_USER; - - if (!NT_STATUS_IS_OK(nt_status = pdb_fill_sam_pw(*account, pass))) { - return nt_status; - } - } - return NT_STATUS_OK; -} - /**************************************************************************** Create an auth_usersupplied_data structure ****************************************************************************/ diff --git a/source/client/client.c b/source/client/client.c index 47a45b8a53b..f95bbea6718 100644 --- a/source/client/client.c +++ b/source/client/client.c @@ -3084,11 +3084,20 @@ static void readline_callback(void) session keepalives and then drop them here. */ if (FD_ISSET(cli->fd,&fds)) { - receive_smb(cli->fd,cli->inbuf,0); + if (!receive_smb(cli->fd,cli->inbuf,0)) { + DEBUG(0, ("Read from server failed, maybe it closed the " + "connection\n")); + return; + } goto again; } - cli_chkpath(cli, "\\"); + /* Ping the server to keep the connection alive using SMBecho. */ + { + unsigned char garbage[16]; + memset(garbage, 0xf0, sizeof(garbage)); + cli_echo(cli, garbage, sizeof(garbage)); + } } /**************************************************************************** diff --git a/source/client/mount.cifs.c b/source/client/mount.cifs.c index 5750deb31ca..ed88c92c626 100755 --- a/source/client/mount.cifs.c +++ b/source/client/mount.cifs.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -39,7 +40,7 @@ #include #define MOUNT_CIFS_VERSION_MAJOR "1" -#define MOUNT_CIFS_VERSION_MINOR "8" +#define MOUNT_CIFS_VERSION_MINOR "10" #ifndef MOUNT_CIFS_VENDOR_SUFFIX #define MOUNT_CIFS_VENDOR_SUFFIX "" @@ -83,11 +84,16 @@ static void mount_cifs_usage(void) printf(" to a local directory.\n\nOptions:\n"); printf("\tuser=\n\tpass=\n\tdom=\n"); printf("\nLess commonly used options:"); - printf("\n\tcredentials=,guest,perm,noperm,setuids,nosetuids,rw,ro,\n\tsep=,iocharset=,suid,nosuid,exec,noexec,serverino,\n\tdirectio,mapchars,nomapchars"); - printf("\n\nOptions not needed for servers supporting CIFS Unix extensions\n\t(e.g. most Samba versions):"); - printf("\n\tuid=,gid=,dir_mode=,file_mode="); + printf("\n\tcredentials=,guest,perm,noperm,setuids,nosetuids,rw,ro,"); + printf("\n\tsep=,iocharset=,suid,nosuid,exec,noexec,serverino,"); + printf("\n\tdirectio,mapchars,nomapchars,nolock,servernetbiosname="); + printf("\n\nOptions not needed for servers supporting CIFS Unix extensions"); + printf("\n\t(e.g. unneeded for mounts to most Samba versions):"); + printf("\n\tuid=,gid=,dir_mode=,file_mode=,sfu"); printf("\n\nRarely used options:"); - printf("\n\tport=,rsize=,wsize=,unc=,ip=,\n\tdev,nodev,nouser_xattr,netbiosname,hard,soft,intr,nointr,noacl"); + printf("\n\tport=,rsize=,wsize=,unc=,ip=,"); + printf("\n\tdev,nodev,nouser_xattr,netbiosname=,hard,soft,intr,"); + printf("\n\tnointr,ignorecase,noposixpaths,noacl"); printf("\n\nOptions are described in more detail in the manual page"); printf("\n\tman 8 mount.cifs\n"); printf("\nTo display the version number of the mount helper:"); @@ -127,8 +133,10 @@ static int open_cred_file(char * file_name) if(fs == NULL) return errno; line_buf = malloc(4096); - if(line_buf == NULL) + if(line_buf == NULL) { + fclose(fs); return -ENOMEM; + } while(fgets(line_buf,4096,fs)) { /* parse line from credential file */ @@ -282,21 +290,23 @@ static int get_password_from_file(int file_descript, char * filename) return rc; } -static int parse_options(char * options, int * filesys_flags) +static int parse_options(char ** optionsp, int * filesys_flags) { char * data; char * percent_char = NULL; char * value = NULL; char * next_keyword = NULL; + char * out = NULL; + int out_len = 0; + int word_len; int rc = 0; - if (!options) + if (!optionsp || !*optionsp) return 1; - else - data = options; + data = *optionsp; if(verboseflag) - printf("parsing options: %s\n", options); + printf("parsing options: %s\n", data); /* BB fixme check for separator override BB */ @@ -314,7 +324,7 @@ static int parse_options(char * options, int * filesys_flags) /* temporarily null terminate end of keyword=value pair */ if(next_keyword) - *next_keyword = 0; + *next_keyword++ = 0; /* temporarily null terminate keyword to make keyword and value distinct */ if ((value = strchr(data, '=')) != NULL) { @@ -324,7 +334,7 @@ static int parse_options(char * options, int * filesys_flags) if (strncmp(data, "users",5) == 0) { if(!value || !*value) { - strncpy(data,",,,,,",5); + goto nocopy; } } else if (strncmp(data, "user_xattr",10) == 0) { /* do nothing - need to skip so not parsed as user name */ @@ -336,10 +346,7 @@ static int parse_options(char * options, int * filesys_flags) printf("\nskipping empty user mount parameter\n"); /* remove the parm since it would otherwise be confusing to the kernel code which would think it was a real username */ - data[0] = ','; - data[1] = ','; - data[2] = ','; - data[3] = ','; + goto nocopy; } else { printf("username specified with no parameter\n"); return 1; /* needs_arg; */ @@ -458,10 +465,34 @@ static int parse_options(char * options, int * filesys_flags) } else if (strncmp(data, "uid", 3) == 0) { if (value && *value) { 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(); + } } } 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(); + } } /* fmask and dmask synonyms for people used to smbfs syntax */ } else if (strcmp(data, "file_mode") == 0 || strcmp(data, "fmask")==0) { @@ -504,6 +535,9 @@ static int parse_options(char * options, int * filesys_flags) *filesys_flags &= ~MS_NOSUID; } else if (strncmp(data, "nodev", 5) == 0) { *filesys_flags |= MS_NODEV; + } else if ((strncmp(data, "nobrl", 5) == 0) || + (strncmp(data, "nolock", 6) == 0)) { + *filesys_flags &= ~MS_MANDLOCK; } else if (strncmp(data, "dev", 3) == 0) { *filesys_flags &= ~MS_NODEV; } else if (strncmp(data, "noexec", 6) == 0) { @@ -513,11 +547,7 @@ static int parse_options(char * options, int * filesys_flags) } else if (strncmp(data, "guest", 5) == 0) { got_password=1; /* remove the parm since it would otherwise be logged by kern */ - data[0] = ','; - data[1] = ','; - data[2] = ','; - data[3] = ','; - data[4] = ','; + goto nocopy; } else if (strncmp(data, "ro", 2) == 0) { *filesys_flags |= MS_RDONLY; } else if (strncmp(data, "rw", 2) == 0) { @@ -545,21 +575,29 @@ static int parse_options(char * options, int * filesys_flags) } */ /* nothing to do on those four mount options above. Just pass to kernel and ignore them here */ - /* move to next option */ - data = next_keyword+1; + /* Copy (possibly modified) option to out */ + word_len = strlen(data); + if (value) + word_len += 1 + strlen(value); - /* put overwritten equals sign back */ - if(value) { - value--; - *value = '='; + out = realloc(out, out_len + word_len + 2); + if (out == NULL) { + perror("malloc"); + exit(1); } - - /* put previous overwritten comma back */ - if(next_keyword) - *next_keyword = ','; /* BB handle sep= */ + + if (out_len) + out[out_len++] = ','; + if (value) + sprintf(out + out_len, "%s=%s", data, value); else - data = NULL; + sprintf(out + out_len, "%s", data); + out_len = strlen(out); + +nocopy: + data = next_keyword; } + *optionsp = out; return 0; } @@ -570,13 +608,15 @@ static void check_for_comma(char ** ppasswrd) char *pass; int i,j; int number_of_commas = 0; - int len = strlen(*ppasswrd); + int len; if(ppasswrd == NULL) return; else (pass = *ppasswrd); + len = strlen(pass); + for(i=0;i 1023) { printf("mount error: UNC name too long"); @@ -715,6 +754,13 @@ static char * parse_server(char ** punc_name) if(share) { free_share_name = 1; *punc_name = malloc(length+3); + if(*punc_name == NULL) { + /* put the original string back if + no memory left */ + *punc_name = unc_name; + return NULL; + } + *share = '/'; strncpy((*punc_name)+2,unc_name,length); unc_name = *punc_name; @@ -744,8 +790,7 @@ continue_unc_parsing: return NULL; } if(host_entry == NULL) { - printf("mount error: could not find target server. TCP name %s not found ", unc_name); - printf(" rc = %d\n",rc); + printf("mount error: could not find target server. TCP name %s not found\n", unc_name); return NULL; } else { /* BB should we pass an alternate version of the share name as Unicode */ @@ -905,10 +950,44 @@ int main(int argc, char ** argv) wsize = atoi(optarg); break; case '1': - uid = atoi(optarg); + if (isdigit(*optarg)) { + char *ep; + + uid = strtoul(optarg, &ep, 10); + if (*ep) { + printf("bad uid value \"%s\"\n", optarg); + exit(1); + } + } else { + struct passwd *pw; + + if (!(pw = getpwnam(optarg))) { + printf("bad user name \"%s\"\n", optarg); + exit(1); + } + uid = pw->pw_uid; + endpwent(); + } break; case '2': - gid = atoi(optarg); + if (isdigit(*optarg)) { + char *ep; + + gid = strtoul(optarg, &ep, 10); + if (*ep) { + printf("bad gid value \"%s\"\n", optarg); + exit(1); + } + } else { + struct group *gr; + + if (!(gr = getgrnam(optarg))) { + printf("bad user name \"%s\"\n", optarg); + exit(1); + } + gid = gr->gr_gid; + endpwent(); + } break; case 'u': got_user = 1; @@ -954,7 +1033,7 @@ int main(int argc, char ** argv) get_password_from_file(0, getenv("PASSWD_FILE")); } - if (orgoptions && parse_options(orgoptions, &flags)) + if (orgoptions && parse_options(&orgoptions, &flags)) return -1; ipaddr = parse_server(&share_name); if((ipaddr == NULL) && (got_ip == 0)) { @@ -1018,6 +1097,9 @@ mount_retry: optlen = 0; if(share_name) optlen += strlen(share_name) + 4; + else { + printf("No server share name specified\n"); + } if(user_name) optlen += strlen(user_name) + 6; if(ipaddr) @@ -1126,8 +1208,6 @@ mount_retry: strcat(mountent.mnt_opts,"rw"); if(flags & MS_MANDLOCK) strcat(mountent.mnt_opts,",mand"); - else - strcat(mountent.mnt_opts,",nomand"); if(flags & MS_NOEXEC) strcat(mountent.mnt_opts,",noexec"); if(flags & MS_NOSUID) diff --git a/source/client/smbspool.c b/source/client/smbspool.c index aff241adeed..7fe918413d5 100644 --- a/source/client/smbspool.c +++ b/source/client/smbspool.c @@ -461,6 +461,7 @@ smb_connect(const char *workgroup, /* I - Workgroup */ { struct cli_state *cli; /* New connection */ pstring myname; /* Client name */ + struct passwd *pwd; /* * Get the names and addresses of the client and server... @@ -488,12 +489,24 @@ smb_connect(const char *workgroup, /* I - Workgroup */ if (cli ) { return cli; } + /* give a chance for a passwordless NTLMSSP session setup */ + + pwd = getpwuid(geteuid()); + if (pwd == NULL) { + return NULL; + } + + cli = smb_complete_connection(myname, server, port, pwd->pw_name, "", + workgroup, share, 0); + + if (cli) { return cli; } + /* * last try. Use anonymous authentication */ + cli = smb_complete_connection(myname, server, port, "", "", workgroup, share, 0); - /* * Return the new connection... */ diff --git a/source/include/passdb.h b/source/include/passdb.h index 293d18a42a2..0589b9a7cd4 100644 --- a/source/include/passdb.h +++ b/source/include/passdb.h @@ -265,9 +265,12 @@ struct pdb_search { * This next constant specifies the version number of the PASSDB interface * this SAMBA will load. Increment this if *ANY* changes are made to the interface. * Changed interface to fix int -> size_t problems. JRA. + * There's no point in allocating arrays in + * samr_lookup_rids twice. It was done in the srv_samr_nt.c code as well as in + * the pdb module. Remove the latter, this might happen more often. VL. */ -#define PASSDB_INTERFACE_VERSION 11 +#define PASSDB_INTERFACE_VERSION 12 typedef struct pdb_context { @@ -367,12 +370,11 @@ typedef struct pdb_context size_t *p_num_alias_rids); NTSTATUS (*pdb_lookup_rids)(struct pdb_context *context, - TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid, size_t num_rids, uint32 *rids, - const char ***pp_names, - uint32 **attrs); + const char **pp_names, + uint32 *attrs); NTSTATUS (*pdb_get_account_policy)(struct pdb_context *context, int policy_index, uint32 *value); @@ -491,12 +493,11 @@ typedef struct pdb_methods size_t *p_num_alias_rids); NTSTATUS (*lookup_rids)(struct pdb_methods *methods, - TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid, int num_rids, uint32 *rids, - const char ***pp_names, - uint32 **attrs); + const char **pp_names, + uint32 *attrs); NTSTATUS (*get_account_policy)(struct pdb_methods *methods, int policy_index, uint32 *value); diff --git a/source/include/rpc_dce.h b/source/include/rpc_dce.h index 3de4d2b691e..e718d92271c 100644 --- a/source/include/rpc_dce.h +++ b/source/include/rpc_dce.h @@ -26,15 +26,27 @@ /* DCE/RPC packet types */ enum RPC_PKT_TYPE { - RPC_REQUEST = 0x00, - RPC_RESPONSE = 0x02, - RPC_FAULT = 0x03, - RPC_BIND = 0x0B, - RPC_BINDACK = 0x0C, - RPC_BINDNACK = 0x0D, - RPC_ALTCONT = 0x0E, - RPC_ALTCONTRESP = 0x0F, - RPC_AUTH3 = 0x10 /* not the real name! this is undocumented! */ + RPC_REQUEST = 0x00, /* Ordinary request. */ + RPC_PING = 0x01, /* Connectionless is server alive ? */ + RPC_RESPONSE = 0x02, /* Ordinary reply. */ + RPC_FAULT = 0x03, /* Fault in processing of call. */ + RPC_WORKING = 0x04, /* Connectionless reply to a ping when server busy. */ + RPC_NOCALL = 0x05, /* Connectionless reply to a ping when server has lost part of clients call. */ + RPC_REJECT = 0x06, /* Refuse a request with a code. */ + RPC_ACK = 0x07, /* Connectionless client to server code. */ + RPC_CL_CANCEL= 0x08, /* Connectionless cancel. */ + RPC_FACK = 0x09, /* Connectionless fragment ack. Both client and server send. */ + RPC_CANCEL_ACK = 0x0A, /* Server ACK to client cancel request. */ + RPC_BIND = 0x0B, /* Bind to interface. */ + RPC_BINDACK = 0x0C, /* Server ack of bind. */ + RPC_BINDNACK = 0x0D, /* Server nack of bind. */ + RPC_ALTCONT = 0x0E, /* Alter auth. */ + RPC_ALTCONTRESP = 0x0F, /* Reply to alter auth. */ + RPC_AUTH3 = 0x10, /* not the real name! this is undocumented! */ + RPC_SHUTDOWN = 0x11, /* Server to client request to shutdown. */ + RPC_CO_CANCEL= 0x12, /* Connection-oriented cancel request. */ + RPC_ORPHANED = 0x13 /* Client telling server it's aborting a partially sent request or telling + server to stop sending replies. */ }; /* DCE/RPC flags */ diff --git a/source/include/rpc_netlogon.h b/source/include/rpc_netlogon.h index c73cd03f103..fdf2f08c03c 100644 --- a/source/include/rpc_netlogon.h +++ b/source/include/rpc_netlogon.h @@ -38,7 +38,9 @@ #define NET_LOGON_CTRL2 0x0e #define NET_SAM_SYNC 0x10 #define NET_TRUST_DOM_LIST 0x13 +#define NET_DSR_GETDCNAME 0x14 #define NET_AUTH3 0x1a +#define NET_DSR_GETSITENAME 0x1c /* Secure Channel types. used in NetrServerAuthenticate negotiation */ #define SEC_CHAN_WKSTA 2 @@ -934,4 +936,51 @@ typedef struct net_r_sam_deltas_info { NTSTATUS status; } NET_R_SAM_DELTAS; +/* NET_Q_DSR_GETDCNAME - Ask a DC for a trusted DC name and its address */ +typedef struct net_q_dsr_getdcname { + uint32 ptr_server_unc; + UNISTR2 uni_server_unc; + uint32 ptr_domain_name; + UNISTR2 uni_domain_name; + uint32 ptr_domain_guid; + struct uuid *domain_guid; + uint32 ptr_site_guid; + struct uuid *site_guid; + uint32_t flags; +} NET_Q_DSR_GETDCNAME; + +/* NET_R_DSR_GETDCNAME - Ask a DC for a trusted DC name and its address */ +typedef struct net_r_dsr_getdcname { + uint32 ptr_dc_unc; + UNISTR2 uni_dc_unc; + uint32 ptr_dc_address; + UNISTR2 uni_dc_address; + int32 dc_address_type; + struct uuid domain_guid; + uint32 ptr_domain_name; + UNISTR2 uni_domain_name; + uint32 ptr_forest_name; + UNISTR2 uni_forest_name; + uint32 dc_flags; + uint32 ptr_dc_site_name; + UNISTR2 uni_dc_site_name; + uint32 ptr_client_site_name; + UNISTR2 uni_client_site_name; + WERROR result; +} NET_R_DSR_GETDCNAME; + +/* NET_Q_DSR_GESITENAME */ +typedef struct net_q_dsr_getsitename { + uint32 ptr_computer_name; + UNISTR2 uni_computer_name; +} NET_Q_DSR_GETSITENAME; + +/* NET_R_DSR_GETSITENAME */ +typedef struct net_r_dsr_getsitename { + uint32 ptr_site_name; + UNISTR2 uni_site_name; + WERROR result; +} NET_R_DSR_GETSITENAME; + + #endif /* _RPC_NETLOGON_H */ diff --git a/source/include/rpc_samr.h b/source/include/rpc_samr.h index f19de2ef4fc..5555aaef0e4 100644 --- a/source/include/rpc_samr.h +++ b/source/include/rpc_samr.h @@ -143,6 +143,8 @@ SamrTestPrivateFunctionsUser #define SAMR_CONNECT 0x39 #define SAMR_SET_USERINFO 0x3A #define SAMR_CONNECT4 0x3E +#define SAMR_CHGPASSWD3 0x3F +#define SAMR_CONNECT5 0x40 typedef struct logon_hours_info { @@ -592,7 +594,7 @@ typedef struct sam_unknown_info_1_inf { uint16 min_length_password; uint16 password_history; - uint32 flag; + uint32 password_properties; NTTIME expire; NTTIME min_passwordage; @@ -1697,7 +1699,7 @@ typedef struct q_samr_connect_info /* SAMR_R_CONNECT - probably an open */ typedef struct r_samr_connect_info { - POLICY_HND connect_pol; /* policy handle */ + POLICY_HND connect_pol; /* policy handle */ NTSTATUS status; /* return status */ } SAMR_R_CONNECT; @@ -1715,6 +1717,31 @@ typedef struct q_samr_connect4_info /* SAMR_R_CONNECT4 - same format as connect */ typedef struct r_samr_connect_info SAMR_R_CONNECT4; +/* SAMR_Q_CONNECT5 */ +typedef struct q_samr_connect5_info +{ + uint32 ptr_srv_name; /* pointer to server name */ + UNISTR2 uni_srv_name; + uint32 access_mask; + uint32 level; + /* These following are acutally a level dependent + value. Fudge it for now. JRA */ + uint32 info1_unk1; + uint32 info1_unk2; +} SAMR_Q_CONNECT5; + +/* SAMR_R_CONNECT5 */ +typedef struct r_samr_connect_info5 +{ + uint32 level; + uint32 info1_unk1; + uint32 info1_unk2; + POLICY_HND connect_pol; /* policy handle */ + NTSTATUS status; /* return status */ + +} SAMR_R_CONNECT5; + + /* SAMR_Q_GET_DOM_PWINFO */ typedef struct q_samr_get_dom_pwinfo { @@ -1724,14 +1751,18 @@ typedef struct q_samr_get_dom_pwinfo } SAMR_Q_GET_DOM_PWINFO; +#define DOMAIN_PASSWORD_COMPLEX 0x00000001 +#define DOMAIN_PASSWORD_NO_ANON_CHANGE 0x00000002 +#define DOMAIN_PASSWORD_NO_CLEAR_CHANGE 0x00000004 +#define DOMAIN_LOCKOUT_ADMINS 0x00000008 +#define DOMAIN_PASSWORD_STORE_CLEARTEXT 0x00000010 +#define DOMAIN_REFUSE_PASSWORD_CHANGE 0x00000020 + /* SAMR_R_GET_DOM_PWINFO */ typedef struct r_samr_get_dom_pwinfo { - /* - * See Samba4 IDL - */ - uint16 unk_0; - uint32 unk_1; + uint16 min_pwd_length; + uint32 password_properties; NTSTATUS status; } SAMR_R_GET_DOM_PWINFO; @@ -1780,6 +1811,48 @@ typedef struct r_samr_chgpasswd_user_info } SAMR_R_CHGPASSWD_USER; +/* SAMR_Q_CHGPASSWD3 */ +typedef struct q_samr_chgpasswd3 +{ + uint32 ptr_0; + + UNIHDR hdr_dest_host; /* server name unicode header */ + UNISTR2 uni_dest_host; /* server name unicode string */ + + UNIHDR hdr_user_name; /* username unicode string header */ + UNISTR2 uni_user_name; /* username unicode string */ + + SAMR_ENC_PASSWD nt_newpass; + SAMR_ENC_HASH nt_oldhash; + + uint32 lm_change; /* 0x0000 0001 */ + + SAMR_ENC_PASSWD lm_newpass; + SAMR_ENC_HASH lm_oldhash; + + SAMR_ENC_PASSWD password3; + +} SAMR_Q_CHGPASSWD3; + +/* SAMR_CHANGE_REJECT */ +typedef struct samr_change_reject +{ + uint32 reject_reason; + uint32 unknown1; + uint32 unknown2; + +} SAMR_CHANGE_REJECT; + +/* SAMR_R_CHGPASSWD3 */ +typedef struct r_samr_chgpasswd3 +{ + SAM_UNK_INFO_1 info; + SAMR_CHANGE_REJECT reject; + NTSTATUS status; /* 0 == OK, C000006A (NT_STATUS_WRONG_PASSWORD) */ + +} SAMR_R_CHGPASSWD3; + + /* SAMR_Q_REMOVE_SID_FOREIGN_DOMAIN */ typedef struct q_samr_remove_sid_foreign_domain_info diff --git a/source/include/talloc.h b/source/include/talloc.h index 738506e323d..1001a951702 100644 --- a/source/include/talloc.h +++ b/source/include/talloc.h @@ -6,19 +6,23 @@ Copyright (C) Andrew Tridgell 2004-2005 - 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. + ** NOTE! The following LGPL license applies to the talloc + ** library. This does NOT imply that all of Samba is released + ** under the LGPL - This program is distributed in the hope that it will be useful, + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* this is only needed for compatibility with the old talloc */ @@ -58,9 +62,18 @@ typedef void TALLOC_CTX; #define malloc_array_p(type, count) (type *)realloc_array(NULL, sizeof(type), count) #define realloc_p(p, type, count) (type *)realloc_array(p, sizeof(type), count) +#if 0 +/* Not correct for Samba3. */ +#define data_blob(ptr, size) data_blob_named(ptr, size, "DATA_BLOB: "__location__) +#define data_blob_talloc(ctx, ptr, size) data_blob_talloc_named(ctx, ptr, size, "DATA_BLOB: "__location__) +#define data_blob_dup_talloc(ctx, blob) data_blob_talloc_named(ctx, (blob)->data, (blob)->length, "DATA_BLOB: "__location__) +#endif + #define talloc_set_type(ptr, type) talloc_set_name_const(ptr, #type) #define talloc_get_type(ptr, type) (type *)talloc_check_name(ptr, #type) +#define talloc_find_parent_bytype(ptr, type) (type *)talloc_find_parent_byname(ptr, #type) + #if TALLOC_DEPRECATED #define talloc_zero_p(ctx, type) talloc_zero(ctx, type) @@ -113,6 +126,7 @@ void *_talloc_zero(const void *ctx, size_t size, const char *name); void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name); char *talloc_strdup(const void *t, const char *p); char *talloc_strndup(const void *t, const char *p, size_t n); +char *talloc_append_string(const void *t, char *orig, const char *append); char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); char *talloc_asprintf_append(char *s, @@ -123,6 +137,8 @@ void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned void *talloc_realloc_fn(const void *context, void *ptr, size_t size); void *talloc_autofree_context(void); size_t talloc_get_size(const void *ctx); +void *talloc_find_parent_byname(const void *ctx, const char *name); +void talloc_show_parents(const void *context, FILE *file); #endif diff --git a/source/lib/talloc.c b/source/lib/talloc.c index 2df4588f425..00f889d682c 100644 --- a/source/lib/talloc.c +++ b/source/lib/talloc.c @@ -1,4 +1,4 @@ -/* +/* Samba Unix SMB/CIFS implementation. Samba trivial allocation library - new interface @@ -6,27 +6,30 @@ NOTE: Please read talloc_guide.txt for full documentation Copyright (C) Andrew Tridgell 2004 - - 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, + + ** NOTE! The following LGPL license applies to the talloc + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* inspired by http://swapped.cc/halloc/ */ - #ifdef _SAMBA_BUILD_ #include "includes.h" #if ((SAMBA_VERSION_MAJOR==3)&&(SAMBA_VERSION_MINOR<9)) @@ -56,8 +59,9 @@ #define MAX_TALLOC_SIZE 0x10000000 -#define TALLOC_MAGIC 0xe814ec4f -#define TALLOC_MAGIC_FREE 0x7faebef3 +#define TALLOC_MAGIC 0xe814ec70 +#define TALLOC_FLAG_FREE 0x01 +#define TALLOC_FLAG_LOOP 0x02 #define TALLOC_MAGIC_REFERENCE ((const char *)1) /* by default we abort when given a bad pointer (such as when talloc_free() is called @@ -93,27 +97,27 @@ struct talloc_chunk { struct talloc_chunk *next, *prev; struct talloc_chunk *parent, *child; struct talloc_reference_handle *refs; - size_t size; talloc_destructor_t destructor; const char *name; - union { - unsigned magic; - double align_dummy; - } u; + size_t size; + unsigned flags; }; +/* 16 byte alignment seems to keep everyone happy */ +#define TC_HDR_SIZE ((sizeof(struct talloc_chunk)+15)&~15) +#define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc)) + /* panic if we get a bad magic value */ static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr) { - struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, ptr)-1; - if (tc->u.magic != TALLOC_MAGIC) { - if (tc->u.magic == TALLOC_MAGIC_FREE) { - TALLOC_ABORT("Bad talloc magic value - double free"); - } else { - TALLOC_ABORT("Bad talloc magic value - unknown value"); - } + const char *pp = ptr; + struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE); + if ((tc->flags & ~0xF) != TALLOC_MAGIC) { + TALLOC_ABORT("Bad talloc magic value - unknown value"); + } + if (tc->flags & TALLOC_FLAG_FREE) { + TALLOC_ABORT("Bad talloc magic value - double free"); } - return tc; } @@ -158,7 +162,7 @@ static struct talloc_chunk *talloc_parent_chunk(const void *ptr) void *talloc_parent(const void *ptr) { struct talloc_chunk *tc = talloc_parent_chunk(ptr); - return tc ? (void *)(tc+1) : NULL; + return tc? TC_PTR_FROM_CHUNK(tc) : NULL; } /* @@ -176,11 +180,11 @@ void *_talloc(const void *context, size_t size) return NULL; } - tc = malloc(sizeof(*tc)+size); + tc = malloc(TC_HDR_SIZE+size); if (tc == NULL) return NULL; tc->size = size; - tc->u.magic = TALLOC_MAGIC; + tc->flags = TALLOC_MAGIC; tc->destructor = NULL; tc->child = NULL; tc->name = NULL; @@ -200,7 +204,7 @@ void *_talloc(const void *context, size_t size) tc->next = tc->prev = tc->parent = NULL; } - return (void *)(tc+1); + return TC_PTR_FROM_CHUNK(tc); } @@ -285,7 +289,7 @@ static int talloc_unreference(const void *context, const void *ptr) for (h=tc->refs;h;h=h->next) { struct talloc_chunk *p = talloc_parent_chunk(h); - if ((p==NULL && context==NULL) || p+1 == context) break; + if ((p==NULL && context==NULL) || TC_PTR_FROM_CHUNK(p) == context) break; } if (h == NULL) { return -1; @@ -336,7 +340,7 @@ int talloc_unlink(const void *context, void *ptr) new_p = talloc_parent_chunk(tc_p->refs); if (new_p) { - new_parent = new_p+1; + new_parent = TC_PTR_FROM_CHUNK(new_p); } else { new_parent = NULL; } @@ -464,6 +468,8 @@ void *talloc_init(const char *fmt, ...) va_list ap; void *ptr; + talloc_enable_null_tracking(); + ptr = _talloc(NULL, 0); if (ptr == NULL) return NULL; @@ -495,16 +501,16 @@ void talloc_free_children(void *ptr) choice is owner of any remaining reference to this pointer, the second choice is our parent, and the final choice is the null context. */ - void *child = tc->child+1; + void *child = TC_PTR_FROM_CHUNK(tc->child); const void *new_parent = null_context; if (tc->child->refs) { struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs); - if (p) new_parent = p+1; + if (p) new_parent = TC_PTR_FROM_CHUNK(p); } if (talloc_free(child) == -1) { if (new_parent == null_context) { struct talloc_chunk *p = talloc_parent_chunk(ptr); - if (p) new_parent = p+1; + if (p) new_parent = TC_PTR_FROM_CHUNK(p); } talloc_steal(new_parent, child); } @@ -534,6 +540,11 @@ int talloc_free(void *ptr) return -1; } + if (tc->flags & TALLOC_FLAG_LOOP) { + /* we have a free loop - stop looping */ + return 0; + } + if (tc->destructor) { talloc_destructor_t d = tc->destructor; if (d == (talloc_destructor_t)-1) { @@ -547,6 +558,8 @@ int talloc_free(void *ptr) tc->destructor = NULL; } + tc->flags |= TALLOC_FLAG_LOOP; + talloc_free_children(ptr); if (tc->parent) { @@ -559,7 +572,7 @@ int talloc_free(void *ptr) if (tc->next) tc->next->prev = tc->prev; } - tc->u.magic = TALLOC_MAGIC_FREE; + tc->flags |= TALLOC_FLAG_FREE; free(tc); return 0; @@ -599,24 +612,24 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n } /* by resetting magic we catch users of the old memory */ - tc->u.magic = TALLOC_MAGIC_FREE; + tc->flags |= TALLOC_FLAG_FREE; #if ALWAYS_REALLOC - new_ptr = malloc(size + sizeof(*tc)); + new_ptr = malloc(size + TC_HDR_SIZE); if (new_ptr) { - memcpy(new_ptr, tc, tc->size + sizeof(*tc)); + memcpy(new_ptr, tc, tc->size + TC_HDR_SIZE); free(tc); } #else - new_ptr = realloc(tc, size + sizeof(*tc)); + new_ptr = realloc(tc, size + TC_HDR_SIZE); #endif if (!new_ptr) { - tc->u.magic = TALLOC_MAGIC; + tc->flags &= ~TALLOC_FLAG_FREE; return NULL; } tc = new_ptr; - tc->u.magic = TALLOC_MAGIC; + tc->flags &= ~TALLOC_FLAG_FREE; if (tc->parent) { tc->parent->child = new_ptr; } @@ -632,9 +645,9 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n } tc->size = size; - talloc_set_name_const(tc+1, name); + talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name); - return (void *)(tc+1); + return TC_PTR_FROM_CHUNK(tc); } /* @@ -711,10 +724,19 @@ off_t talloc_total_size(const void *ptr) tc = talloc_chunk_from_ptr(ptr); + if (tc->flags & TALLOC_FLAG_LOOP) { + return 0; + } + + tc->flags |= TALLOC_FLAG_LOOP; + total = tc->size; for (c=tc->child;c;c=c->next) { - total += talloc_total_size(c+1); + total += talloc_total_size(TC_PTR_FROM_CHUNK(c)); } + + tc->flags &= ~TALLOC_FLAG_LOOP; + return total; } @@ -726,10 +748,19 @@ off_t talloc_total_blocks(const void *ptr) off_t total = 0; struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); + if (tc->flags & TALLOC_FLAG_LOOP) { + return 0; + } + + tc->flags |= TALLOC_FLAG_LOOP; + total++; for (c=tc->child;c;c=c->next) { - total += talloc_total_blocks(c+1); + total += talloc_total_blocks(TC_PTR_FROM_CHUNK(c)); } + + tc->flags &= ~TALLOC_FLAG_LOOP; + return total; } @@ -755,23 +786,29 @@ void talloc_report_depth(const void *ptr, FILE *f, int depth) { struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); + if (tc->flags & TALLOC_FLAG_LOOP) { + return; + } + + tc->flags |= TALLOC_FLAG_LOOP; + for (c=tc->child;c;c=c->next) { if (c->name == TALLOC_MAGIC_REFERENCE) { - struct talloc_reference_handle *handle = (void *)(c+1); + struct talloc_reference_handle *handle = TC_PTR_FROM_CHUNK(c); const char *name2 = talloc_get_name(handle->ptr); fprintf(f, "%*sreference to: %s\n", depth*4, "", name2); } else { - const char *name = talloc_get_name(c+1); + const char *name = talloc_get_name(TC_PTR_FROM_CHUNK(c)); fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n", depth*4, "", name, - (unsigned long)talloc_total_size(c+1), - (unsigned long)talloc_total_blocks(c+1), - talloc_reference_count(c+1)); - talloc_report_depth(c+1, f, depth+1); + (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)), + (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)), + talloc_reference_count(TC_PTR_FROM_CHUNK(c))); + talloc_report_depth(TC_PTR_FROM_CHUNK(c), f, depth+1); } } - + tc->flags &= ~TALLOC_FLAG_LOOP; } /* @@ -814,9 +851,9 @@ void talloc_report(const void *ptr, FILE *f) for (c=tc->child;c;c=c->next) { fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n", - talloc_get_name(c+1), - (unsigned long)talloc_total_size(c+1), - (unsigned long)talloc_total_blocks(c+1)); + talloc_get_name(TC_PTR_FROM_CHUNK(c)), + (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)), + (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c))); } fflush(f); } @@ -851,6 +888,74 @@ void talloc_enable_null_tracking(void) } } +#ifdef _SAMBA_BUILD_ +/* Ugly calls to Samba-specific sprintf_append... JRA. */ + +/* + report on memory usage by all children of a pointer, giving a full tree view +*/ +static void talloc_report_depth_str(const void *ptr, char **pps, ssize_t *plen, size_t *pbuflen, int depth) +{ + struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); + + if (tc->flags & TALLOC_FLAG_LOOP) { + return; + } + + tc->flags |= TALLOC_FLAG_LOOP; + + for (c=tc->child;c;c=c->next) { + if (c->name == TALLOC_MAGIC_REFERENCE) { + struct talloc_reference_handle *handle = TC_PTR_FROM_CHUNK(c); + const char *name2 = talloc_get_name(handle->ptr); + + sprintf_append(NULL, pps, plen, pbuflen, + "%*sreference to: %s\n", depth*4, "", name2); + + } else { + const char *name = talloc_get_name(TC_PTR_FROM_CHUNK(c)); + + sprintf_append(NULL, pps, plen, pbuflen, + "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n", + depth*4, "", + name, + (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)), + (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)), + talloc_reference_count(TC_PTR_FROM_CHUNK(c))); + + talloc_report_depth_str(TC_PTR_FROM_CHUNK(c), pps, plen, pbuflen, depth+1); + } + } + tc->flags &= ~TALLOC_FLAG_LOOP; +} + +/* + report on memory usage by all children of a pointer +*/ +char *talloc_describe_all(void) +{ + ssize_t len = 0; + size_t buflen = 512; + char *s = NULL; + + if (null_context == NULL) { + return NULL; + } + + sprintf_append(NULL, &s, &len, &buflen, + "full talloc report on '%s' (total %lu bytes in %lu blocks)\n", + talloc_get_name(null_context), + (unsigned long)talloc_total_size(null_context), + (unsigned long)talloc_total_blocks(null_context)); + + if (!s) { + return NULL; + } + talloc_report_depth_str(null_context, &s, &len, &buflen, 1); + return s; +} +#endif + /* enable leak reporting on exit */ @@ -914,6 +1019,28 @@ char *talloc_strdup(const void *t, const char *p) return ret; } +/* + append to a talloced string +*/ +char *talloc_append_string(const void *t, char *orig, const char *append) +{ + char *ret; + size_t olen = strlen(orig); + size_t alenz = strlen(append) + 1; + + if (!append) + return orig; + + ret = talloc_realloc(t, orig, char, olen + alenz); + if (!ret) + return NULL; + + /* append the string with the trailing \0 */ + memcpy(&ret[olen], append, alenz); + + return ret; +} + /* strndup with a talloc */ @@ -989,6 +1116,7 @@ static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINT static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) { + struct talloc_chunk *tc; int len, s_len; va_list ap2; @@ -996,9 +1124,11 @@ static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) return talloc_vasprintf(NULL, fmt, ap); } + tc = talloc_chunk_from_ptr(s); + VA_COPY(ap2, ap); - s_len = strlen(s); + s_len = tc->size - 1; len = vsnprintf(NULL, 0, fmt, ap2); s = talloc_realloc(NULL, s, char, s_len + len+1); @@ -1102,3 +1232,46 @@ size_t talloc_get_size(const void *context) return tc->size; } + +/* + find a parent of this context that has the given name, if any +*/ +void *talloc_find_parent_byname(const void *context, const char *name) +{ + struct talloc_chunk *tc; + + if (context == NULL) { + return NULL; + } + + tc = talloc_chunk_from_ptr(context); + while (tc) { + if (tc->name && strcmp(tc->name, name) == 0) { + return TC_PTR_FROM_CHUNK(tc); + } + while (tc && tc->prev) tc = tc->prev; + tc = tc->parent; + } + return NULL; +} + +/* + show the parentage of a context +*/ +void talloc_show_parents(const void *context, FILE *file) +{ + struct talloc_chunk *tc; + + if (context == NULL) { + fprintf(file, "talloc no parents for NULL\n"); + return; + } + + tc = talloc_chunk_from_ptr(context); + fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context)); + while (tc) { + fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc))); + while (tc && tc->prev) tc = tc->prev; + tc = tc->parent; + } +} diff --git a/source/lib/tallocmsg.c b/source/lib/tallocmsg.c index 8f03fd66ff1..b515093cd69 100644 --- a/source/lib/tallocmsg.c +++ b/source/lib/tallocmsg.c @@ -33,18 +33,23 @@ void msg_pool_usage(int msg_type, struct process_id src_pid, void *UNUSED(buf), size_t UNUSED(len)) { - off_t reply; - fstring reply_str; + char *reply = NULL; SMB_ASSERT(msg_type == MSG_REQ_POOL_USAGE); DEBUG(2,("Got POOL_USAGE\n")); - reply = talloc_total_size(NULL); - fstr_sprintf(reply_str, "%ld", (long)reply); + reply = talloc_describe_all(); + if (!reply) { + return; + } + become_root(); message_send_pid(src_pid, MSG_POOL_USAGE, - reply_str, strlen(reply_str)+1, True); + reply, strlen(reply)+1, True); + unbecome_root(); + + SAFE_FREE(reply); } /** diff --git a/source/lib/util_unistr.c b/source/lib/util_unistr.c index d80bb2ce521..b979745d366 100644 --- a/source/lib/util_unistr.c +++ b/source/lib/util_unistr.c @@ -265,6 +265,34 @@ int rpcstr_pull_unistr2_fstring(char *dest, UNISTR2 *src) src->uni_str_len * 2, 0); } +/* Helper function to return a talloc'ed string. I have implemented it with a + * copy because I don't really know how pull_ucs2 and friends calculate the + * target size. If this turns out to be a major bottleneck someone with deeper + * multi-byte knowledge needs to revisit this. + * My (VL) use is dsr_getdcname, which returns 6 strings, the alternative would + * have been to manually talloc_strdup them in rpc_client/cli_netlogon.c. + */ + +size_t rpcstr_pull_unistr2_talloc(TALLOC_CTX *mem_ctx, char **dest, + UNISTR2 *src) +{ + pstring tmp; + size_t result; + + result = pull_ucs2(NULL, tmp, src->buffer, sizeof(tmp), + src->uni_str_len * 2, 0); + if (result < 0) { + return result; + } + + *dest = talloc_strdup(mem_ctx, tmp); + if (*dest == NULL) { + return -1; + } + + return result; +} + /* Converts a string from internal samba format to unicode */ diff --git a/source/libsmb/cliconnect.c b/source/libsmb/cliconnect.c index b352d3572a7..ac7d1b1650c 100644 --- a/source/libsmb/cliconnect.c +++ b/source/libsmb/cliconnect.c @@ -163,6 +163,7 @@ static BOOL cli_session_setup_guest(struct cli_state *cli) char *p; uint32 capabilities = cli_session_setup_capabilities(cli); + memset(cli->outbuf, '\0', smb_size); set_message(cli->outbuf,13,0,True); SCVAL(cli->outbuf,smb_com,SMBsesssetupX); cli_setup_packet(cli); diff --git a/source/libsmb/clientgen.c b/source/libsmb/clientgen.c index bc64cc919b7..6dc7386c03b 100644 --- a/source/libsmb/clientgen.c +++ b/source/libsmb/clientgen.c @@ -481,6 +481,7 @@ BOOL cli_set_case_sensitive(struct cli_state *cli, BOOL case_sensitive) /**************************************************************************** Send a keepalive packet to the server ****************************************************************************/ + BOOL cli_send_keepalive(struct cli_state *cli) { if (cli->fd == -1) { @@ -495,3 +496,36 @@ BOOL cli_send_keepalive(struct cli_state *cli) } return True; } + +/**************************************************************************** + Send/receive a SMBecho command: ping the server +****************************************************************************/ + +BOOL cli_echo(struct cli_state *cli, unsigned char *data, size_t length) +{ + char *p; + + SMB_ASSERT(length < 1024); + + memset(cli->outbuf,'\0',smb_size); + set_message(cli->outbuf,1,length,True); + SCVAL(cli->outbuf,smb_com,SMBecho); + SSVAL(cli->outbuf,smb_tid,65535); + SSVAL(cli->outbuf,smb_vwv0,1); + cli_setup_packet(cli); + p = smb_buf(cli->outbuf); + memcpy(p, data, length); + p += length; + + cli_setup_bcc(cli, p); + + cli_send_smb(cli); + if (!cli_receive_smb(cli)) { + return False; + } + + if (cli_is_error(cli)) { + return False; + } + return True; +} diff --git a/source/nsswitch/wbinfo.c b/source/nsswitch/wbinfo.c index 45195fb86ab..aae76e44238 100644 --- a/source/nsswitch/wbinfo.c +++ b/source/nsswitch/wbinfo.c @@ -30,7 +30,7 @@ extern int winbindd_fd; -static char winbind_separator(void) +static char winbind_separator_int(BOOL strict) { struct winbindd_response response; static BOOL got_sep; @@ -46,6 +46,9 @@ static char winbind_separator(void) if (winbindd_request_response(WINBINDD_INFO, NULL, &response) != NSS_STATUS_SUCCESS) { d_printf("could not obtain winbind separator!\n"); + if (strict) { + return -1; + } /* HACK: (this module should not call lp_ funtions) */ return *lp_winbind_separator(); } @@ -55,6 +58,9 @@ static char winbind_separator(void) if (!sep) { d_printf("winbind separator was NULL!\n"); + if (strict) { + return -1; + } /* HACK: (this module should not call lp_ funtions) */ sep = *lp_winbind_separator(); } @@ -62,6 +68,11 @@ static char winbind_separator(void) return sep; } +static char winbind_separator(void) +{ + return winbind_separator_int(False); +} + static const char *get_winbind_domain(void) { struct winbindd_response response; @@ -956,7 +967,8 @@ enum { OPT_SEQUENCE, OPT_GETDCNAME, OPT_USERDOMGROUPS, - OPT_USERSIDS + OPT_USERSIDS, + OPT_SEPARATOR }; int main(int argc, char **argv) @@ -1004,6 +1016,7 @@ int main(int argc, char **argv) #ifdef WITH_FAKE_KASERVER { "klog", 'k', POPT_ARG_STRING, &string_arg, 'k', "set an AFS token from winbind", "user%password" }, #endif + { "separator", 0, POPT_ARG_NONE, 0, OPT_SEPARATOR, "Get the active winbind separator", NULL }, POPT_COMMON_VERSION POPT_TABLEEND }; @@ -1197,6 +1210,10 @@ int main(int argc, char **argv) case OPT_GETDCNAME: wbinfo_getdcname(string_arg); break; + case OPT_SEPARATOR: + d_printf("%c\n", winbind_separator_int(True)); + break; + /* generic configuration options */ case OPT_DOMAIN_NAME: break; diff --git a/source/param/loadparm.c b/source/param/loadparm.c index 86a5353dca7..cdef0340618 100644 --- a/source/param/loadparm.c +++ b/source/param/loadparm.c @@ -168,6 +168,7 @@ typedef struct char *szIdmapUID; char *szIdmapGID; BOOL bEnableRidAlgorithm; + BOOL bPassdbExpandExplicit; int AlgorithmicRidBase; char *szTemplateHomedir; char *szTemplateShell; @@ -1240,6 +1241,7 @@ static struct parm_struct parm_table[] = { {N_("Winbind options"), P_SEP, P_SEPARATOR}, {"enable rid algorithm", P_BOOL, P_GLOBAL, &Globals.bEnableRidAlgorithm, NULL, NULL, FLAG_DEPRECATED}, + {"passdb expand explicit", P_BOOL, P_GLOBAL, &Globals.bPassdbExpandExplicit, NULL, NULL, FLAG_ADVANCED}, {"idmap backend", P_LIST, P_GLOBAL, &Globals.szIdmapBackend, NULL, NULL, FLAG_ADVANCED}, {"idmap uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_ADVANCED}, {"winbind uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_HIDE}, @@ -1603,6 +1605,7 @@ static void init_globals(void) Globals.szWinbindNssInfo = str_list_make("template", NULL); Globals.bEnableRidAlgorithm = True; + Globals.bPassdbExpandExplicit = True; Globals.name_cache_timeout = 660; /* In seconds */ @@ -1792,6 +1795,7 @@ FN_GLOBAL_BOOL(lp_winbind_nested_groups, &Globals.bWinbindNestedGroups) FN_GLOBAL_LIST(lp_idmap_backend, &Globals.szIdmapBackend) FN_GLOBAL_BOOL(lp_enable_rid_algorithm, &Globals.bEnableRidAlgorithm) +FN_GLOBAL_BOOL(lp_passdb_expand_explicit, &Globals.bPassdbExpandExplicit) #ifdef WITH_LDAP_SAMCONFIG FN_GLOBAL_STRING(lp_ldap_server, &Globals.szLdapServer) diff --git a/source/passdb/lookup_sid.c b/source/passdb/lookup_sid.c index 6b58210919a..b397e084c33 100644 --- a/source/passdb/lookup_sid.c +++ b/source/passdb/lookup_sid.c @@ -66,7 +66,8 @@ BOOL lookup_name(const char *domain, const char *name, DOM_SID *psid, enum SID_N Tries local lookup first - for local sids, then tries winbind. *****************************************************************/ -BOOL lookup_sid(const DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE *name_type) +BOOL lookup_sid(const DOM_SID *sid, fstring dom_name, fstring name, + enum SID_NAME_USE *name_type) { if (!name_type) return False; @@ -76,25 +77,51 @@ BOOL lookup_sid(const DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAM /* Check if this is our own sid. This should perhaps be done by winbind? For the moment handle it here. */ - if (sid->num_auths == 4 && sid_equal(get_global_sam_sid(), sid)) { - DOM_SID tmp_sid; - sid_copy(&tmp_sid, sid); - return map_domain_sid_to_name(&tmp_sid, dom_name) && - local_lookup_sid(sid, name, name_type); + if (sid_check_is_domain(sid)) { + fstrcpy(dom_name, get_global_sam_name()); + fstrcpy(name, ""); + *name_type = SID_NAME_DOMAIN; + return True; } - if (sid->num_auths == 5) { - DOM_SID tmp_sid; + if (sid_check_is_in_our_domain(sid)) { uint32 rid; + SMB_ASSERT(sid_peek_rid(sid, &rid)); + + /* For our own domain passdb is responsible */ + fstrcpy(dom_name, get_global_sam_name()); + return lookup_global_sam_rid(rid, name, name_type); + } - sid_copy(&tmp_sid, sid); - sid_split_rid(&tmp_sid, &rid); + if (sid_check_is_builtin(sid)) { - if (sid_equal(get_global_sam_sid(), &tmp_sid)) { + /* Got through map_domain_sid_to_name here so that the mapping + * of S-1-5-32 to the name "BUILTIN" in as few places as + * possible. We might add i18n... */ + SMB_ASSERT(map_domain_sid_to_name(sid, dom_name)); - return map_domain_sid_to_name(&tmp_sid, dom_name) && - local_lookup_sid(sid, name, name_type); - } + /* Yes, W2k3 returns "BUILTIN" both as domain and name here */ + fstrcpy(name, dom_name); + + *name_type = SID_NAME_DOMAIN; + return True; + } + + if (sid_check_is_in_builtin(sid)) { + uint32 rid; + + SMB_ASSERT(sid_peek_rid(sid, &rid)); + + /* Got through map_domain_sid_to_name here so that the mapping + * of S-1-5-32 to the name "BUILTIN" in as few places as + * possible. We might add i18n... */ + SMB_ASSERT(map_domain_sid_to_name(&global_sid_Builtin, + dom_name)); + + /* There's only aliases in S-1-5-32 */ + *name_type = SID_NAME_ALIAS; + + return lookup_builtin_rid(rid, name); } if (winbind_lookup_sid(sid, dom_name, name, name_type)) { diff --git a/source/passdb/passdb.c b/source/passdb/passdb.c index a7ff3a04f7e..e073db3499c 100644 --- a/source/passdb/passdb.c +++ b/source/passdb/passdb.c @@ -732,34 +732,25 @@ BOOL algorithmic_pdb_rid_is_user(uint32 rid) } /******************************************************************* - Convert a rid into a name. Used in the lookup SID rpc. + Look up a rid in the SAM we're responsible for (i.e. passdb) ********************************************************************/ -BOOL local_lookup_sid(const DOM_SID *sid, char *name, enum SID_NAME_USE *psid_name_use) +BOOL lookup_global_sam_rid(uint32 rid, fstring name, + enum SID_NAME_USE *psid_name_use) { - uint32 rid; SAM_ACCOUNT *sam_account = NULL; GROUP_MAP map; BOOL ret; + DOM_SID sid; - if (sid_equal(get_global_sam_sid(), sid)) { - *psid_name_use = SID_NAME_DOMAIN; - fstrcpy(name, ""); - DEBUG(5,("local_lookup_sid: SID is our own domain-sid: %s.\n", - sid_string_static(sid))); - return True; - } - - if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid)){ - DEBUG(0,("local_lookup_sid: sid_peek_check_rid return False! SID: %s\n", - sid_string_static(&map.sid))); - return False; - } *psid_name_use = SID_NAME_UNKNOWN; - DEBUG(5,("local_lookup_sid: looking up RID %u.\n", (unsigned int)rid)); - + DEBUG(5,("lookup_global_sam_rid: looking up RID %u.\n", + (unsigned int)rid)); + sid_copy(&sid, get_global_sam_sid()); + sid_append_rid(&sid, rid); + /* see if the passdb can help us with the name of the user */ if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_account))) { return False; @@ -767,8 +758,8 @@ BOOL local_lookup_sid(const DOM_SID *sid, char *name, enum SID_NAME_USE *psid_na /* BEING ROOT BLLOCK */ become_root(); - if (pdb_getsampwsid(sam_account, sid)) { - unbecome_root(); /* -----> EXIT BECOME_ROOT() */ + if (pdb_getsampwsid(sam_account, &sid)) { + unbecome_root(); /* -----> EXIT BECOME_ROOT() */ fstrcpy(name, pdb_get_username(sam_account)); *psid_name_use = SID_NAME_USER; @@ -778,15 +769,19 @@ BOOL local_lookup_sid(const DOM_SID *sid, char *name, enum SID_NAME_USE *psid_na } pdb_free_sam(&sam_account); - ret = pdb_getgrsid(&map, *sid); + ret = pdb_getgrsid(&map, sid); unbecome_root(); /* END BECOME_ROOT BLOCK */ if ( ret ) { if (map.gid!=(gid_t)-1) { - DEBUG(5,("local_lookup_sid: mapped group %s to gid %u\n", map.nt_name, (unsigned int)map.gid)); + DEBUG(5,("lookup_global_sam_rid: mapped group %s to " + "gid %u\n", map.nt_name, + (unsigned int)map.gid)); } else { - DEBUG(5,("local_lookup_sid: mapped group %s to no unix gid. Returning name.\n", map.nt_name)); + DEBUG(5,("lookup_global_sam_rid: mapped group %s to " + "no unix gid. Returning name.\n", + map.nt_name)); } fstrcpy(name, map.nt_name); @@ -809,16 +804,16 @@ BOOL local_lookup_sid(const DOM_SID *sid, char *name, enum SID_NAME_USE *psid_na uid = algorithmic_pdb_user_rid_to_uid(rid); pw = sys_getpwuid( uid ); - DEBUG(5,("local_lookup_sid: looking up uid %u %s\n", (unsigned int)uid, - pw ? "succeeded" : "failed" )); + DEBUG(5,("lookup_global_sam_rid: looking up uid %u %s\n", + (unsigned int)uid, pw ? "succeeded" : "failed" )); if ( !pw ) - fstr_sprintf(name, "unix_user.%u", (unsigned int)uid); + fstr_sprintf(name, "unix_user.%u", (unsigned int)uid); else fstrcpy( name, pw->pw_name ); - DEBUG(5,("local_lookup_sid: found user %s for rid %u\n", name, - (unsigned int)rid )); + DEBUG(5,("lookup_global_sam_rid: found user %s for rid %u\n", + name, (unsigned int)rid )); *psid_name_use = SID_NAME_USER; @@ -832,16 +827,16 @@ BOOL local_lookup_sid(const DOM_SID *sid, char *name, enum SID_NAME_USE *psid_na gid = pdb_group_rid_to_gid(rid); gr = getgrgid(gid); - DEBUG(5,("local_lookup_sid: looking up gid %u %s\n", (unsigned int)gid, - gr ? "succeeded" : "failed" )); + DEBUG(5,("lookup_global_sam_rid: looking up gid %u %s\n", + (unsigned int)gid, gr ? "succeeded" : "failed" )); if( !gr ) fstr_sprintf(name, "unix_group.%u", (unsigned int)gid); else fstrcpy( name, gr->gr_name); - DEBUG(5,("local_lookup_sid: found group %s for rid %u\n", name, - (unsigned int)rid )); + DEBUG(5,("lookup_global_sam_rid: found group %s for rid %u\n", + name, (unsigned int)rid )); /* assume algorithmic groups are domain global groups */ @@ -1756,6 +1751,7 @@ BOOL init_sam_from_buffer_v2(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) uint32 pwHistLen = 0; BOOL ret = True; fstring tmpstring; + BOOL expand_explicit = lp_passdb_expand_explicit(); if(sampass == NULL || buf == NULL) { DEBUG(0, ("init_sam_from_buffer_v2: NULL parameters found!\n")); @@ -1820,7 +1816,10 @@ BOOL init_sam_from_buffer_v2(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) if (homedir) { fstrcpy( tmpstring, homedir ); - standard_sub_basic( username, tmpstring, sizeof(tmpstring) ); + if (expand_explicit) { + standard_sub_basic( username, tmpstring, + sizeof(tmpstring) ); + } pdb_set_homedir(sampass, tmpstring, PDB_SET); } else { @@ -1836,7 +1835,10 @@ BOOL init_sam_from_buffer_v2(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) if (logon_script) { fstrcpy( tmpstring, logon_script ); - standard_sub_basic( username, tmpstring, sizeof(tmpstring) ); + if (expand_explicit) { + standard_sub_basic( username, tmpstring, + sizeof(tmpstring) ); + } pdb_set_logon_script(sampass, tmpstring, PDB_SET); } else { @@ -1847,7 +1849,10 @@ BOOL init_sam_from_buffer_v2(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) if (profile_path) { fstrcpy( tmpstring, profile_path ); - standard_sub_basic( username, tmpstring, sizeof(tmpstring) ); + if (expand_explicit) { + standard_sub_basic( username, tmpstring, + sizeof(tmpstring) ); + } pdb_set_profile_path(sampass, tmpstring, PDB_SET); } else { diff --git a/source/passdb/pdb_interface.c b/source/passdb/pdb_interface.c index 482f3e3c9b8..875e264bf01 100644 --- a/source/passdb/pdb_interface.c +++ b/source/passdb/pdb_interface.c @@ -681,12 +681,11 @@ static NTSTATUS context_enum_alias_memberships(struct pdb_context *context, } static NTSTATUS context_lookup_rids(struct pdb_context *context, - TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid, size_t num_rids, uint32 *rids, - const char ***pp_names, - uint32 **pp_attrs) + const char **pp_names, + uint32 *pp_attrs) { NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; @@ -696,7 +695,7 @@ static NTSTATUS context_lookup_rids(struct pdb_context *context, } return context->pdb_methods->lookup_rids(context->pdb_methods, - mem_ctx, domain_sid, num_rids, + domain_sid, num_rids, rids, pp_names, pp_attrs); } @@ -1398,12 +1397,11 @@ BOOL pdb_enum_alias_memberships(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid, p_num_alias_rids)); } -NTSTATUS pdb_lookup_rids(TALLOC_CTX *mem_ctx, - const DOM_SID *domain_sid, +NTSTATUS pdb_lookup_rids(const DOM_SID *domain_sid, int num_rids, uint32 *rids, - const char ***names, - uint32 **attrs) + const char **names, + uint32 *attrs) { struct pdb_context *pdb_context = pdb_get_static_context(False); @@ -1411,7 +1409,7 @@ NTSTATUS pdb_lookup_rids(TALLOC_CTX *mem_ctx, return NT_STATUS_NOT_IMPLEMENTED; } - return pdb_context->pdb_lookup_rids(pdb_context, mem_ctx, domain_sid, + return pdb_context->pdb_lookup_rids(pdb_context, domain_sid, num_rids, rids, names, attrs); } @@ -1643,51 +1641,58 @@ NTSTATUS pdb_default_enum_group_members(struct pdb_methods *methods, } NTSTATUS pdb_default_lookup_rids(struct pdb_methods *methods, - TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid, int num_rids, uint32 *rids, - const char ***names, - uint32 **attrs) + const char **names, + uint32 *attrs) { int i; NTSTATUS result; BOOL have_mapped = False; BOOL have_unmapped = False; - (*names) = TALLOC_ZERO_ARRAY(mem_ctx, const char *, num_rids); - (*attrs) = TALLOC_ZERO_ARRAY(mem_ctx, uint32, num_rids); - - if ((num_rids != 0) && (((*names) == NULL) || ((*attrs) == NULL))) - return NT_STATUS_NO_MEMORY; - - if (!sid_equal(domain_sid, get_global_sam_sid())) { - /* TODO: Sooner or later we need to look up BUILTIN rids as - * well. -- vl */ + if (sid_check_is_builtin(domain_sid)) { + + for (i=0; iprivate_data; @@ -3521,7 +3530,7 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods, NTSTATUS result = NT_STATUS_UNSUCCESSFUL; if (!lp_parm_bool(-1, "ldapsam", "trusted", False)) - return pdb_default_lookup_rids(methods, mem_ctx, domain_sid, + return pdb_default_lookup_rids(methods, domain_sid, num_rids, rids, names, attrs); if (!sid_equal(domain_sid, get_global_sam_sid())) { @@ -3530,14 +3539,8 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods, goto done; } - (*names) = TALLOC_ZERO_ARRAY(mem_ctx, const char *, num_rids); - (*attrs) = TALLOC_ARRAY(mem_ctx, uint32, num_rids); - - if ((num_rids != 0) && (((*names) == NULL) || ((*attrs) == NULL))) - return NT_STATUS_NO_MEMORY; - for (i=0; i=n_services || !W_ERROR_IS_OK( get_a_printer(NULL, &printer, 2, printername) ) ) { return -1; diff --git a/source/rpc_client/cli_netlogon.c b/source/rpc_client/cli_netlogon.c index af0062f2b39..e3cc97cdc6b 100644 --- a/source/rpc_client/cli_netlogon.c +++ b/source/rpc_client/cli_netlogon.c @@ -417,6 +417,170 @@ NTSTATUS rpccli_netlogon_getdcname(struct rpc_pipe_client *cli, return result; } +/* Dsr_GetDCName */ + +WERROR rpccli_netlogon_dsr_getdcname(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + const char *server_name, + const char *domain_name, + struct uuid *domain_guid, + struct uuid *site_guid, + uint32_t flags, + char **dc_unc, char **dc_address, + int32 *dc_address_type, + struct uuid *domain_guid_out, + char **domain_name_out, + char **forest_name, + uint32 *dc_flags, + char **dc_site_name, + char **client_site_name) +{ + prs_struct qbuf, rbuf; + NET_Q_DSR_GETDCNAME q; + NET_R_DSR_GETDCNAME r; + char *tmp_str; + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + /* Initialize input parameters */ + + tmp_str = talloc_asprintf(mem_ctx, "\\\\%s", server_name); + if (tmp_str == NULL) { + return WERR_NOMEM; + } + + init_net_q_dsr_getdcname(&q, tmp_str, domain_name, domain_guid, + site_guid, flags); + + /* Marshall data and send request */ + + CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETDCNAME, + q, r, + qbuf, rbuf, + net_io_q_dsr_getdcname, + net_io_r_dsr_getdcname, + WERR_GENERAL_FAILURE); + + if (!W_ERROR_IS_OK(r.result)) { + return r.result; + } + + if (dc_unc != NULL) { + char *tmp; + if (rpcstr_pull_unistr2_talloc(mem_ctx, &tmp, + &r.uni_dc_unc) < 0) { + return WERR_GENERAL_FAILURE; + } + if (*tmp == '\\') tmp += 1; + if (*tmp == '\\') tmp += 1; + + /* We have to talloc_strdup, otherwise a talloc_steal would + fail */ + *dc_unc = talloc_strdup(mem_ctx, tmp); + if (*dc_unc == NULL) { + return WERR_NOMEM; + } + } + + if (dc_address != NULL) { + char *tmp; + if (rpcstr_pull_unistr2_talloc(mem_ctx, &tmp, + &r.uni_dc_address) < 0) { + return WERR_GENERAL_FAILURE; + } + if (*tmp == '\\') tmp += 1; + if (*tmp == '\\') tmp += 1; + + /* We have to talloc_strdup, otherwise a talloc_steal would + fail */ + *dc_address = talloc_strdup(mem_ctx, tmp); + if (*dc_address == NULL) { + return WERR_NOMEM; + } + } + + if (dc_address_type != NULL) { + *dc_address_type = r.dc_address_type; + } + + if (domain_guid_out != NULL) { + *domain_guid_out = r.domain_guid; + } + + if ((domain_name_out != NULL) && + (rpcstr_pull_unistr2_talloc(mem_ctx, domain_name_out, + &r.uni_domain_name) < 1)) { + return WERR_GENERAL_FAILURE; + } + + if ((forest_name != NULL) && + (rpcstr_pull_unistr2_talloc(mem_ctx, forest_name, + &r.uni_forest_name) < 1)) { + return WERR_GENERAL_FAILURE; + } + + if (dc_flags != NULL) { + *dc_flags = r.dc_flags; + } + + if ((dc_site_name != NULL) && + (rpcstr_pull_unistr2_talloc(mem_ctx, dc_site_name, + &r.uni_dc_site_name) < 1)) { + return WERR_GENERAL_FAILURE; + } + + if ((client_site_name != NULL) && + (rpcstr_pull_unistr2_talloc(mem_ctx, client_site_name, + &r.uni_client_site_name) < 1)) { + return WERR_GENERAL_FAILURE; + } + + return WERR_OK; +} + +/* Dsr_GetSiteName */ + +WERROR rpccli_netlogon_dsr_getsitename(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + const char *computer_name, + char **site_name) +{ + prs_struct qbuf, rbuf; + NET_Q_DSR_GETSITENAME q; + NET_R_DSR_GETSITENAME r; + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + /* Initialize input parameters */ + + init_net_q_dsr_getsitename(&q, computer_name); + + /* Marshall data and send request */ + + CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETSITENAME, + q, r, + qbuf, rbuf, + net_io_q_dsr_getsitename, + net_io_r_dsr_getsitename, + WERR_GENERAL_FAILURE); + + if (!W_ERROR_IS_OK(r.result)) { + return r.result; + } + + if ((site_name != NULL) && + (rpcstr_pull_unistr2_talloc(mem_ctx, site_name, + &r.uni_site_name) < 1)) { + return WERR_GENERAL_FAILURE; + } + + return WERR_OK; +} + + + /* Sam synchronisation */ NTSTATUS rpccli_netlogon_sam_sync(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, diff --git a/source/rpc_client/cli_samr.c b/source/rpc_client/cli_samr.c index d68c72e20c8..fb95da97aef 100644 --- a/source/rpc_client/cli_samr.c +++ b/source/rpc_client/cli_samr.c @@ -1205,6 +1205,95 @@ NTSTATUS rpccli_samr_chgpasswd_user(struct rpc_pipe_client *cli, return result; } +/* change password 3 */ + +NTSTATUS rpccli_samr_chgpasswd3(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + const char *username, + const char *newpassword, + const char *oldpassword, + SAM_UNK_INFO_1 **info, + SAMR_CHANGE_REJECT **reject) +{ + prs_struct qbuf, rbuf; + SAMR_Q_CHGPASSWD3 q; + SAMR_R_CHGPASSWD3 r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + + uchar new_nt_password[516]; + uchar new_lm_password[516]; + uchar old_nt_hash[16]; + uchar old_lanman_hash[16]; + uchar old_nt_hash_enc[16]; + uchar old_lanman_hash_enc[16]; + + uchar new_nt_hash[16]; + uchar new_lanman_hash[16]; + + char *srv_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", cli->cli->desthost); + + DEBUG(10,("rpccli_samr_chgpasswd3\n")); + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + *info = NULL; + *reject = NULL; + + /* Calculate the MD4 hash (NT compatible) of the password */ + E_md4hash(oldpassword, old_nt_hash); + E_md4hash(newpassword, new_nt_hash); + + if (lp_client_lanman_auth() + && E_deshash(newpassword, new_lanman_hash) + && E_deshash(oldpassword, old_lanman_hash)) { + /* E_deshash returns false for 'long' passwords (> 14 + DOS chars). This allows us to match Win2k, which + does not store a LM hash for these passwords (which + would reduce the effective password length to 14) */ + + encode_pw_buffer(new_lm_password, newpassword, STR_UNICODE); + + SamOEMhash( new_lm_password, old_nt_hash, 516); + E_old_pw_hash( new_nt_hash, old_lanman_hash, old_lanman_hash_enc); + } else { + ZERO_STRUCT(new_lm_password); + ZERO_STRUCT(old_lanman_hash_enc); + } + + encode_pw_buffer(new_nt_password, newpassword, STR_UNICODE); + + SamOEMhash( new_nt_password, old_nt_hash, 516); + E_old_pw_hash( new_nt_hash, old_nt_hash, old_nt_hash_enc); + + /* Marshall data and send request */ + + init_samr_q_chgpasswd3(&q, srv_name_slash, username, + new_nt_password, + old_nt_hash_enc, + new_lm_password, + old_lanman_hash_enc); + + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_CHGPASSWD3, + q, r, + qbuf, rbuf, + samr_io_q_chgpasswd3, + samr_io_r_chgpasswd3, + NT_STATUS_UNSUCCESSFUL); + + /* Return output parameters */ + + if (!NT_STATUS_IS_OK(result = r.status)) { + *info = &r.info; + *reject = &r.reject; + goto done; + } + + done: + + return result; +} + /* This function returns the bizzare set of (max_entries, max_size) required for the QueryDisplayInfo RPC to actually work against a domain controller with large (10k and higher) numbers of users. These values were @@ -1723,7 +1812,7 @@ NTSTATUS rpccli_samr_query_sec_obj(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ /* Get domain password info */ NTSTATUS rpccli_samr_get_dom_pwinfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, - uint16 *unk_0, uint16 *unk_1) + uint16 *min_pwd_length, uint32 *password_properties) { prs_struct qbuf, rbuf; SAMR_Q_GET_DOM_PWINFO q; @@ -1751,10 +1840,10 @@ NTSTATUS rpccli_samr_get_dom_pwinfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem result = r.status; if (NT_STATUS_IS_OK(result)) { - if (unk_0) - *unk_0 = r.unk_0; - if (unk_1) - *unk_1 = r.unk_1; + if (min_pwd_length) + *min_pwd_length = r.min_pwd_length; + if (password_properties) + *password_properties = r.password_properties; } return result; diff --git a/source/rpc_parse/parse_lsa.c b/source/rpc_parse/parse_lsa.c index d924ea27d1f..3d28b657f33 100644 --- a/source/rpc_parse/parse_lsa.c +++ b/source/rpc_parse/parse_lsa.c @@ -3009,6 +3009,44 @@ static BOOL lsa_io_trustdom_query_4(const char *desc, TRUSTED_DOMAIN_INFO_PASSWO /******************************************************************* ********************************************************************/ +static BOOL lsa_io_trustdom_query_6(const char *desc, TRUSTED_DOMAIN_INFO_EX *info_ex, + prs_struct *ps, int depth) +{ + uint32 dom_sid_ptr; + + if (!smb_io_unihdr("domain_name_hdr", &info_ex->domain_name.hdr, ps, depth)) + return False; + + if (!smb_io_unihdr("netbios_name_hdr", &info_ex->netbios_name.hdr, ps, depth)) + return False; + + if (!prs_uint32("dom_sid_ptr", ps, depth, &dom_sid_ptr)) + return False; + + if (!prs_uint32("trust_direction", ps, depth, &info_ex->trust_direction)) + return False; + + if (!prs_uint32("trust_type", ps, depth, &info_ex->trust_type)) + return False; + + if (!prs_uint32("trust_attributes", ps, depth, &info_ex->trust_attributes)) + return False; + + if (!smb_io_unistr2("domain_name_unistring", &info_ex->domain_name.unistring, info_ex->domain_name.hdr.buffer, ps, depth)) + return False; + + if (!smb_io_unistr2("netbios_name_unistring", &info_ex->netbios_name.unistring, info_ex->netbios_name.hdr.buffer, ps, depth)) + return False; + + if (!smb_io_dom_sid2("sid", &info_ex->sid, ps, depth)) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ + static BOOL lsa_io_trustdom_query(const char *desc, prs_struct *ps, int depth, LSA_TRUSTED_DOMAIN_INFO *info) { prs_debug(ps, depth, desc, "lsa_io_trustdom_query"); @@ -3033,6 +3071,10 @@ static BOOL lsa_io_trustdom_query(const char *desc, prs_struct *ps, int depth, L if(!lsa_io_trustdom_query_4("password", &info->password, ps, depth)) return False; break; + case 6: + if(!lsa_io_trustdom_query_6("info_ex", &info->info_ex, ps, depth)) + return False; + break; default: DEBUG(0,("unsupported info-level: %d\n", info->info_class)); return False; diff --git a/source/rpc_parse/parse_net.c b/source/rpc_parse/parse_net.c index a32edd43841..ce2a085f478 100644 --- a/source/rpc_parse/parse_net.c +++ b/source/rpc_parse/parse_net.c @@ -3153,3 +3153,311 @@ BOOL net_io_r_sam_deltas(const char *desc, return True; } + +/******************************************************************* + Inits a NET_Q_DSR_GETDCNAME structure. +********************************************************************/ + +void init_net_q_dsr_getdcname(NET_Q_DSR_GETDCNAME *r_t, const char *server_unc, + const char *domain_name, + struct uuid *domain_guid, + struct uuid *site_guid, + uint32_t flags) +{ + DEBUG(5, ("init_net_q_dsr_getdcname\n")); + + r_t->ptr_server_unc = (server_unc != NULL); + init_unistr2(&r_t->uni_server_unc, server_unc, UNI_STR_TERMINATE); + + r_t->ptr_domain_name = (domain_name != NULL); + init_unistr2(&r_t->uni_domain_name, domain_name, UNI_STR_TERMINATE); + + r_t->ptr_domain_guid = (domain_guid != NULL); + r_t->domain_guid = domain_guid; + + r_t->ptr_site_guid = (site_guid != NULL); + r_t->site_guid = site_guid; + + r_t->flags = flags; +} + +/******************************************************************* + Reads or writes an NET_Q_DSR_GETDCNAME structure. +********************************************************************/ + +BOOL net_io_q_dsr_getdcname(const char *desc, NET_Q_DSR_GETDCNAME *r_t, + prs_struct *ps, int depth) +{ + if (r_t == NULL) + return False; + + prs_debug(ps, depth, desc, "net_io_q_dsr_getdcname"); + depth++; + + if (!prs_uint32("ptr_server_unc", ps, depth, &r_t->ptr_server_unc)) + return False; + + if (!smb_io_unistr2("server_unc", &r_t->uni_server_unc, + r_t->ptr_server_unc, ps, depth)) + return False; + + if (!prs_align(ps)) + return False; + + if (!prs_uint32("ptr_domain_name", ps, depth, &r_t->ptr_domain_name)) + return False; + + if (!smb_io_unistr2("domain_name", &r_t->uni_domain_name, + r_t->ptr_domain_name, ps, depth)) + return False; + + if (!prs_align(ps)) + return False; + + if (!prs_uint32("ptr_domain_guid", ps, depth, &r_t->ptr_domain_guid)) + return False; + + if (UNMARSHALLING(ps) && (r_t->ptr_domain_guid)) { + r_t->domain_guid = PRS_ALLOC_MEM(ps, struct uuid, 1); + if (r_t->domain_guid == NULL) + return False; + } + + if ((r_t->ptr_domain_guid) && + (!smb_io_uuid("domain_guid", r_t->domain_guid, ps, depth))) + return False; + + if (!prs_align(ps)) + return False; + + if (!prs_uint32("ptr_site_guid", ps, depth, &r_t->ptr_site_guid)) + return False; + + if (UNMARSHALLING(ps) && (r_t->ptr_site_guid)) { + r_t->site_guid = PRS_ALLOC_MEM(ps, struct uuid, 1); + if (r_t->site_guid == NULL) + return False; + } + + if ((r_t->ptr_site_guid) && + (!smb_io_uuid("site_guid", r_t->site_guid, ps, depth))) + return False; + + if (!prs_align(ps)) + return False; + + if (!prs_uint32("flags", ps, depth, &r_t->flags)) + return False; + + return True; +} + +/******************************************************************* + Inits a NET_R_DSR_GETDCNAME structure. +********************************************************************/ +void init_net_r_dsr_getdcname(NET_R_DSR_GETDCNAME *r_t, const char *dc_unc, + const char *dc_address, int32 dc_address_type, + struct uuid domain_guid, const char *domain_name, + const char *forest_name, uint32 dc_flags, + const char *dc_site_name, + const char *client_site_name) +{ + DEBUG(5, ("init_net_q_dsr_getdcname\n")); + + r_t->ptr_dc_unc = (dc_unc != NULL); + init_unistr2(&r_t->uni_dc_unc, dc_unc, UNI_STR_TERMINATE); + + r_t->ptr_dc_address = (dc_address != NULL); + init_unistr2(&r_t->uni_dc_address, dc_address, UNI_STR_TERMINATE); + + r_t->dc_address_type = dc_address_type; + r_t->domain_guid = domain_guid; + + r_t->ptr_domain_name = (domain_name != NULL); + init_unistr2(&r_t->uni_domain_name, domain_name, UNI_STR_TERMINATE); + + r_t->ptr_forest_name = (forest_name != NULL); + init_unistr2(&r_t->uni_forest_name, forest_name, UNI_STR_TERMINATE); + + r_t->dc_flags = dc_flags; + + r_t->ptr_dc_site_name = (dc_site_name != NULL); + init_unistr2(&r_t->uni_dc_site_name, dc_site_name, UNI_STR_TERMINATE); + + r_t->ptr_client_site_name = (client_site_name != NULL); + init_unistr2(&r_t->uni_client_site_name, client_site_name, + UNI_STR_TERMINATE); +} + +/******************************************************************* + Reads or writes an NET_R_DSR_GETDCNAME structure. +********************************************************************/ + +BOOL net_io_r_dsr_getdcname(const char *desc, NET_R_DSR_GETDCNAME *r_t, + prs_struct *ps, int depth) +{ + uint32 info_ptr = 1; + + if (r_t == NULL) + return False; + + prs_debug(ps, depth, desc, "net_io_r_dsr_getdcname"); + depth++; + + /* The reply contains *just* an info struct, this is the ptr to it */ + if (!prs_uint32("info_ptr", ps, depth, &info_ptr)) + return False; + + if (info_ptr == 0) + return False; + + if (!prs_uint32("ptr_dc_unc", ps, depth, &r_t->ptr_dc_unc)) + return False; + + if (!prs_uint32("ptr_dc_address", ps, depth, &r_t->ptr_dc_address)) + return False; + + if (!prs_uint32("dc_address_type", ps, depth, &r_t->dc_address_type)) + return False; + + if (!smb_io_uuid("domain_guid", &r_t->domain_guid, ps, depth)) + return False; + + if (!prs_uint32("ptr_domain_name", ps, depth, &r_t->ptr_domain_name)) + return False; + + if (!prs_uint32("ptr_forest_name", ps, depth, &r_t->ptr_forest_name)) + return False; + + if (!prs_uint32("dc_flags", ps, depth, &r_t->dc_flags)) + return False; + + if (!prs_uint32("ptr_dc_site_name", ps, depth, &r_t->ptr_dc_site_name)) + return False; + + if (!prs_uint32("ptr_client_site_name", ps, depth, + &r_t->ptr_client_site_name)) + return False; + + if (!prs_align(ps)) + return False; + + if (!smb_io_unistr2("dc_unc", &r_t->uni_dc_unc, + r_t->ptr_dc_unc, ps, depth)) + return False; + + if (!prs_align(ps)) + return False; + + if (!smb_io_unistr2("dc_address", &r_t->uni_dc_address, + r_t->ptr_dc_address, ps, depth)) + return False; + + if (!prs_align(ps)) + return False; + + if (!smb_io_unistr2("domain_name", &r_t->uni_domain_name, + r_t->ptr_domain_name, ps, depth)) + return False; + + if (!prs_align(ps)) + return False; + + if (!smb_io_unistr2("forest_name", &r_t->uni_forest_name, + r_t->ptr_forest_name, ps, depth)) + return False; + + if (!prs_align(ps)) + return False; + + if (!smb_io_unistr2("dc_site_name", &r_t->uni_dc_site_name, + r_t->ptr_dc_site_name, ps, depth)) + return False; + + if (!prs_align(ps)) + return False; + + if (!smb_io_unistr2("client_site_name", &r_t->uni_client_site_name, + r_t->ptr_client_site_name, ps, depth)) + return False; + + if (!prs_align(ps)) + return False; + + if (!prs_werror("result", ps, depth, &r_t->result)) + return False; + + return True; +} + +/******************************************************************* + Inits a NET_Q_DSR_GETSITENAME structure. +********************************************************************/ + +void init_net_q_dsr_getsitename(NET_Q_DSR_GETSITENAME *r_t, const char *computer_name) +{ + DEBUG(5, ("init_net_q_dsr_getsitename\n")); + + r_t->ptr_computer_name = (computer_name != NULL); + init_unistr2(&r_t->uni_computer_name, computer_name, UNI_STR_TERMINATE); +} + +/******************************************************************* + Reads or writes an NET_Q_DSR_GETSITENAME structure. +********************************************************************/ + +BOOL net_io_q_dsr_getsitename(const char *desc, NET_Q_DSR_GETSITENAME *r_t, + prs_struct *ps, int depth) +{ + if (r_t == NULL) + return False; + + prs_debug(ps, depth, desc, "net_io_q_dsr_getsitename"); + depth++; + + if (!prs_uint32("ptr_computer_name", ps, depth, &r_t->ptr_computer_name)) + return False; + + if (!smb_io_unistr2("computer_name", &r_t->uni_computer_name, + r_t->ptr_computer_name, ps, depth)) + return False; + + if (!prs_align(ps)) + return False; + + return True; +} + +/******************************************************************* + Reads or writes an NET_R_DSR_GETSITENAME structure. +********************************************************************/ + +BOOL net_io_r_dsr_getsitename(const char *desc, NET_R_DSR_GETSITENAME *r_t, + prs_struct *ps, int depth) +{ + if (r_t == NULL) + return False; + + prs_debug(ps, depth, desc, "net_io_r_dsr_getsitename"); + depth++; + + if (!prs_uint32("ptr_site_name", ps, depth, &r_t->ptr_site_name)) + return False; + + if (!prs_align(ps)) + return False; + + if (!smb_io_unistr2("site_name", &r_t->uni_site_name, + r_t->ptr_site_name, ps, depth)) + return False; + + if (!prs_align(ps)) + return False; + + if (!prs_werror("result", ps, depth, &r_t->result)) + return False; + + return True; +} + + diff --git a/source/rpc_parse/parse_samr.c b/source/rpc_parse/parse_samr.c index 2ba99fff495..0a055ff826a 100644 --- a/source/rpc_parse/parse_samr.c +++ b/source/rpc_parse/parse_samr.c @@ -778,11 +778,11 @@ inits a structure. ********************************************************************/ void init_unk_info1(SAM_UNK_INFO_1 *u_1, uint16 min_pass_len, uint16 pass_hist, - uint32 flag, NTTIME nt_expire, NTTIME nt_min_age) + uint32 password_properties, NTTIME nt_expire, NTTIME nt_min_age) { u_1->min_length_password = min_pass_len; u_1->password_history = pass_hist; - u_1->flag = flag; + u_1->password_properties = password_properties; /* password never expire */ u_1->expire.high = nt_expire.high; @@ -811,7 +811,7 @@ static BOOL sam_io_unk_info1(const char *desc, SAM_UNK_INFO_1 * u_1, return False; if(!prs_uint16("password_history", ps, depth, &u_1->password_history)) return False; - if(!prs_uint32("flag", ps, depth, &u_1->flag)) + if(!prs_uint32("password_properties", ps, depth, &u_1->password_properties)) return False; if(!smb_io_time("expire", &u_1->expire, ps, depth)) return False; @@ -6734,7 +6734,7 @@ inits a SAMR_Q_CONNECT4 structure. void init_samr_q_connect4(SAMR_Q_CONNECT4 * q_u, char *srv_name, uint32 access_mask) { - DEBUG(5, ("init_samr_q_connect\n")); + DEBUG(5, ("init_samr_q_connect4\n")); /* make PDC server name \\server */ q_u->ptr_srv_name = (srv_name != NULL && *srv_name) ? 1 : 0; @@ -6803,6 +6803,116 @@ BOOL samr_io_r_connect4(const char *desc, SAMR_R_CONNECT4 * r_u, return True; } +/******************************************************************* +inits a SAMR_Q_CONNECT5 structure. +********************************************************************/ + +void init_samr_q_connect5(SAMR_Q_CONNECT5 * q_u, + char *srv_name, uint32 access_mask) +{ + DEBUG(5, ("init_samr_q_connect5\n")); + + /* make PDC server name \\server */ + q_u->ptr_srv_name = (srv_name != NULL && *srv_name) ? 1 : 0; + init_unistr2(&q_u->uni_srv_name, srv_name, UNI_STR_TERMINATE); + + /* example values: 0x0000 0002 */ + q_u->access_mask = access_mask; + + q_u->level = 1; + q_u->info1_unk1 = 3; + q_u->info1_unk2 = 0; +} + +/******************************************************************* +inits a SAMR_R_CONNECT5 structure. +********************************************************************/ + +void init_samr_r_connect5(SAMR_R_CONNECT5 * r_u, POLICY_HND *pol, NTSTATUS status) +{ + DEBUG(5, ("init_samr_q_connect5\n")); + + r_u->level = 1; + r_u->info1_unk1 = 3; + r_u->info1_unk2 = 0; + + r_u->connect_pol = *pol; + r_u->status = status; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ + +BOOL samr_io_q_connect5(const char *desc, SAMR_Q_CONNECT5 * q_u, + prs_struct *ps, int depth) +{ + if (q_u == NULL) + return False; + + prs_debug(ps, depth, desc, "samr_io_q_connect5"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!prs_uint32("ptr_srv_name", ps, depth, &q_u->ptr_srv_name)) + return False; + if(!smb_io_unistr2("", &q_u->uni_srv_name, q_u->ptr_srv_name, ps, depth)) + return False; + + if(!prs_align(ps)) + return False; + if(!prs_uint32("access_mask", ps, depth, &q_u->access_mask)) + return False; + + if(!prs_uint32("level", ps, depth, &q_u->level)) + return False; + if(!prs_uint32("level", ps, depth, &q_u->level)) + return False; + + if(!prs_uint32("info1_unk1", ps, depth, &q_u->info1_unk1)) + return False; + if(!prs_uint32("info1_unk2", ps, depth, &q_u->info1_unk2)) + return False; + + return True; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ + +BOOL samr_io_r_connect5(const char *desc, SAMR_R_CONNECT5 * r_u, + prs_struct *ps, int depth) +{ + if (r_u == NULL) + return False; + + prs_debug(ps, depth, desc, "samr_io_r_connect5"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!prs_uint32("level", ps, depth, &r_u->level)) + return False; + if(!prs_uint32("level", ps, depth, &r_u->level)) + return False; + if(!prs_uint32("info1_unk1", ps, depth, &r_u->info1_unk1)) + return False; + if(!prs_uint32("info1_unk2", ps, depth, &r_u->info1_unk2)) + return False; + + if(!smb_io_pol_hnd("connect_pol", &r_u->connect_pol, ps, depth)) + return False; + + if(!prs_ntstatus("status", ps, depth, &r_u->status)) + return False; + + return True; +} + /******************************************************************* inits a SAMR_Q_CONNECT_ANON structure. ********************************************************************/ @@ -6928,15 +7038,11 @@ BOOL samr_io_r_get_dom_pwinfo(const char *desc, SAMR_R_GET_DOM_PWINFO * r_u, if(!prs_align(ps)) return False; - /* - * see the Samba4 IDL for what these actually are. - */ - - if(!prs_uint16("unk_0", ps, depth, &r_u->unk_0)) + if(!prs_uint16("min_pwd_length", ps, depth, &r_u->min_pwd_length)) return False; if(!prs_align(ps)) return False; - if(!prs_uint32("unk_1", ps, depth, &r_u->unk_1)) + if(!prs_uint32("password_properties", ps, depth, &r_u->password_properties)) return False; if(!prs_ntstatus("status", ps, depth, &r_u->status)) @@ -7031,7 +7137,7 @@ BOOL samr_io_enc_hash(const char *desc, SAMR_ENC_HASH * hsh, } /******************************************************************* -inits a SAMR_R_GET_DOM_PWINFO structure. +inits a SAMR_Q_CHGPASSWD_USER structure. ********************************************************************/ void init_samr_q_chgpasswd_user(SAMR_Q_CHGPASSWD_USER * q_u, @@ -7139,6 +7245,172 @@ BOOL samr_io_r_chgpasswd_user(const char *desc, SAMR_R_CHGPASSWD_USER * r_u, return True; } +/******************************************************************* +inits a SAMR_Q_CHGPASSWD3 structure. +********************************************************************/ + +void init_samr_q_chgpasswd3(SAMR_Q_CHGPASSWD3 * q_u, + const char *dest_host, const char *user_name, + const uchar nt_newpass[516], + const uchar nt_oldhash[16], + const uchar lm_newpass[516], + const uchar lm_oldhash[16]) +{ + DEBUG(5, ("init_samr_q_chgpasswd3\n")); + + q_u->ptr_0 = 1; + init_unistr2(&q_u->uni_dest_host, dest_host, UNI_FLAGS_NONE); + init_uni_hdr(&q_u->hdr_dest_host, &q_u->uni_dest_host); + + init_unistr2(&q_u->uni_user_name, user_name, UNI_FLAGS_NONE); + init_uni_hdr(&q_u->hdr_user_name, &q_u->uni_user_name); + + init_enc_passwd(&q_u->nt_newpass, (const char *)nt_newpass); + init_enc_hash(&q_u->nt_oldhash, nt_oldhash); + + q_u->lm_change = 0x01; + + init_enc_passwd(&q_u->lm_newpass, (const char *)lm_newpass); + init_enc_hash(&q_u->lm_oldhash, lm_oldhash); + + init_enc_passwd(&q_u->password3, NULL); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ + +BOOL samr_io_q_chgpasswd3(const char *desc, SAMR_Q_CHGPASSWD3 * q_u, + prs_struct *ps, int depth) +{ + if (q_u == NULL) + return False; + + prs_debug(ps, depth, desc, "samr_io_q_chgpasswd3"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!prs_uint32("ptr_0", ps, depth, &q_u->ptr_0)) + return False; + + if(!smb_io_unihdr("", &q_u->hdr_dest_host, ps, depth)) + return False; + if(!smb_io_unistr2("", &q_u->uni_dest_host, q_u->hdr_dest_host.buffer, ps, depth)) + return False; + + if(!prs_align(ps)) + return False; + if(!smb_io_unihdr("", &q_u->hdr_user_name, ps, depth)) + return False; + if(!smb_io_unistr2("", &q_u->uni_user_name, q_u->hdr_user_name.buffer,ps, depth)) + return False; + + if(!samr_io_enc_passwd("nt_newpass", &q_u->nt_newpass, ps, depth)) + return False; + if(!samr_io_enc_hash("nt_oldhash", &q_u->nt_oldhash, ps, depth)) + return False; + + if(!prs_uint32("lm_change", ps, depth, &q_u->lm_change)) + return False; + + if(!samr_io_enc_passwd("lm_newpass", &q_u->lm_newpass, ps, depth)) + return False; + if(!samr_io_enc_hash("lm_oldhash", &q_u->lm_oldhash, ps, depth)) + return False; + + if(!samr_io_enc_passwd("password3", &q_u->password3, ps, depth)) + return False; + + return True; +} + +/******************************************************************* +inits a SAMR_R_CHGPASSWD3 structure. +********************************************************************/ + +void init_samr_r_chgpasswd3(SAMR_R_CHGPASSWD3 * r_u, NTSTATUS status) +{ + DEBUG(5, ("init_r_chgpasswd3\n")); + + r_u->status = status; +} + +/******************************************************************* + Reads or writes an SAMR_CHANGE_REJECT structure. +********************************************************************/ + +BOOL samr_io_change_reject(const char *desc, SAMR_CHANGE_REJECT *reject, prs_struct *ps, int depth) +{ + if (reject == NULL) + return False; + + prs_debug(ps, depth, desc, "samr_io_change_reject"); + depth++; + + if(!prs_align(ps)) + return False; + + if(UNMARSHALLING(ps)) + ZERO_STRUCTP(reject); + + if (!prs_uint32("reject_reason", ps, depth, &reject->reject_reason)) + return False; + + if (!prs_uint32("unknown1", ps, depth, &reject->unknown1)) + return False; + + if (!prs_uint32("unknown2", ps, depth, &reject->unknown2)) + return False; + + return True; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ + +BOOL samr_io_r_chgpasswd3(const char *desc, SAMR_R_CHGPASSWD3 * r_u, + prs_struct *ps, int depth) +{ + uint32 ptr_info, ptr_reject; + + if (r_u == NULL) + return False; + + prs_debug(ps, depth, desc, "samr_io_r_chgpasswd3"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!prs_uint32("ptr_info", ps, depth, &ptr_info)) + return False; + + if (ptr_info) { + + /* SAM_UNK_INFO_1 */ + if(!sam_io_unk_info1("info", &r_u->info, ps, depth)) + return False; + } + + if(!prs_uint32("ptr_reject", ps, depth, &ptr_reject)) + return False; + + if (ptr_reject) { + + /* SAMR_CHANGE_REJECT */ + if(!samr_io_change_reject("reject", &r_u->reject, ps, depth)) + return False; + } + + if(!prs_ntstatus("status", ps, depth, &r_u->status)) + return False; + + return True; +} + /******************************************************************* reads or writes a structure. ********************************************************************/ diff --git a/source/rpc_server/srv_netlog_nt.c b/source/rpc_server/srv_netlog_nt.c index 7903adff6d5..d0d47be9f29 100644 --- a/source/rpc_server/srv_netlog_nt.c +++ b/source/rpc_server/srv_netlog_nt.c @@ -584,6 +584,35 @@ NTSTATUS _net_sam_logoff(pipes_struct *p, NET_Q_SAM_LOGOFF *q_u, NET_R_SAM_LOGOF } +/******************************************************************* + gets a domain user's groups from their already-calculated NT_USER_TOKEN + ********************************************************************/ +static NTSTATUS nt_token_to_group_list(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid, + const NT_USER_TOKEN *nt_token, + int *numgroups, DOM_GID **pgids) +{ + DOM_GID *gids; + int i; + + gids = TALLOC_ARRAY(mem_ctx, DOM_GID, nt_token->num_sids); + + if (!gids) { + return NT_STATUS_NO_MEMORY; + } + + *numgroups=0; + + for (i=PRIMARY_GROUP_SID_INDEX; i < nt_token->num_sids; i++) { + if (sid_compare_domain(domain_sid, &nt_token->user_sids[i])==0) { + sid_peek_rid(&nt_token->user_sids[i], &(gids[*numgroups].g_rid)); + gids[*numgroups].attr= (SE_GROUP_MANDATORY|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_ENABLED); + (*numgroups)++; + } + } + *pgids = gids; + return NT_STATUS_OK; +} + /************************************************************************* _net_sam_logon *************************************************************************/ diff --git a/source/rpc_server/srv_pipe.c b/source/rpc_server/srv_pipe.c index b615080d349..8084e7673a5 100644 --- a/source/rpc_server/srv_pipe.c +++ b/source/rpc_server/srv_pipe.c @@ -892,6 +892,55 @@ BOOL setup_fault_pdu(pipes_struct *p, NTSTATUS status) return True; } +#if 0 +/******************************************************************* + Marshall a cancel_ack pdu. + We should probably check the auth-verifier here. +*******************************************************************/ + +BOOL setup_cancel_ack_reply(pipes_struct *p, prs_struct *rpc_in_p) +{ + prs_struct outgoing_pdu; + RPC_HDR ack_reply_hdr; + + /* Free any memory in the current return data buffer. */ + prs_mem_free(&p->out_data.rdata); + + /* + * Marshall directly into the outgoing PDU space. We + * must do this as we need to set to the bind response + * header and are never sending more than one PDU here. + */ + + prs_init( &outgoing_pdu, 0, p->mem_ctx, MARSHALL); + prs_give_memory( &outgoing_pdu, (char *)p->out_data.current_pdu, sizeof(p->out_data.current_pdu), False); + + /* + * Initialize a cancel_ack header. + */ + + init_rpc_hdr(&ack_reply_hdr, RPC_CANCEL_ACK, RPC_FLG_FIRST | RPC_FLG_LAST, + p->hdr.call_id, RPC_HEADER_LEN, 0); + + /* + * Marshall the header into the outgoing PDU. + */ + + if(!smb_io_rpc_hdr("", &ack_reply_hdr, &outgoing_pdu, 0)) { + DEBUG(0,("setup_cancel_ack_reply: marshalling of RPC_HDR failed.\n")); + prs_mem_free(&outgoing_pdu); + return False; + } + + p->out_data.data_sent_length = 0; + p->out_data.current_pdu_len = prs_offset(&outgoing_pdu); + p->out_data.current_pdu_sent = 0; + + prs_mem_free(&outgoing_pdu); + return True; +} +#endif + /******************************************************************* Ensure a bind request has the correct abstract & transfer interface. Used to reject unknown binds from Win2k. diff --git a/source/rpc_server/srv_pipe_hnd.c b/source/rpc_server/srv_pipe_hnd.c index 6077faed164..5fb84115cc3 100644 --- a/source/rpc_server/srv_pipe_hnd.c +++ b/source/rpc_server/srv_pipe_hnd.c @@ -716,6 +716,32 @@ static void process_complete_pdu(pipes_struct *p) (unsigned int)p->hdr.pkt_type )); switch (p->hdr.pkt_type) { + case RPC_REQUEST: + reply = process_request_pdu(p, &rpc_in); + break; + + case RPC_PING: /* CL request - ignore... */ + DEBUG(0,("process_complete_pdu: Error. Connectionless packet type %u received on pipe %s.\n", + (unsigned int)p->hdr.pkt_type, p->name)); + break; + + case RPC_RESPONSE: /* No responses here. */ + DEBUG(0,("process_complete_pdu: Error. RPC_RESPONSE received from client on pipe %s.\n", + p->name )); + break; + + case RPC_FAULT: + case RPC_WORKING: /* CL request - reply to a ping when a call in process. */ + case RPC_NOCALL: /* CL - server reply to a ping call. */ + case RPC_REJECT: + case RPC_ACK: + case RPC_CL_CANCEL: + case RPC_FACK: + case RPC_CANCEL_ACK: + DEBUG(0,("process_complete_pdu: Error. Connectionless packet type %u received on pipe %s.\n", + (unsigned int)p->hdr.pkt_type, p->name)); + break; + case RPC_BIND: /* * We assume that a pipe bind is only in one pdu. @@ -724,6 +750,14 @@ static void process_complete_pdu(pipes_struct *p) reply = api_pipe_bind_req(p, &rpc_in); } break; + + case RPC_BINDACK: + case RPC_BINDNACK: + DEBUG(0,("process_complete_pdu: Error. RPC_BINDACK/RPC_BINDNACK packet type %u received on pipe %s.\n", + (unsigned int)p->hdr.pkt_type, p->name)); + break; + + case RPC_ALTCONT: /* * We assume that a pipe bind is only in one pdu. @@ -732,6 +766,12 @@ static void process_complete_pdu(pipes_struct *p) reply = api_pipe_alter_context(p, &rpc_in); } break; + + case RPC_ALTCONTRESP: + DEBUG(0,("process_complete_pdu: Error. RPC_ALTCONTRESP on pipe %s: Should only be server -> client.\n", + p->name)); + break; + case RPC_AUTH3: /* * The third packet in an NTLMSSP auth exchange. @@ -740,9 +780,38 @@ static void process_complete_pdu(pipes_struct *p) reply = api_pipe_bind_auth3(p, &rpc_in); } break; - case RPC_REQUEST: - reply = process_request_pdu(p, &rpc_in); + + case RPC_SHUTDOWN: + DEBUG(0,("process_complete_pdu: Error. RPC_SHUTDOWN on pipe %s: Should only be server -> client.\n", + p->name)); + break; + + case RPC_CO_CANCEL: + /* For now just free all client data and continue processing. */ + DEBUG(3,("process_complete_pdu: RPC_ORPHANED. Abandoning rpc call.\n")); + /* As we never do asynchronous RPC serving, we can never cancel a + call (as far as I know). If we ever did we'd have to send a cancel_ack + reply. For now, just free all client data and continue processing. */ + reply = True; break; +#if 0 + /* Enable this if we're doing async rpc. */ + /* We must check the call-id matches the outstanding callid. */ + if(pipe_init_outgoing_data(p)) { + /* Send a cancel_ack PDU reply. */ + /* We should probably check the auth-verifier here. */ + reply = setup_cancel_ack_reply(p, &rpc_in); + } + break; +#endif + + case RPC_ORPHANED: + /* We should probably check the auth-verifier here. + For now just free all client data and continue processing. */ + DEBUG(3,("process_complete_pdu: RPC_ORPHANED. Abandoning rpc call.\n")); + reply = True; + break; + default: DEBUG(0,("process_complete_pdu: Unknown rpc type = %u received.\n", (unsigned int)p->hdr.pkt_type )); break; @@ -815,7 +884,13 @@ incoming data size = %u\n", (unsigned int)p->in_data.pdu_received_len, (unsigned */ if(p->in_data.pdu_needed_len == 0) { - return unmarshall_rpc_header(p); + ssize_t rret = unmarshall_rpc_header(p); + if (rret == -1 || p->in_data.pdu_needed_len > 0) { + return rret; + } + /* If rret == 0 and pdu_needed_len == 0 here we have a PDU that consists + of an RPC_HEADER only. This is a RPC_SHUTDOWN, RPC_CO_CANCEL or RPC_ORPHANED + pdu type. Deal with this in process_complete_pdu(). */ } /* diff --git a/source/rpc_server/srv_samr_nt.c b/source/rpc_server/srv_samr_nt.c index 4d44f8312b3..8f981dc41d4 100644 --- a/source/rpc_server/srv_samr_nt.c +++ b/source/rpc_server/srv_samr_nt.c @@ -5,11 +5,12 @@ * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, * Copyright (C) Paul Ashton 1997, * Copyright (C) Marc Jacobsen 1999, - * Copyright (C) Jeremy Allison 2001-2002, + * Copyright (C) Jeremy Allison 2001-2005, * Copyright (C) Jean François Micouleau 1998-2001, * Copyright (C) Jim McDonough 2002, * Copyright (C) Gerald (Jerry) Carter 2003-2004, * Copyright (C) Simo Sorce 2003. + * Copyright (C) Volker Lendecke 2005. * * 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 @@ -46,15 +47,16 @@ typedef struct disp_info { struct disp_info *next, *prev; TALLOC_CTX *mem_ctx; DOM_SID sid; /* identify which domain this is. */ + BOOL builtin_domain; /* Quick flag to check if this is the builtin domain. */ struct pdb_search *users; /* querydispinfo 1 and 4 */ struct pdb_search *machines; /* querydispinfo 2 */ struct pdb_search *groups; /* querydispinfo 3 and 5, enumgroups */ struct pdb_search *aliases; /* enumaliases */ - struct pdb_search *builtins; /* enumaliases */ uint16 enum_acb_mask; struct pdb_search *enum_users; /* enumusers with a mask */ + smb_event_id_t di_cache_timeout_event; /* cache idle timeout handler. */ } DISP_INFO; @@ -66,19 +68,38 @@ static DISP_INFO *disp_info_list; struct samr_info { /* for use by the \PIPE\samr policy */ DOM_SID sid; + BOOL builtin_domain; /* Quick flag to check if this is the builtin domain. */ uint32 status; /* some sort of flag. best to record it. comes from opnum 0x39 */ uint32 acc_granted; - uint16 acb_mask; - BOOL only_machines; DISP_INFO *disp_info; TALLOC_CTX *mem_ctx; }; -struct generic_mapping sam_generic_mapping = {GENERIC_RIGHTS_SAM_READ, GENERIC_RIGHTS_SAM_WRITE, GENERIC_RIGHTS_SAM_EXECUTE, GENERIC_RIGHTS_SAM_ALL_ACCESS}; -struct generic_mapping dom_generic_mapping = {GENERIC_RIGHTS_DOMAIN_READ, GENERIC_RIGHTS_DOMAIN_WRITE, GENERIC_RIGHTS_DOMAIN_EXECUTE, GENERIC_RIGHTS_DOMAIN_ALL_ACCESS}; -struct generic_mapping usr_generic_mapping = {GENERIC_RIGHTS_USER_READ, GENERIC_RIGHTS_USER_WRITE, GENERIC_RIGHTS_USER_EXECUTE, GENERIC_RIGHTS_USER_ALL_ACCESS}; -struct generic_mapping grp_generic_mapping = {GENERIC_RIGHTS_GROUP_READ, GENERIC_RIGHTS_GROUP_WRITE, GENERIC_RIGHTS_GROUP_EXECUTE, GENERIC_RIGHTS_GROUP_ALL_ACCESS}; -struct generic_mapping ali_generic_mapping = {GENERIC_RIGHTS_ALIAS_READ, GENERIC_RIGHTS_ALIAS_WRITE, GENERIC_RIGHTS_ALIAS_EXECUTE, GENERIC_RIGHTS_ALIAS_ALL_ACCESS}; +static struct generic_mapping sam_generic_mapping = { + GENERIC_RIGHTS_SAM_READ, + GENERIC_RIGHTS_SAM_WRITE, + GENERIC_RIGHTS_SAM_EXECUTE, + GENERIC_RIGHTS_SAM_ALL_ACCESS}; +static struct generic_mapping dom_generic_mapping = { + GENERIC_RIGHTS_DOMAIN_READ, + GENERIC_RIGHTS_DOMAIN_WRITE, + GENERIC_RIGHTS_DOMAIN_EXECUTE, + GENERIC_RIGHTS_DOMAIN_ALL_ACCESS}; +static struct generic_mapping usr_generic_mapping = { + GENERIC_RIGHTS_USER_READ, + GENERIC_RIGHTS_USER_WRITE, + GENERIC_RIGHTS_USER_EXECUTE, + GENERIC_RIGHTS_USER_ALL_ACCESS}; +static struct generic_mapping grp_generic_mapping = { + GENERIC_RIGHTS_GROUP_READ, + GENERIC_RIGHTS_GROUP_WRITE, + GENERIC_RIGHTS_GROUP_EXECUTE, + GENERIC_RIGHTS_GROUP_ALL_ACCESS}; +static struct generic_mapping ali_generic_mapping = { + GENERIC_RIGHTS_ALIAS_READ, + GENERIC_RIGHTS_ALIAS_WRITE, + GENERIC_RIGHTS_ALIAS_EXECUTE, + GENERIC_RIGHTS_ALIAS_ALL_ACCESS}; /******************************************************************* *******************************************************************/ @@ -247,8 +268,12 @@ static DISP_INFO *get_samr_dispinfo_by_sid(DOM_SID *psid, const char *sid_str) return NULL; dpi->mem_ctx = mem_ctx; + if (psid) { sid_copy( &dpi->sid, psid); + dpi->builtin_domain = sid_check_is_builtin(psid); + } else { + dpi->builtin_domain = False; } DLIST_ADD(disp_info_list, dpi); @@ -280,8 +305,10 @@ static struct samr_info *get_samr_info_by_sid(DOM_SID *psid) DEBUG(10,("get_samr_info_by_sid: created new info for sid %s\n", sid_str)); if (psid) { sid_copy( &info->sid, psid); + info->builtin_domain = sid_check_is_builtin(psid); } else { DEBUG(10,("get_samr_info_by_sid: created new info for NULL sid.\n")); + info->builtin_domain = False; } info->mem_ctx = mem_ctx; @@ -328,11 +355,6 @@ static void free_samr_cache(DISP_INFO *disp_info, const char *sid_str) pdb_search_destroy(disp_info->aliases); disp_info->aliases = NULL; } - if (disp_info->builtins) { - DEBUG(10,("free_samr_cache: deleting builtins cache\n")); - pdb_search_destroy(disp_info->builtins); - disp_info->builtins = NULL; - } if (disp_info->enum_users) { DEBUG(10,("free_samr_cache: deleting enum_users cache\n")); pdb_search_destroy(disp_info->enum_users); @@ -452,6 +474,12 @@ static void samr_clear_sam_passwd(SAM_ACCOUNT *sam_pass) static uint32 count_sam_users(struct disp_info *info, uint16 acct_flags) { struct samr_displayentry *entry; + + if (info->builtin_domain) { + /* No users in builtin. */ + return 0; + } + if (info->users == NULL) { info->users = pdb_search_users(acct_flags); if (info->users == NULL) { @@ -470,6 +498,12 @@ static uint32 count_sam_users(struct disp_info *info, uint16 acct_flags) static uint32 count_sam_groups(struct disp_info *info) { struct samr_displayentry *entry; + + if (info->builtin_domain) { + /* No groups in builtin. */ + return 0; + } + if (info->groups == NULL) { info->groups = pdb_search_groups(); if (info->groups == NULL) { @@ -485,6 +519,25 @@ static uint32 count_sam_groups(struct disp_info *info) return info->groups->num_entries; } +static uint32 count_sam_aliases(struct disp_info *info) +{ + struct samr_displayentry *entry; + + if (info->aliases == NULL) { + info->aliases = pdb_search_aliases(&info->sid); + if (info->aliases == NULL) { + return 0; + } + } + /* Fetch the last possible entry, thus trigger an enumeration */ + pdb_search_entries(info->aliases, 0xffffffff, 1, &entry); + + /* Ensure we cache this enumeration. */ + set_disp_info_cache_timeout(info, DISP_INFO_CACHE_TIMEOUT); + + return info->aliases->num_entries; +} + /******************************************************************* _samr_close_hnd ********************************************************************/ @@ -544,6 +597,11 @@ NTSTATUS _samr_open_domain(pipes_struct *p, SAMR_Q_OPEN_DOMAIN *q_u, SAMR_R_OPEN if ( !NT_STATUS_IS_OK(status) ) return status; + if (!sid_check_is_domain(&q_u->dom_sid.sid) && + !sid_check_is_builtin(&q_u->dom_sid.sid)) { + return NT_STATUS_NO_SUCH_DOMAIN; + } + /* associate the domain SID with the (unique) handle. */ if ((info = get_samr_info_by_sid(&q_u->dom_sid.sid))==NULL) return NT_STATUS_NO_MEMORY; @@ -756,6 +814,13 @@ NTSTATUS _samr_enum_dom_users(pipes_struct *p, SAMR_Q_ENUM_DOM_USERS *q_u, DEBUG(5,("_samr_enum_dom_users: %d\n", __LINE__)); + if (info->builtin_domain) { + /* No users in builtin. */ + init_samr_r_enum_dom_users(r_u, q_u->start_idx, 0); + DEBUG(5,("_samr_enum_dom_users: No users in BUILTIN\n")); + return r_u->status; + } + become_root(); /* AS ROOT !!!! */ @@ -882,6 +947,13 @@ NTSTATUS _samr_enum_dom_groups(pipes_struct *p, SAMR_Q_ENUM_DOM_GROUPS *q_u, SAM DEBUG(5,("samr_reply_enum_dom_groups: %d\n", __LINE__)); + if (info->builtin_domain) { + /* No groups in builtin. */ + init_samr_r_enum_dom_groups(r_u, q_u->start_idx, 0); + DEBUG(5,("_samr_enum_dom_users: No groups in BUILTIN\n")); + return r_u->status; + } + /* the domain group array is being allocated in the function below */ become_root(); @@ -920,7 +992,6 @@ NTSTATUS _samr_enum_dom_aliases(pipes_struct *p, SAMR_Q_ENUM_DOM_ALIASES *q_u, S { struct samr_info *info; struct samr_displayentry *aliases; - struct pdb_search **search = NULL; uint32 num_aliases = 0; /* find the policy handle. open a policy on it. */ @@ -936,25 +1007,17 @@ NTSTATUS _samr_enum_dom_aliases(pipes_struct *p, SAMR_Q_ENUM_DOM_ALIASES *q_u, S DEBUG(5,("samr_reply_enum_dom_aliases: sid %s\n", sid_string_static(&info->sid))); - if (sid_check_is_domain(&info->sid)) - search = &info->disp_info->aliases; - if (sid_check_is_builtin(&info->sid)) - search = &info->disp_info->builtins; - - if (search == NULL) - return NT_STATUS_INVALID_HANDLE; - become_root(); - if (*search == NULL) { - *search = pdb_search_aliases(&info->sid); - if (*search == NULL) { + if (info->disp_info->aliases == NULL) { + info->disp_info->aliases = pdb_search_aliases(&info->sid); + if (info->disp_info->aliases == NULL) { unbecome_root(); return NT_STATUS_ACCESS_DENIED; } } - num_aliases = pdb_search_entries(*search, q_u->start_idx, + num_aliases = pdb_search_entries(info->disp_info->aliases, q_u->start_idx, MAX_SAM_ENTRIES, &aliases); unbecome_root(); @@ -1493,19 +1556,11 @@ NTSTATUS _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOK if ((num_rids != 0) && ((names == NULL) || (attrs == NULL))) return NT_STATUS_NO_MEMORY; - if (!sid_equal(&pol_sid, get_global_sam_sid())) { - /* TODO: Sooner or later we need to look up BUILTIN rids as - * well. -- vl */ - goto done; - } - become_root(); /* lookup_sid can require root privs */ - r_u->status = pdb_lookup_rids(p->mem_ctx, &pol_sid, num_rids, q_u->rid, - &names, &attrs); + r_u->status = pdb_lookup_rids(&pol_sid, num_rids, q_u->rid, + names, attrs); unbecome_root(); - done: - if(!make_samr_lookup_rids(p->mem_ctx, num_rids, names, &hdr_name, &uni_name)) return NT_STATUS_NO_MEMORY; @@ -2081,9 +2136,9 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA /* AS ROOT !!! */ - num_users=count_sam_users(info->disp_info, - ACB_NORMAL); - num_groups=count_sam_groups(info->disp_info); + num_users = count_sam_users(info->disp_info, ACB_NORMAL); + num_groups = count_sam_groups(info->disp_info); + num_aliases = count_sam_aliases(info->disp_info); pdb_get_account_policy(AP_TIME_TO_LOGOUT, &account_policy_temp); u_logout = account_policy_temp; @@ -4623,9 +4678,9 @@ NTSTATUS _samr_query_domain_info2(pipes_struct *p, break; case 0x02: become_root(); - num_users = count_sam_users(info->disp_info, - ACB_NORMAL); + num_users = count_sam_users(info->disp_info, ACB_NORMAL); num_groups = count_sam_groups(info->disp_info); + num_aliases = count_sam_aliases(info->disp_info); unbecome_root(); pdb_get_account_policy(AP_TIME_TO_LOGOUT, &account_policy_temp); @@ -4725,7 +4780,7 @@ NTSTATUS _samr_set_dom_info(pipes_struct *p, SAMR_Q_SET_DOMAIN_INFO *q_u, SAMR_R pdb_set_account_policy(AP_MIN_PASSWORD_LEN, (uint32)q_u->ctr->info.inf1.min_length_password); pdb_set_account_policy(AP_PASSWORD_HISTORY, (uint32)q_u->ctr->info.inf1.password_history); - pdb_set_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, (uint32)q_u->ctr->info.inf1.flag); + pdb_set_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, (uint32)q_u->ctr->info.inf1.password_properties); pdb_set_account_policy(AP_MAX_PASSWORD_AGE, (int)u_expire); pdb_set_account_policy(AP_MIN_PASSWORD_AGE, (int)u_min_age); break; diff --git a/source/rpc_server/srv_spoolss_nt.c b/source/rpc_server/srv_spoolss_nt.c index e5b3ca3947d..f0ba863b4d7 100644 --- a/source/rpc_server/srv_spoolss_nt.c +++ b/source/rpc_server/srv_spoolss_nt.c @@ -479,29 +479,30 @@ static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename) DEBUGADD(5, ("searching for [%s]\n", aprinter )); /* Search all sharenames first as this is easier than pulling - the printer_info_2 off of disk */ + the printer_info_2 off of disk. Don't use find_service() since + that calls out to map_username() */ - snum = find_service(aprinter); - - if ( lp_snum_ok(snum) && lp_print_ok(snum) ) { - found = True; - fstrcpy( sname, aprinter ); - } - /* do another loop to look for printernames */ for (snum=0; !found && snummem_ctx, TIME_OF_DAY_INFO); if (!tod) @@ -1947,7 +1950,7 @@ WERROR _srv_net_remote_tod(pipes_struct *p, SRV_Q_NET_REMOTE_TOD *q_u, SRV_R_NET t->tm_min, t->tm_sec, 0, - get_time_zone(unixdate)/60, + zone, 10000, t->tm_mday, t->tm_mon + 1, diff --git a/source/rpc_server/srv_util.c b/source/rpc_server/srv_util.c index 3666d474787..924e08cc23a 100644 --- a/source/rpc_server/srv_util.c +++ b/source/rpc_server/srv_util.c @@ -81,32 +81,3 @@ static const rid_name domain_group_rids[] = }; #endif -/******************************************************************* - gets a domain user's groups from their already-calculated NT_USER_TOKEN - ********************************************************************/ -NTSTATUS nt_token_to_group_list(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid, - const NT_USER_TOKEN *nt_token, - int *numgroups, DOM_GID **pgids) -{ - DOM_GID *gids; - int i; - - gids = TALLOC_ARRAY(mem_ctx, DOM_GID, nt_token->num_sids); - - if (!gids) { - return NT_STATUS_NO_MEMORY; - } - - *numgroups=0; - - for (i=PRIMARY_GROUP_SID_INDEX; i < nt_token->num_sids; i++) { - if (sid_compare_domain(domain_sid, &nt_token->user_sids[i])==0) { - sid_peek_rid(&nt_token->user_sids[i], &(gids[*numgroups].g_rid)); - gids[*numgroups].attr= (SE_GROUP_MANDATORY|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_ENABLED); - (*numgroups)++; - } - } - *pgids = gids; - return NT_STATUS_OK; -} - diff --git a/source/rpcclient/cmd_lsarpc.c b/source/rpcclient/cmd_lsarpc.c index 5a0ba054833..c79508de8d0 100644 --- a/source/rpcclient/cmd_lsarpc.c +++ b/source/rpcclient/cmd_lsarpc.c @@ -771,7 +771,7 @@ static void display_trust_dom_info_1(TRUSTED_DOMAIN_INFO_NAME *n) static void display_trust_dom_info_3(TRUSTED_DOMAIN_INFO_POSIX_OFFSET *p) { - printf("Posix Offset:\t%d\n", p->posix_offset); + printf("Posix Offset:\t%08x (%d)\n", p->posix_offset, p->posix_offset); } static void display_trust_dom_info_4(TRUSTED_DOMAIN_INFO_PASSWORD *p, const char *password) @@ -800,6 +800,17 @@ static void display_trust_dom_info_4(TRUSTED_DOMAIN_INFO_PASSWORD *p, const char data_blob_free(&data_old); } +static void display_trust_dom_info_6(TRUSTED_DOMAIN_INFO_EX *i) +{ + printf("Domain Name:\t\t%s\n", unistr2_static(&i->domain_name.unistring)); + printf("NetBIOS Name:\t\t%s\n", unistr2_static(&i->netbios_name.unistring)); + printf("SID:\t\t\t%s\n", sid_string_static(&i->sid.sid)); + printf("Trust Direction:\t0x%08x\n", i->trust_direction); + printf("Trust Type:\t\t0x%08x\n", i->trust_type); + printf("Trust Attributes:\t0x%08x\n", i->trust_attributes); +} + + static void display_trust_dom_info(LSA_TRUSTED_DOMAIN_INFO *info, uint32 info_class, const char *pass) { switch (info_class) { @@ -812,6 +823,9 @@ static void display_trust_dom_info(LSA_TRUSTED_DOMAIN_INFO *info, uint32 info_cl case 4: display_trust_dom_info_4(&info->password, pass); break; + case 6: + display_trust_dom_info_6(&info->info_ex); + break; default: printf("unsupported info-class: %d\n", info_class); break; diff --git a/source/rpcclient/cmd_netlogon.c b/source/rpcclient/cmd_netlogon.c index d8f5a75b54e..9377f8fde8c 100644 --- a/source/rpcclient/cmd_netlogon.c +++ b/source/rpcclient/cmd_netlogon.c @@ -70,6 +70,60 @@ static NTSTATUS cmd_netlogon_getdcname(struct rpc_pipe_client *cli, return result; } +static WERROR cmd_netlogon_dsr_getdcname(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, int argc, + const char **argv) +{ + WERROR result; + char *dcname, *dcaddress; + + if (argc != 2) { + fprintf(stderr, "Usage: %s domainname\n", argv[0]); + return WERR_OK; + } + + result = rpccli_netlogon_dsr_getdcname( + cli, mem_ctx, cli->cli->desthost, argv[1], NULL, NULL, + 0x40000000, &dcname, &dcaddress, NULL, NULL, NULL, NULL, + NULL, NULL, NULL); + + if (W_ERROR_IS_OK(result)) { + printf("Domain %s's DC is called %s at IP %s\n", + argv[1], dcname, dcaddress); + return WERR_OK; + } + + printf("rpccli_netlogon_dsr_getdcname returned %s\n", + nt_errstr(werror_to_ntstatus(result))); + + return result; +} + +static WERROR cmd_netlogon_dsr_getsitename(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, int argc, + const char **argv) +{ + WERROR result; + char *sitename; + + if (argc != 2) { + fprintf(stderr, "Usage: %s computername\n", argv[0]); + return WERR_OK; + } + + result = rpccli_netlogon_dsr_getsitename(cli, mem_ctx, argv[1], &sitename); + + if (!W_ERROR_IS_OK(result)) { + printf("rpccli_netlogon_dsr_gesitename returned %s\n", + nt_errstr(werror_to_ntstatus(result))); + return result; + } + + printf("Computer %s is on Site: %s\n", argv[1], sitename); + + return WERR_OK; +} + static NTSTATUS cmd_netlogon_logon_ctrl(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) @@ -317,6 +371,8 @@ struct cmd_set netlogon_commands[] = { { "logonctrl2", RPC_RTYPE_NTSTATUS, cmd_netlogon_logon_ctrl2, NULL, PI_NETLOGON, NULL, "Logon Control 2", "" }, { "getdcname", RPC_RTYPE_NTSTATUS, cmd_netlogon_getdcname, NULL, PI_NETLOGON, NULL, "Get trusted DC name", "" }, + { "dsr_getdcname", RPC_RTYPE_WERROR, NULL, cmd_netlogon_dsr_getdcname, PI_NETLOGON, NULL, "Get trusted DC name", "" }, + { "dsr_getsitename", RPC_RTYPE_WERROR, NULL, cmd_netlogon_dsr_getsitename, PI_NETLOGON, NULL, "Get sitename", "" }, { "logonctrl", RPC_RTYPE_NTSTATUS, cmd_netlogon_logon_ctrl, NULL, PI_NETLOGON, NULL, "Logon Control", "" }, { "samsync", RPC_RTYPE_NTSTATUS, cmd_netlogon_sam_sync, NULL, PI_NETLOGON, NULL, "Sam Synchronisation", "" }, { "samdeltas", RPC_RTYPE_NTSTATUS, cmd_netlogon_sam_deltas, NULL, PI_NETLOGON, NULL, "Query Sam Deltas", "" }, diff --git a/source/rpcclient/cmd_samr.c b/source/rpcclient/cmd_samr.c index 6ff2bce8518..2050f2a7796 100644 --- a/source/rpcclient/cmd_samr.c +++ b/source/rpcclient/cmd_samr.c @@ -165,14 +165,32 @@ static const char* server_role_str(uint32 server_role) static void display_sam_unk_info_1(SAM_UNK_INFO_1 *info1) { - printf("Minimum password length: %d\n", info1->min_length_password); - printf("Password uniqueness (remember x passwords): %d\n", info1->password_history); - printf("flag: "); - if(info1->flag&&2==2) printf("users must open a session to change password "); - printf("\n"); - - printf("password expire in: %s\n", display_time(info1->expire)); - printf("Min password age (allow changing in x days): %s\n", display_time(info1->min_passwordage)); + printf("Minimum password length:\t\t\t%d\n", info1->min_length_password); + printf("Password uniqueness (remember x passwords):\t%d\n", info1->password_history); + printf("Password Properties:\t\t\t\t0x%08x\n", info1->password_properties); + + if (info1->password_properties & DOMAIN_PASSWORD_COMPLEX) + printf("\tDOMAIN_PASSWORD_COMPLEX\n"); + + if (info1->password_properties & DOMAIN_PASSWORD_NO_ANON_CHANGE) { + printf("\tDOMAIN_PASSWORD_NO_ANON_CHANGE\n"); + printf("users must open a session to change password "); + } + + if (info1->password_properties & DOMAIN_PASSWORD_NO_CLEAR_CHANGE) + printf("\tDOMAIN_PASSWORD_NO_CLEAR_CHANGE\n"); + + if (info1->password_properties & DOMAIN_LOCKOUT_ADMINS) + printf("\tDOMAIN_LOCKOUT_ADMINS\n"); + + if (info1->password_properties & DOMAIN_PASSWORD_STORE_CLEARTEXT) + printf("\tDOMAIN_PASSWORD_STORE_CLEARTEXT\n"); + + if (info1->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE) + printf("\tDOMAIN_REFUSE_PASSWORD_CHANGE\n"); + + printf("password expire in:\t\t\t\t%s\n", display_time(info1->expire)); + printf("Min password age (allow changing in x days):\t%s\n", display_time(info1->min_passwordage)); } static void display_sam_unk_info_2(SAM_UNK_INFO_2 *info2) @@ -333,7 +351,7 @@ static NTSTATUS cmd_samr_query_user(struct rpc_pipe_client *cli, return NT_STATUS_OK; } - sscanf(argv[1], "%i", &user_rid); + user_rid = strtoul(argv[1], NULL, 10); if (argc > 2) sscanf(argv[2], "%i", &info_level); @@ -362,6 +380,27 @@ static NTSTATUS cmd_samr_query_user(struct rpc_pipe_client *cli, access_mask, user_rid, &user_pol); + if (NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_USER) && + (user_rid == 0)) { + + /* Probably this was a user name, try lookupnames */ + uint32 num_rids; + uint32 *rids, *types; + + result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol, + 1000, 1, &argv[1], + &num_rids, &rids, + &types); + + if (NT_STATUS_IS_OK(result)) { + result = rpccli_samr_open_user(cli, mem_ctx, + &domain_pol, + access_mask, + rids[0], &user_pol); + } + } + + if (!NT_STATUS_IS_OK(result)) goto done; @@ -1457,8 +1496,8 @@ static NTSTATUS cmd_samr_lookup_rids(struct rpc_pipe_client *cli, char **names; int i; - if (argc < 2) { - printf("Usage: %s rid1 [rid2 [rid3] [...]]\n", argv[0]); + if (argc < 3) { + printf("Usage: %s domain|builtin rid1 [rid2 [rid3] [...]]\n", argv[0]); return NT_STATUS_OK; } @@ -1470,20 +1509,27 @@ static NTSTATUS cmd_samr_lookup_rids(struct rpc_pipe_client *cli, if (!NT_STATUS_IS_OK(result)) goto done; - result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol, - MAXIMUM_ALLOWED_ACCESS, - &domain_sid, &domain_pol); + if (StrCaseCmp(argv[1], "domain")==0) + result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol, + MAXIMUM_ALLOWED_ACCESS, + &domain_sid, &domain_pol); + else if (StrCaseCmp(argv[1], "builtin")==0) + result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol, + MAXIMUM_ALLOWED_ACCESS, + &global_sid_Builtin, &domain_pol); + else + return NT_STATUS_OK; if (!NT_STATUS_IS_OK(result)) goto done; /* Look up rids */ - num_rids = argc - 1; + num_rids = argc - 2; rids = TALLOC_ARRAY(mem_ctx, uint32, num_rids); - for (i = 0; i < argc - 1; i++) - sscanf(argv[i + 1], "%i", &rids[i]); + for (i = 0; i < argc - 2; i++) + sscanf(argv[i + 2], "%i", &rids[i]); result = rpccli_samr_lookup_rids(cli, mem_ctx, &domain_pol, num_rids, rids, &num_names, &names, &name_types); @@ -1663,18 +1709,37 @@ static NTSTATUS cmd_samr_get_dom_pwinfo(struct rpc_pipe_client *cli, int argc, const char **argv) { NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - uint16 unk_0, unk_1; + uint16 min_pwd_length; + uint32 password_properties; if (argc != 1) { printf("Usage: %s\n", argv[0]); return NT_STATUS_OK; } - result = rpccli_samr_get_dom_pwinfo(cli, mem_ctx, &unk_0, &unk_1) ; + result = rpccli_samr_get_dom_pwinfo(cli, mem_ctx, &min_pwd_length, &password_properties) ; if (NT_STATUS_IS_OK(result)) { - printf("unk_0 = 0x%08x\n", unk_0); - printf("unk_1 = 0x%08x\n", unk_1); + printf("min_pwd_length: %d\n", min_pwd_length); + printf("password_properties: 0x%08x\n", password_properties); + + if (password_properties & DOMAIN_PASSWORD_COMPLEX) + printf("\tDOMAIN_PASSWORD_COMPLEX\n"); + + if (password_properties & DOMAIN_PASSWORD_NO_ANON_CHANGE) + printf("\tDOMAIN_PASSWORD_NO_ANON_CHANGE\n"); + + if (password_properties & DOMAIN_PASSWORD_NO_CLEAR_CHANGE) + printf("\tDOMAIN_PASSWORD_NO_CLEAR_CHANGE\n"); + + if (password_properties & DOMAIN_LOCKOUT_ADMINS) + printf("\tDOMAIN_LOCKOUT_ADMINS\n"); + + if (password_properties & DOMAIN_PASSWORD_STORE_CLEARTEXT) + printf("\tDOMAIN_PASSWORD_STORE_CLEARTEXT\n"); + + if (password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE) + printf("\tDOMAIN_REFUSE_PASSWORD_CHANGE\n"); } return result; diff --git a/source/smbd/dosmode.c b/source/smbd/dosmode.c index 532c79043a2..7f3bda582df 100644 --- a/source/smbd/dosmode.c +++ b/source/smbd/dosmode.c @@ -190,7 +190,8 @@ static BOOL get_ea_dos_attribute(connection_struct *conn, const char *path,SMB_S return False; } - *pattr = 0; + /* Don't reset pattr to zero as we may already have filename-based attributes we + need to preserve. */ sizeret = SMB_VFS_GETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, sizeof(attrstr)); if (sizeret == -1) { @@ -337,6 +338,7 @@ uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf) if (result & aSYSTEM) DEBUG(8, ("s")); if (result & aDIR ) DEBUG(8, ("d")); if (result & aARCH ) DEBUG(8, ("a")); + if (result & FILE_ATTRIBUTE_SPARSE ) DEBUG(8, ("[sparse]")); DEBUG(8,("\n")); @@ -355,6 +357,9 @@ int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode, mode_t unixmode; int ret = -1; + /* We only allow READONLY|HIDDEN|SYSTEM|DIRECTORY|ARCHIVE here. */ + 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))) { st = &st1; diff --git a/source/smbd/filename.c b/source/smbd/filename.c index 2ee8ba1e4ff..6c0f8b77585 100644 --- a/source/smbd/filename.c +++ b/source/smbd/filename.c @@ -150,6 +150,19 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen pstrcpy(saved_last_component, name); } + /* + * Large directory fix normalization. If we're case sensitive, and + * the case preserving parameters are set to "no", normalize the case of + * the incoming filename from the client WHETHER IT EXISTS OR NOT ! + * This is in conflict with the current (3.0.20) man page, but is + * what people expect from the "large directory howto". I'll update + * the man page. Thanks to jht@samba.org for finding this. JRA. + */ + + if (conn->case_sensitive && !conn->case_preserve && !conn->short_case_preserve) { + strnorm(name, lp_defaultcase(SNUM(conn))); + } + start = name; pstrcpy(orig_path, name); diff --git a/source/utils/smbcontrol.c b/source/utils/smbcontrol.c index a0304eb89a9..25b42a58c1e 100644 --- a/source/utils/smbcontrol.c +++ b/source/utils/smbcontrol.c @@ -508,13 +508,13 @@ static BOOL do_poolusage(const struct process_id pid, return False; } + message_register(MSG_POOL_USAGE, print_string_cb); + /* Send a message and register our interest in a reply */ if (!send_message(pid, MSG_REQ_POOL_USAGE, NULL, 0, False)) return False; - message_register(MSG_POOL_USAGE, print_string_cb); - wait_replies(procid_to_pid(&pid) == 0); /* No replies were received within the timeout period */ diff --git a/source/utils/testparm.c b/source/utils/testparm.c index b4561b58deb..0ce838e5c76 100644 --- a/source/utils/testparm.c +++ b/source/utils/testparm.c @@ -73,6 +73,11 @@ cannot be set in the smb.conf file. nmbd will abort with this setting.\n"); ret = 1; } + if (lp_passdb_expand_explicit()) { + fprintf(stderr, "WARNING: passdb expand explicit = yes is " + "deprecated\n"); + } + /* * Password server sanity checks. */ -- cgit