From fecd5ea163ffcd1bbee5b06e05112dbff9aa71b1 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 4 Aug 2004 05:42:36 +0000 Subject: [PATCH] r1643: syncing all changes from 3.0 and hopefully get 3.0.6rc2 out tomorrow --- WHATSNEW.txt | 127 +++++- source/Makefile.in | 2 +- source/VERSION | 4 +- source/auth/auth.c | 2 +- source/auth/auth_sam.c | 6 + source/configure.in | 48 ++- source/include/includes.h | 9 + source/include/mangle.h | 2 +- source/include/ntdomain.h | 110 +++-- source/include/passdb.h | 8 +- source/include/smbldap.h | 7 +- source/lib/account_pol.c | 27 +- source/lib/afs.c | 2 +- source/lib/debug.c | 604 +++++++++++++-------------- source/lib/fsusage.c | 11 +- source/lib/genrand.c | 38 +- source/lib/smbldap.c | 191 ++++----- source/lib/util_str.c | 16 +- source/lib/util_uuid.c | 2 +- source/libsmb/cliconnect.c | 9 +- source/libsmb/clidgram.c | 2 +- source/libsmb/clientgen.c | 2 +- source/libsmb/clikrb5.c | 2 - source/libsmb/ntlmssp.c | 6 +- source/libsmb/passchange.c | 2 + source/libsmb/smb_signing.c | 4 +- source/libsmb/smbencrypt.c | 6 +- source/nsswitch/wbinfo.c | 43 +- source/nsswitch/winbindd.c | 13 + source/nsswitch/winbindd_cm.c | 1 - source/nsswitch/winbindd_pam.c | 2 +- source/nsswitch/wins.c | 2 +- source/param/loadparm.c | 22 +- source/passdb/machine_sid.c | 2 +- source/passdb/passdb.c | 810 +++++++++++++++++++------------------ source/passdb/pdb_get_set.c | 84 +++- source/passdb/pdb_ldap.c | 72 +++- source/passdb/pdb_tdb.c | 9 +- source/passdb/secrets.c | 60 ++- source/printing/printing.c | 3 - source/python/py_winbind.c | 4 +- source/rpc_client/cli_netlogon.c | 4 +- source/rpc_client/cli_srvsvc.c | 36 ++ source/rpc_parse/parse_prs.c | 2 +- source/rpc_server/srv_netlog_nt.c | 2 +- source/rpc_server/srv_pipe.c | 39 +- source/rpc_server/srv_pipe_hnd.c | 19 +- source/rpc_server/srv_spoolss_nt.c | 18 +- source/rpcclient/cmd_netlogon.c | 10 +- source/rpcclient/cmd_srvsvc.c | 23 ++ source/sam/idmap.c | 7 +- source/script/installswat.sh | 2 +- source/smbd/chgpasswd.c | 85 +++- source/smbd/filename.c | 4 +- source/smbd/mangle.c | 4 +- source/smbd/mangle_hash.c | 10 +- source/smbd/mangle_hash2.c | 8 +- source/smbd/password.c | 26 +- source/smbd/reply.c | 6 +- source/smbd/server.c | 11 +- source/smbd/service.c | 8 +- source/smbd/trans2.c | 39 +- source/torture/mangle_test.c | 4 + source/torture/torture.c | 2 +- source/utils/ntlm_auth.c | 4 +- source/utils/pdbedit.c | 62 +-- source/utils/smbpasswd.c | 31 +- source/wrepld/server.c | 2 +- 68 files changed, 1689 insertions(+), 1155 deletions(-) diff --git a/WHATSNEW.txt b/WHATSNEW.txt index d637d0065be..ea97e56844f 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -1,6 +1,6 @@ ================================ - Release Notes for Samba 3.0.5rc1 - July 8, 2004 + Release Notes for Samba 3.0.6rc2 + Aug 3, 2004 ================================ This is a release candidate snapshot of the Samba 3.0.5 code @@ -15,6 +15,120 @@ we feel are important to make available to the Samba community for wider testings. See the "Changes" section for details on exact updates. +Common bugs fixed in 3.0.6rc2 include: + + o + +New features introduced in this release include: + + o Support for maintaining user password history. + + +###################################################################### +Changes +####### + +Changes since 3.0.6rc1 +(formally referred to as 3.0.5rc1) +---------------------------------- + +smb.conf changes +---------------- + + Parameter Name Action + -------------- ------ + + +commits +------- +o Jeremy Allison + * Add support for storing a user's password history. + LDAP portion of the code was based on a patch from + Jianliang Lu . + + + +Changes for older versions follow below: + + -------------------------------------------------- + + ============================= + Release Notes for Samba 3.0.5 + July 20, 2004 + ============================= + +Please note that Samba 3.0.5 is identical to Samba 3.0.4 with +the exception of correcting the two security issues outlined +below. + +######################## SECURITY RELEASE ######################## + +Summary: Multiple Potential Buffer Overruns in Samba 3.0.x +CVE ID: CAN-2004-0600, CAN-2004-0686 + (http://cve.mitre.org/) + + +This is the latest stable release of Samba. This is the version +that production Samba servers should be running for all current +bug-fixes. + +It has been confirmed that versions of Samba 3 prior to v3.0.4 +are vulnerable to two potential buffer overruns. The individual +details are given below. + +------------- +CAN-2004-0600 +------------- + +Affected Versions: Samba 3.0.2 and later + +The internal routine used by the Samba Web Administration +Tool (SWAT v3.0.2 and later) to decode the base64 data +during HTTP basic authentication is subject to a buffer +overrun caused by an invalid base64 character. It is +recommended that all Samba v3.0.2 or later installations +running SWAT either (a) upgrade to v3.0.5, or (b) disable +the swat administration service as a temporary workaround. + +This same code is used internally to decode the +sambaMungedDial attribute value when using the ldapsam +passdb backend. While we do not believe that the base64 +decoding routines used by the ldapsam passdb backend can +be exploited, sites using an LDAP directory service with +Samba are strongly encouraged to verify that the DIT only +allows write access to sambaSamAccount attributes by a +sufficiently authorized user. + +The Samba Team would like to heartily thank Evgeny Demidov +for analyzing and reporting this bug. + +------------- +CAN-2004-0686 +------------- + +Affected Versions: Samba 3.0.0 and later + +A buffer overrun has been located in the code used to support +the 'mangling method = hash' smb.conf option. Please be aware +that the default setting for this parameter is 'mangling method += hash2' and therefore not vulnerable. + +Affected Samba 3 installations can avoid this possible security +bug by using the default hash2 mangling method. Server +installations requiring the hash mangling method are encouraged +to upgrade to Samba 3.0.5. + + +################################################################## + + + -------------------------------------------------- + + ================================ + Release Notes for Samba 3.0.5rc1 + July 8, 2004 + ================================ + Common bugs fixed in this 3.0.5rc1 include: o Corrupt workgroup names in nmbd's browse.dat. @@ -50,10 +164,8 @@ New features introduced in this release include: Changes ####### - - -Changes since 3.0.4 --------------------- +Changes since 3.0.5pre1 +----------------------- smb.conf changes ---------------- @@ -267,9 +379,6 @@ o Jelmer Vernooij * Prepare for better error checking in tar. - -Changes for older versions follow below: - -------------------------------------------------- ================================= diff --git a/source/Makefile.in b/source/Makefile.in index 398ad4e0e3f..58c8a7895d6 100644 --- a/source/Makefile.in +++ b/source/Makefile.in @@ -307,7 +307,7 @@ RPC_PARSE_OBJ = rpc_parse/parse_lsa.o rpc_parse/parse_net.o \ RPC_CLIENT_OBJ = rpc_client/cli_pipe.o -LOCKING_OBJ = locking/locking.o locking/brlock.o locking/posix.o smbd/tdbutil.o +LOCKING_OBJ = locking/locking.o locking/brlock.o locking/posix.o PASSDB_GET_SET_OBJ = passdb/pdb_get_set.o diff --git a/source/VERSION b/source/VERSION index b6dcf4957e3..6a3dd5010f9 100644 --- a/source/VERSION +++ b/source/VERSION @@ -19,7 +19,7 @@ ######################################################## SAMBA_VERSION_MAJOR=3 SAMBA_VERSION_MINOR=0 -SAMBA_VERSION_RELEASE=5 +SAMBA_VERSION_RELEASE=6 ######################################################## # For 'pre' releases the version will be # @@ -39,7 +39,7 @@ SAMBA_VERSION_PRE_RELEASE= # e.g. SAMBA_VERSION_RC_RELEASE=1 # # -> "3.0.0rc1" # ######################################################## -SAMBA_VERSION_RC_RELEASE=1 +SAMBA_VERSION_RC_RELEASE=2 ######################################################## # To mark SVN snapshots this should be set to 'yes' # diff --git a/source/auth/auth.c b/source/auth/auth.c index 1b49699fbca..7cfe3fc6394 100644 --- a/source/auth/auth.c +++ b/source/auth/auth.c @@ -124,7 +124,7 @@ static const uint8 *get_ntlm_challenge(struct auth_context *auth_context) if (!challenge_set_by) { uchar chal[8]; - generate_random_buffer(chal, sizeof(chal), False); + generate_random_buffer(chal, sizeof(chal)); auth_context->challenge = data_blob_talloc(auth_context->mem_ctx, chal, sizeof(chal)); diff --git a/source/auth/auth_sam.c b/source/auth/auth_sam.c index 2f9ff6265c9..44e0a1810fe 100644 --- a/source/auth/auth_sam.c +++ b/source/auth/auth_sam.c @@ -231,6 +231,8 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context, DEBUG(1, ("Failed to modify entry.\n")); unbecome_root(); } + data_blob_free(&user_sess_key); + data_blob_free(&lm_sess_key); pdb_free_sam(&sampass); return nt_status; } @@ -253,11 +255,15 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context, if (!NT_STATUS_IS_OK(nt_status)) { pdb_free_sam(&sampass); + data_blob_free(&user_sess_key); + data_blob_free(&lm_sess_key); return nt_status; } if (!NT_STATUS_IS_OK(nt_status = make_server_info_sam(server_info, sampass))) { DEBUG(0,("check_sam_security: make_server_info_sam() failed with '%s'\n", nt_errstr(nt_status))); + data_blob_free(&user_sess_key); + data_blob_free(&lm_sess_key); return nt_status; } diff --git a/source/configure.in b/source/configure.in index e57076a346a..4076f654ef8 100644 --- a/source/configure.in +++ b/source/configure.in @@ -643,7 +643,7 @@ AC_CHECK_HEADERS(sys/param.h ctype.h sys/wait.h sys/resource.h sys/ioctl.h sys/i AC_CHECK_HEADERS(sys/mman.h sys/filio.h sys/priv.h sys/shm.h string.h strings.h stdlib.h sys/socket.h) AC_CHECK_HEADERS(sys/mount.h sys/vfs.h sys/fs/s5param.h sys/filsys.h termios.h termio.h) AC_CHECK_HEADERS(sys/termio.h sys/statfs.h sys/dustat.h sys/statvfs.h stdarg.h sys/sockio.h) -AC_CHECK_HEADERS(security/pam_modules.h security/_pam_macros.h dlfcn.h) +AC_CHECK_HEADERS(sys/sysmacros.h security/pam_modules.h security/_pam_macros.h dlfcn.h) AC_CHECK_HEADERS(sys/syslog.h syslog.h execinfo.h) AC_CHECK_HEADERS(langinfo.h locale.h) @@ -1130,7 +1130,7 @@ if test "$enable_shared" = "yes"; then case "$host_os" in *linux*) AC_DEFINE(LINUX,1,[Whether the host os is linux]) BLDSHARED="true" - LDSHFLAGS="-shared" + LDSHFLAGS="-shared -Bsymbolic" DYNEXP="-Wl,--export-dynamic" PICFLAGS="-fPIC" SONAMEFLAG="-Wl,-soname=" @@ -1429,6 +1429,18 @@ if test x"$samba_cv_HAVE_DEVICE_MINOR_FN" = x"yes"; then AC_DEFINE(HAVE_DEVICE_MINOR_FN,1,[Whether the minor macro for dev_t is available]) fi +AC_CACHE_CHECK([for makedev macro],samba_cv_HAVE_MAKEDEV,[ +AC_TRY_RUN([ +#if defined(HAVE_UNISTD_H) +#include +#endif +#include +main() { dev_t dev = makedev(1,2); return 0; }], +samba_cv_HAVE_MAKEDEV=yes,samba_cv_HAVE_MAKEDEV=no,samba_cv_HAVE_MAKEDEV=cross)]) +if test x"$samba_cv_HAVE_MAKEDEV" = x"yes"; then + AC_DEFINE(HAVE_MAKEDEV,1,[Whether the macro for makedev is available]) +fi + AC_CACHE_CHECK([for unsigned char],samba_cv_HAVE_UNSIGNED_CHAR,[ AC_TRY_RUN([#include main() { char c; c=250; exit((c > 0)?0:1); }], @@ -1680,31 +1692,37 @@ AC_ARG_WITH(libiconv, fi ]) -ICONV_FOUND="no" -libext="" for i in $LOOK_DIRS ; do save_LIBS=$LIBS save_LDFLAGS=$LDFLAGS save_CPPFLAGS=$CPPFLAGS + ICONV_FOUND="no" + unset libext CPPFLAGS="$CPPFLAGS -I$i/include" dnl This is here to handle -withval stuff for --with-libiconv dnl Perhaps we should always add a -L dnl Check lib and lib32 library variants to cater for IRIX ABI-specific -dnl installation paths. - for l in "lib" "lib32" ; do - LDFLAGS="$LDFLAGS -L$i/$l" - LIBS= - export LDFLAGS LIBS CPPFLAGS +dnl installation paths. This gets a little tricky since we might have iconv +dnl in both libiconv and in libc. In this case the jm_ICONV test will always +dnl succeed when the header is found. To counter this, make sure the +dnl library directory is there and check the ABI directory first (which +dnl should be harmless on other systems. + for l in "lib32" "lib" ; do + if test -d "$i/$l" ; then + LDFLAGS="$save_LDFLAGS -L$i/$l" + LIBS= + export LDFLAGS LIBS CPPFLAGS dnl Try to find iconv(3) - jm_ICONV($i) - if test "$ICONV_FOUND" = yes; then - libext="$l" - break; + jm_ICONV($i/$l) + if test x"$ICONV_FOUND" = "xyes" ; then + libext="$l" + break; + fi fi done - if test "$ICONV_FOUND" = yes; then + if test x"$ICONV_FOUND" = "xyes" ; then LDFLAGS=$save_LDFLAGS LIB_ADD_DIR(LDFLAGS, "$i/$libext") CFLAGS_ADD_DIR(CPPFLAGS, "$i/include") @@ -1718,7 +1736,7 @@ dnl there might be a working iconv further down the list of LOOK_DIRS # check for iconv in libc ic_save_LIBS="$LIBS" if test x"$ICONV_PATH_SPEC" = "xyes" ; then - LIBS="$LIBS -L$ICONV_LOCATION/lib" + LIBS="$LIBS -L$ICONV_LOCATION/$libext" fi if test x"$jm_cv_lib_iconv" != x; then LIBS="$LIBS -l$jm_cv_lib_iconv" diff --git a/source/include/includes.h b/source/include/includes.h index 7657984bfb1..2664cad098f 100644 --- a/source/include/includes.h +++ b/source/include/includes.h @@ -1309,6 +1309,15 @@ void free_kerberos_etypes(krb5_context context, krb5_enctype *enctypes); BOOL get_krb5_smb_session_key(krb5_context context, krb5_auth_context auth_context, DATA_BLOB *session_key, BOOL remote); #endif /* HAVE_KRB5 */ + +#ifdef HAVE_LDAP + +/* function declarations not included in proto.h */ +LDAP *ldap_open_with_timeout(const char *server, int port, unsigned int to); + +#endif /* HAVE_LDAP */ + + /* TRUE and FALSE are part of the C99 standard and gcc, but unfortunately many vendor compilers don't support them. Use True and False instead. */ diff --git a/source/include/mangle.h b/source/include/mangle.h index 1d7cdf73628..08d511689dc 100644 --- a/source/include/mangle.h +++ b/source/include/mangle.h @@ -8,7 +8,7 @@ struct mangle_fns { BOOL (*is_mangled)(const char *s); BOOL (*is_8_3)(const char *fname, BOOL check_case, BOOL allow_wildcards); void (*reset)(void); - BOOL (*check_cache)(char *s); + BOOL (*check_cache)(char *s, size_t maxlen); void (*name_map)(char *OutName, BOOL need83, BOOL cache83, int default_case); }; #endif /* _MANGLE_H_ */ diff --git a/source/include/ntdomain.h b/source/include/ntdomain.h index 084e56b51e1..a63272fd18f 100644 --- a/source/include/ntdomain.h +++ b/source/include/ntdomain.h @@ -4,6 +4,7 @@ Copyright (C) Andrew Tridgell 1992-1997 Copyright (C) Luke Kenneth Casson Leighton 1996-1997 Copyright (C) Paul Ashton 1997 + Copyright (C) Jeremy Allison 200-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 @@ -23,19 +24,17 @@ #ifndef _NT_DOMAIN_H /* _NT_DOMAIN_H */ #define _NT_DOMAIN_H -struct uuid -{ - uint32 time_low; - uint16 time_mid; - uint16 time_hi_and_version; - uint8 clock_seq[2]; - uint8 node[6]; +struct uuid { + uint32 time_low; + uint16 time_mid; + uint16 time_hi_and_version; + uint8 clock_seq[2]; + uint8 node[6]; }; #define UUID_SIZE 16 #define UUID_FLAT_SIZE 16 -typedef struct uuid_flat -{ +typedef struct uuid_flat { uint8 info[UUID_FLAT_SIZE]; } UUID_FLAT; @@ -54,8 +53,7 @@ typedef struct uuid_flat * in the NTDOM branch - it didn't belong there. */ -typedef struct _prs_struct -{ +typedef struct _prs_struct { BOOL io; /* parsing in or out of data stream */ /* * If the (incoming) data is big-endian. On output we are @@ -109,49 +107,47 @@ typedef struct _output_data { } output_data; typedef struct _input_data { - /* - * This is the current incoming pdu. The data here - * is collected via multiple writes until a complete - * pdu is seen, then the data is copied into the in_data - * structure. The maximum size of this is 0x1630 (MAX_PDU_FRAG_LEN). - */ - unsigned char current_in_pdu[MAX_PDU_FRAG_LEN]; - - /* - * The amount of data needed to complete the in_pdu. - * If this is zero, then we are at the start of a new - * pdu. - */ - uint32 pdu_needed_len; - - /* - * The amount of data received so far in the in_pdu. - * If this is zero, then we are at the start of a new - * pdu. - */ - uint32 pdu_received_len; - - /* - * This is the collection of input data with all - * the rpc headers and auth footers removed. - * The maximum length of this (1Mb) is strictly enforced. - */ - prs_struct data; + /* + * This is the current incoming pdu. The data here + * is collected via multiple writes until a complete + * pdu is seen, then the data is copied into the in_data + * structure. The maximum size of this is 0x1630 (MAX_PDU_FRAG_LEN). + */ + unsigned char current_in_pdu[MAX_PDU_FRAG_LEN]; + + /* + * The amount of data needed to complete the in_pdu. + * If this is zero, then we are at the start of a new + * pdu. + */ + uint32 pdu_needed_len; + + /* + * The amount of data received so far in the in_pdu. + * If this is zero, then we are at the start of a new + * pdu. + */ + uint32 pdu_received_len; + + /* + * This is the collection of input data with all + * the rpc headers and auth footers removed. + * The maximum length of this (1Mb) is strictly enforced. + */ + prs_struct data; } input_data; /* * Handle database - stored per pipe. */ -struct policy -{ - struct policy *next, *prev; +struct policy { + struct policy *next, *prev; - POLICY_HND pol_hnd; - - void *data_ptr; - void (*free_fn)(void *); + POLICY_HND pol_hnd; + void *data_ptr; + void (*free_fn)(void *); }; struct handle_list { @@ -161,8 +157,7 @@ struct handle_list { }; /* Domain controller authentication protocol info */ -struct dcinfo -{ +struct dcinfo { DOM_CHAL clnt_chal; /* Initial challenge received from client */ DOM_CHAL srv_chal; /* Initial server challenge */ DOM_CRED clnt_cred; /* Last client credential */ @@ -198,8 +193,7 @@ typedef struct pipe_rpc_fns { * NamedPipes. */ -typedef struct pipes_struct -{ +typedef struct pipes_struct { struct pipes_struct *next, *prev; connection_struct *conn; @@ -291,8 +285,7 @@ typedef struct pipes_struct } pipes_struct; -typedef struct smb_np_struct -{ +typedef struct smb_np_struct { struct smb_np_struct *next, *prev; int pnum; connection_struct *conn; @@ -368,18 +361,15 @@ typedef struct smb_np_struct } smb_np_struct; -struct api_struct -{ - const char *name; - uint8 opnum; - BOOL (*fn) (pipes_struct *); +struct api_struct { + const char *name; + uint8 opnum; + BOOL (*fn) (pipes_struct *); }; -typedef struct -{ +typedef struct { uint32 rid; const char *name; - } rid_name; /* diff --git a/source/include/passdb.h b/source/include/passdb.h index d08fd13a723..7d3e0014b65 100644 --- a/source/include/passdb.h +++ b/source/include/passdb.h @@ -99,6 +99,7 @@ enum pdb_elements { PDB_UNKNOWN6, PDB_LMPASSWD, PDB_NTPASSWD, + PDB_PWHISTORY, PDB_BACKEND_PRIVATE_DATA, /* this must be the last element */ @@ -165,16 +166,17 @@ typedef struct sam_passwd const char * dir_drive; /* home directory drive string */ const char * logon_script; /* logon script string */ const char * profile_path; /* profile path string */ - const char * acct_desc ; /* user description string */ + const char * acct_desc; /* user description string */ const char * workstations; /* login from workstations string */ - const char * unknown_str ; /* don't know what this is, yet. */ - const char * munged_dial ; /* munged path name and dial-back tel number */ + const char * unknown_str; /* don't know what this is, yet. */ + const char * munged_dial; /* munged path name and dial-back tel number */ DOM_SID user_sid; /* Primary User SID */ DOM_SID group_sid; /* Primary Group SID */ DATA_BLOB lm_pw; /* .data is Null if no password */ DATA_BLOB nt_pw; /* .data is Null if no password */ + DATA_BLOB nt_pw_his; /* nt hashed password history .data is Null if not available */ char* plaintext_pw; /* is Null if not available */ uint16 acct_ctrl; /* account info (ACB_xxxx bit-mask) */ diff --git a/source/include/smbldap.h b/source/include/smbldap.h index c7de7d84b37..6046af464e6 100644 --- a/source/include/smbldap.h +++ b/source/include/smbldap.h @@ -93,8 +93,9 @@ #define LDAP_ATTR_LOGON_COUNT 36 #define LDAP_ATTR_MUNGED_DIAL 37 #define LDAP_ATTR_BAD_PASSWORD_TIME 38 - -#define LDAP_ATTR_SID_LIST 40 +#define LDAP_ATTR_PWD_HISTORY 39 +#define LDAP_ATTR_SID_LIST 40 +#define LDAP_ATTR_MOD_TIMESTAMP 41 typedef struct _attrib_map_entry { int attrib; @@ -153,6 +154,6 @@ struct smbldap_state { struct smbldap_state; -#define LDAP_CONNECT_DEFAULT_TIMEOUT 5 +#define LDAP_CONNECT_DEFAULT_TIMEOUT 15 #endif /* _SMBLDAP_H */ diff --git a/source/lib/account_pol.c b/source/lib/account_pol.c index c2c63493a6f..8d5b963da28 100644 --- a/source/lib/account_pol.c +++ b/source/lib/account_pol.c @@ -81,6 +81,30 @@ static const struct { {0, NULL} }; +char *account_policy_names_list(void) +{ + char *nl, *p; + int i; + size_t len = 0; + + for (i=0; account_policy_names[i].string; i++) { + len += strlen(account_policy_names[i].string) + 1; + } + len++; + nl = malloc(len); + if (!nl) { + return NULL; + } + p = nl; + for (i=0; account_policy_names[i].string; i++) { + memcpy(p, account_policy_names[i].string, strlen(account_policy_names[i].string) + 1); + p[strlen(account_policy_names[i].string)] = '\n'; + p += strlen(account_policy_names[i].string) + 1; + } + *p = '\0'; + return nl; +} + /**************************************************************************** Get the account policy name as a string from its #define'ed number ****************************************************************************/ @@ -111,9 +135,9 @@ int account_policy_name_to_fieldnum(const char *name) } - /**************************************************************************** ****************************************************************************/ + BOOL account_policy_get(int field, uint32 *value) { fstring name; @@ -159,4 +183,3 @@ BOOL account_policy_set(int field, uint32 value) return True; } - diff --git a/source/lib/afs.c b/source/lib/afs.c index 0830a3a0e7f..8688fde6b1c 100644 --- a/source/lib/afs.c +++ b/source/lib/afs.c @@ -116,7 +116,7 @@ static BOOL afs_createtoken(const char *username, const char *cell, p += 4; /* We need to create a session key */ - generate_random_buffer(p, 8, False); + generate_random_buffer(p, 8); /* Our client code needs the the key in the clear, it does not know the server-key ... */ diff --git a/source/lib/debug.c b/source/lib/debug.c index f9c8b0c46ab..e5e203e076a 100644 --- a/source/lib/debug.c +++ b/source/lib/debug.c @@ -239,8 +239,9 @@ done: } /**************************************************************************** -utility access to debug class names's + Utility access to debug class names's. ****************************************************************************/ + const char *debug_classname_from_index(int ndx) { if (ndx < 0 || ndx >= debug_num_classes) @@ -250,8 +251,9 @@ const char *debug_classname_from_index(int ndx) } /**************************************************************************** -utility to translate names to debug class index's (internal version) + Utility to translate names to debug class index's (internal version). ****************************************************************************/ + static int debug_lookup_classname_int(const char* classname) { int i; @@ -266,8 +268,9 @@ static int debug_lookup_classname_int(const char* classname) } /**************************************************************************** -Add a new debug class to the system + Add a new debug class to the system. ****************************************************************************/ + int debug_add_class(const char *classname) { int ndx; @@ -285,33 +288,28 @@ int debug_add_class(const char *classname) ndx = debug_num_classes; new_ptr = DEBUGLEVEL_CLASS; - if (DEBUGLEVEL_CLASS == &debug_all_class_hack) - { + if (DEBUGLEVEL_CLASS == &debug_all_class_hack) { /* Initial loading... */ new_ptr = NULL; } - new_ptr = Realloc(new_ptr, - sizeof(int) * (debug_num_classes + 1)); + new_ptr = Realloc(new_ptr, sizeof(int) * (debug_num_classes + 1)); if (!new_ptr) return -1; DEBUGLEVEL_CLASS = new_ptr; DEBUGLEVEL_CLASS[ndx] = 0; /* debug_level is the pointer used for the DEBUGLEVEL-thingy */ - if (ndx==0) - { + if (ndx==0) { /* Transfer the initial level from debug_all_class_hack */ DEBUGLEVEL_CLASS[ndx] = DEBUGLEVEL; } debug_level = DEBUGLEVEL_CLASS; new_ptr = DEBUGLEVEL_CLASS_ISSET; - if (new_ptr == &debug_all_class_isset_hack) - { + if (new_ptr == &debug_all_class_isset_hack) { new_ptr = NULL; } - new_ptr = Realloc(new_ptr, - sizeof(BOOL) * (debug_num_classes + 1)); + new_ptr = Realloc(new_ptr, sizeof(BOOL) * (debug_num_classes + 1)); if (!new_ptr) return -1; DEBUGLEVEL_CLASS_ISSET = new_ptr; @@ -333,42 +331,41 @@ int debug_add_class(const char *classname) } /**************************************************************************** -utility to translate names to debug class index's (public version) + Utility to translate names to debug class index's (public version). ****************************************************************************/ + int debug_lookup_classname(const char *classname) { int ndx; - if (!classname || !*classname) return -1; + if (!classname || !*classname) + return -1; ndx = debug_lookup_classname_int(classname); if (ndx != -1) return ndx; - if (debug_warn_unknown_class) - { + if (debug_warn_unknown_class) { DEBUG(0, ("debug_lookup_classname(%s): Unknown class\n", classname)); } - if (debug_auto_add_unknown_class) - { + if (debug_auto_add_unknown_class) { return debug_add_class(classname); } return -1; } - /**************************************************************************** -dump the current registered debug levels + Dump the current registered debug levels. ****************************************************************************/ + static void debug_dump_status(int level) { int q; DEBUG(level, ("INFO: Current debug levels:\n")); - for (q = 0; q < debug_num_classes; q++) - { + for (q = 0; q < debug_num_classes; q++) { DEBUGADD(level, (" %s: %s/%d\n", classname_table[q], (DEBUGLEVEL_CLASS_ISSET[q] @@ -378,9 +375,10 @@ static void debug_dump_status(int level) } /**************************************************************************** -parse the debug levels from smbcontrol. Example debug level parameter: - printdrivers:7 + parse the debug levels from smbcontrol. Example debug level parameter: + printdrivers:7 ****************************************************************************/ + static BOOL debug_parse_params(char **params) { int i, ndx; @@ -397,9 +395,9 @@ static BOOL debug_parse_params(char **params) DEBUGLEVEL_CLASS[DBGC_ALL] = atoi(params[0]); DEBUGLEVEL_CLASS_ISSET[DBGC_ALL] = True; i = 1; /* start processing at the next params */ - } - else + } else { i = 0; /* DBGC_ALL not specified OR class name was included */ + } /* Fill in new debug class levels */ for (; i < debug_num_classes && params[i]; i++) { @@ -418,10 +416,11 @@ static BOOL debug_parse_params(char **params) } /**************************************************************************** -parse the debug levels from smb.conf. Example debug level string: + Parse the debug levels from smb.conf. Example debug level string: 3 tdb:5 printdrivers:7 -Note: the 1st param has no "name:" preceeding it. + Note: the 1st param has no "name:" preceeding it. ****************************************************************************/ + BOOL debug_parse_levels(const char *params_str) { char **params; @@ -434,8 +433,7 @@ BOOL debug_parse_levels(const char *params_str) params = str_list_make(params_str, NULL); - if (debug_parse_params(params)) - { + if (debug_parse_params(params)) { debug_dump_status(5); str_list_free(¶ms); return True; @@ -446,15 +444,15 @@ BOOL debug_parse_levels(const char *params_str) } /**************************************************************************** -receive a "set debug level" message + Receive a "set debug level" message. ****************************************************************************/ + static void debug_message(int msg_type, pid_t src, void *buf, size_t len) { const char *params_str = buf; /* Check, it's a proper string! */ - if (params_str[len-1] != '\0') - { + if (params_str[len-1] != '\0') { DEBUG(1, ("Invalid debug message from pid %u to pid %u\n", (unsigned int)src, (unsigned int)getpid())); return; @@ -466,10 +464,10 @@ static void debug_message(int msg_type, pid_t src, void *buf, size_t len) debug_parse_levels(params_str); } - /**************************************************************************** -send a "set debug level" message + Send a "set debug level" message. ****************************************************************************/ + void debug_message_send(pid_t pid, const char *params_str) { if (!params_str) @@ -495,6 +493,7 @@ static void debuglevel_message(int msg_type, pid_t src, void *buf, size_t len) /**************************************************************************** Init debugging (one time stuff) ****************************************************************************/ + void debug_init(void) { static BOOL initialised = False; @@ -508,17 +507,15 @@ void debug_init(void) message_register(MSG_DEBUG, debug_message); message_register(MSG_REQ_DEBUGLEVEL, debuglevel_message); - for(p = default_classname_table; *p; p++) - { + for(p = default_classname_table; *p; p++) { debug_add_class(*p); } } +/*************************************************************************** + Get ready for syslog stuff +**************************************************************************/ -/* ************************************************************************** ** - * get ready for syslog stuff - * ************************************************************************** ** - */ void setup_logging(const char *pname, BOOL interactive) { debug_init(); @@ -526,6 +523,11 @@ void setup_logging(const char *pname, BOOL interactive) /* reset to allow multiple setup calls, going from interactive to non-interactive */ stdout_logging = False; + if (dbf) { + x_fflush(dbf); + (void) x_fclose(dbf); + } + dbf = NULL; if (interactive) { @@ -546,16 +548,15 @@ void setup_logging(const char *pname, BOOL interactive) #endif } #endif -} /* setup_logging */ - -/* ************************************************************************** ** - * reopen the log files - * note that we now do this unconditionally - * We attempt to open the new debug fp before closing the old. This means - * if we run out of fd's we just keep using the old fd rather than aborting. - * Fix from dgibson@linuxcare.com. - * ************************************************************************** ** - */ +} + +/************************************************************************** + reopen the log files + note that we now do this unconditionally + We attempt to open the new debug fp before closing the old. This means + if we run out of fd's we just keep using the old fd rather than aborting. + Fix from dgibson@linuxcare.com. +**************************************************************************/ BOOL reopen_logs( void ) { @@ -614,13 +615,13 @@ BOOL reopen_logs( void ) return ret; } -/* ************************************************************************** ** - * Force a check of the log size. - * ************************************************************************** ** - */ +/************************************************************************** + Force a check of the log size. + ***************************************************************************/ + void force_check_log_size( void ) { - debug_count = 100; + debug_count = 100; } /*************************************************************************** @@ -642,10 +643,9 @@ BOOL need_to_check_log_size( void ) return( True ); } -/* ************************************************************************** ** - * Check to see if the log has grown to be too big. - * ************************************************************************** ** - */ +/************************************************************************** + Check to see if the log has grown to be too big. + **************************************************************************/ void check_log_size( void ) { @@ -704,293 +704,273 @@ void check_log_size( void ) } } debug_count = 0; -} /* check_log_size */ +} + +/************************************************************************* + Write an debug message on the debugfile. + This is called by dbghdr() and format_debug_text(). +************************************************************************/ -/* ************************************************************************** ** - * Write an debug message on the debugfile. - * This is called by dbghdr() and format_debug_text(). - * ************************************************************************** ** - */ int Debug1( const char *format_str, ... ) { - va_list ap; - int old_errno = errno; - - debug_count++; - - if( stdout_logging ) - { - va_start( ap, format_str ); - if(dbf) - (void)x_vfprintf( dbf, format_str, ap ); - va_end( ap ); - errno = old_errno; - return( 0 ); - } + va_list ap; + int old_errno = errno; + + debug_count++; + + if( stdout_logging ) { + va_start( ap, format_str ); + if(dbf) + (void)x_vfprintf( dbf, format_str, ap ); + va_end( ap ); + errno = old_errno; + return( 0 ); + } #ifdef WITH_SYSLOG - if( !lp_syslog_only() ) + if( !lp_syslog_only() ) #endif - { - if( !dbf ) - { - mode_t oldumask = umask( 022 ); - - dbf = x_fopen( debugf, O_WRONLY|O_APPEND|O_CREAT, 0644 ); - (void)umask( oldumask ); - if( dbf ) - { - x_setbuf( dbf, NULL ); - } - else - { - errno = old_errno; - return(0); - } - } - } + { + if( !dbf ) { + mode_t oldumask = umask( 022 ); + + dbf = x_fopen( debugf, O_WRONLY|O_APPEND|O_CREAT, 0644 ); + (void)umask( oldumask ); + if( dbf ) { + x_setbuf( dbf, NULL ); + } else { + errno = old_errno; + return(0); + } + } + } #ifdef WITH_SYSLOG - if( syslog_level < lp_syslog() ) - { - /* map debug levels to syslog() priorities - * note that not all DEBUG(0, ...) calls are - * necessarily errors - */ - static int priority_map[] = { - LOG_ERR, /* 0 */ - LOG_WARNING, /* 1 */ - LOG_NOTICE, /* 2 */ - LOG_INFO, /* 3 */ - }; - int priority; - pstring msgbuf; - - if( syslog_level >= ( sizeof(priority_map) / sizeof(priority_map[0]) ) - || syslog_level < 0) - priority = LOG_DEBUG; - else - priority = priority_map[syslog_level]; - - va_start( ap, format_str ); - vslprintf( msgbuf, sizeof(msgbuf)-1, format_str, ap ); - va_end( ap ); - - msgbuf[255] = '\0'; - syslog( priority, "%s", msgbuf ); - } + if( syslog_level < lp_syslog() ) { + /* map debug levels to syslog() priorities + * note that not all DEBUG(0, ...) calls are + * necessarily errors */ + static int priority_map[] = { + LOG_ERR, /* 0 */ + LOG_WARNING, /* 1 */ + LOG_NOTICE, /* 2 */ + LOG_INFO, /* 3 */ + }; + int priority; + pstring msgbuf; + + if( syslog_level >= ( sizeof(priority_map) / sizeof(priority_map[0]) ) || syslog_level < 0) + priority = LOG_DEBUG; + else + priority = priority_map[syslog_level]; + + va_start( ap, format_str ); + vslprintf( msgbuf, sizeof(msgbuf)-1, format_str, ap ); + va_end( ap ); + + msgbuf[255] = '\0'; + syslog( priority, "%s", msgbuf ); + } #endif - check_log_size(); + check_log_size(); #ifdef WITH_SYSLOG - if( !lp_syslog_only() ) + if( !lp_syslog_only() ) #endif - { - va_start( ap, format_str ); - if(dbf) - (void)x_vfprintf( dbf, format_str, ap ); - va_end( ap ); - if(dbf) - (void)x_fflush( dbf ); - } + { + va_start( ap, format_str ); + if(dbf) + (void)x_vfprintf( dbf, format_str, ap ); + va_end( ap ); + if(dbf) + (void)x_fflush( dbf ); + } - errno = old_errno; + errno = old_errno; - return( 0 ); - } /* Debug1 */ + return( 0 ); +} -/* ************************************************************************** ** - * Print the buffer content via Debug1(), then reset the buffer. - * - * Input: none - * Output: none - * - * ************************************************************************** ** - */ +/************************************************************************** + Print the buffer content via Debug1(), then reset the buffer. + Input: none + Output: none +****************************************************************************/ + static void bufr_print( void ) - { - format_bufr[format_pos] = '\0'; - (void)Debug1( "%s", format_bufr ); - format_pos = 0; - } /* bufr_print */ - -/* ************************************************************************** ** - * Format the debug message text. - * - * Input: msg - Text to be added to the "current" debug message text. - * - * Output: none. - * - * Notes: The purpose of this is two-fold. First, each call to syslog() - * (used by Debug1(), see above) generates a new line of syslog - * output. This is fixed by storing the partial lines until the - * newline character is encountered. Second, printing the debug - * message lines when a newline is encountered allows us to add - * spaces, thus indenting the body of the message and making it - * more readable. - * - * ************************************************************************** ** - */ -static void format_debug_text( char *msg ) - { - size_t i; - BOOL timestamp = (!stdout_logging && (lp_timestamp_logs() || - !(lp_loaded()))); - - for( i = 0; msg[i]; i++ ) - { - /* Indent two spaces at each new line. */ - if(timestamp && 0 == format_pos) - { - format_bufr[0] = format_bufr[1] = ' '; - format_pos = 2; - } - - /* If there's room, copy the character to the format buffer. */ - if( format_pos < FORMAT_BUFR_MAX ) - format_bufr[format_pos++] = msg[i]; - - /* If a newline is encountered, print & restart. */ - if( '\n' == msg[i] ) - bufr_print(); - - /* If the buffer is full dump it out, reset it, and put out a line - * continuation indicator. - */ - if( format_pos >= FORMAT_BUFR_MAX ) - { - bufr_print(); - (void)Debug1( " +>\n" ); - } - } - - /* Just to be safe... */ - format_bufr[format_pos] = '\0'; - } /* format_debug_text */ - -/* ************************************************************************** ** - * Flush debug output, including the format buffer content. - * - * Input: none - * Output: none - * - * ************************************************************************** ** - */ +{ + format_bufr[format_pos] = '\0'; + (void)Debug1( "%s", format_bufr ); + format_pos = 0; +} + +/*************************************************************************** + Format the debug message text. + + Input: msg - Text to be added to the "current" debug message text. + + Output: none. + + Notes: The purpose of this is two-fold. First, each call to syslog() + (used by Debug1(), see above) generates a new line of syslog + output. This is fixed by storing the partial lines until the + newline character is encountered. Second, printing the debug + message lines when a newline is encountered allows us to add + spaces, thus indenting the body of the message and making it + more readable. +**************************************************************************/ + +static void format_debug_text( const char *msg ) +{ + size_t i; + BOOL timestamp = (!stdout_logging && (lp_timestamp_logs() || !(lp_loaded()))); + + for( i = 0; msg[i]; i++ ) { + /* Indent two spaces at each new line. */ + if(timestamp && 0 == format_pos) { + format_bufr[0] = format_bufr[1] = ' '; + format_pos = 2; + } + + /* If there's room, copy the character to the format buffer. */ + if( format_pos < FORMAT_BUFR_MAX ) + format_bufr[format_pos++] = msg[i]; + + /* If a newline is encountered, print & restart. */ + if( '\n' == msg[i] ) + bufr_print(); + + /* If the buffer is full dump it out, reset it, and put out a line + * continuation indicator. + */ + if( format_pos >= FORMAT_BUFR_MAX ) { + bufr_print(); + (void)Debug1( " +>\n" ); + } + } + + /* Just to be safe... */ + format_bufr[format_pos] = '\0'; +} + +/*************************************************************************** + Flush debug output, including the format buffer content. + + Input: none + Output: none +***************************************************************************/ + void dbgflush( void ) - { - bufr_print(); - if(dbf) - (void)x_fflush( dbf ); - } /* dbgflush */ - -/* ************************************************************************** ** - * Print a Debug Header. - * - * Input: level - Debug level of the message (not the system-wide debug - * level. ) - * file - Pointer to a string containing the name of the file - * from which this function was called, or an empty string - * if the __FILE__ macro is not implemented. - * func - Pointer to a string containing the name of the function - * from which this function was called, or an empty string - * if the __FUNCTION__ macro is not implemented. - * line - line number of the call to dbghdr, assuming __LINE__ - * works. - * - * Output: Always True. This makes it easy to fudge a call to dbghdr() - * in a macro, since the function can be called as part of a test. - * Eg: ( (level <= DEBUGLEVEL) && (dbghdr(level,"",line)) ) - * - * Notes: This function takes care of setting syslog_level. - * - * ************************************************************************** ** - */ +{ + bufr_print(); + if(dbf) + (void)x_fflush( dbf ); +} + +/*************************************************************************** + Print a Debug Header. + + Input: level - Debug level of the message (not the system-wide debug + level. ) + file - Pointer to a string containing the name of the file + from which this function was called, or an empty string + if the __FILE__ macro is not implemented. + func - Pointer to a string containing the name of the function + from which this function was called, or an empty string + if the __FUNCTION__ macro is not implemented. + line - line number of the call to dbghdr, assuming __LINE__ + works. + + Output: Always True. This makes it easy to fudge a call to dbghdr() + in a macro, since the function can be called as part of a test. + Eg: ( (level <= DEBUGLEVEL) && (dbghdr(level,"",line)) ) + + Notes: This function takes care of setting syslog_level. + +****************************************************************************/ BOOL dbghdr( int level, const char *file, const char *func, int line ) { - /* Ensure we don't lose any real errno value. */ - int old_errno = errno; - - if( format_pos ) { - /* This is a fudge. If there is stuff sitting in the format_bufr, then - * the *right* thing to do is to call - * format_debug_text( "\n" ); - * to write the remainder, and then proceed with the new header. - * Unfortunately, there are several places in the code at which - * the DEBUG() macro is used to build partial lines. That in mind, - * we'll work under the assumption that an incomplete line indicates - * that a new header is *not* desired. - */ - return( True ); - } + /* Ensure we don't lose any real errno value. */ + int old_errno = errno; + + if( format_pos ) { + /* This is a fudge. If there is stuff sitting in the format_bufr, then + * the *right* thing to do is to call + * format_debug_text( "\n" ); + * to write the remainder, and then proceed with the new header. + * Unfortunately, there are several places in the code at which + * the DEBUG() macro is used to build partial lines. That in mind, + * we'll work under the assumption that an incomplete line indicates + * that a new header is *not* desired. + */ + return( True ); + } #ifdef WITH_SYSLOG - /* Set syslog_level. */ - syslog_level = level; + /* Set syslog_level. */ + syslog_level = level; #endif - /* Don't print a header if we're logging to stdout. */ - if( stdout_logging ) - return( True ); + /* Don't print a header if we're logging to stdout. */ + if( stdout_logging ) + return( True ); - /* Print the header if timestamps are turned on. If parameters are - * not yet loaded, then default to timestamps on. - */ - if( lp_timestamp_logs() || !(lp_loaded()) ) { - char header_str[200]; + /* Print the header if timestamps are turned on. If parameters are + * not yet loaded, then default to timestamps on. + */ + if( lp_timestamp_logs() || !(lp_loaded()) ) { + char header_str[200]; - header_str[0] = '\0'; + header_str[0] = '\0'; - if( lp_debug_pid()) - slprintf(header_str,sizeof(header_str)-1,", pid=%u",(unsigned int)sys_getpid()); + if( lp_debug_pid()) + slprintf(header_str,sizeof(header_str)-1,", pid=%u",(unsigned int)sys_getpid()); - if( lp_debug_uid()) { - size_t hs_len = strlen(header_str); - slprintf(header_str + hs_len, - sizeof(header_str) - 1 - hs_len, - ", effective(%u, %u), real(%u, %u)", - (unsigned int)geteuid(), (unsigned int)getegid(), - (unsigned int)getuid(), (unsigned int)getgid()); - } + if( lp_debug_uid()) { + size_t hs_len = strlen(header_str); + slprintf(header_str + hs_len, + sizeof(header_str) - 1 - hs_len, + ", effective(%u, %u), real(%u, %u)", + (unsigned int)geteuid(), (unsigned int)getegid(), + (unsigned int)getuid(), (unsigned int)getgid()); + } - /* Print it all out at once to prevent split syslog output. */ - (void)Debug1( "[%s, %d%s] %s:%s(%d)\n", - timestring(lp_debug_hires_timestamp()), level, - header_str, file, func, line ); - } + /* Print it all out at once to prevent split syslog output. */ + (void)Debug1( "[%s, %d%s] %s:%s(%d)\n", + timestring(lp_debug_hires_timestamp()), level, + header_str, file, func, line ); + } - errno = old_errno; - return( True ); + errno = old_errno; + return( True ); } -/* ************************************************************************** ** - * Add text to the body of the "current" debug message via the format buffer. - * - * Input: format_str - Format string, as used in printf(), et. al. - * ... - Variable argument list. - * - * ..or.. va_alist - Old style variable parameter list starting point. - * - * Output: Always True. See dbghdr() for more info, though this is not - * likely to be used in the same way. - * - * ************************************************************************** ** - */ - BOOL dbgtext( const char *format_str, ... ) - { - va_list ap; - pstring msgbuf; +/*************************************************************************** + Add text to the body of the "current" debug message via the format buffer. - va_start( ap, format_str ); - vslprintf( msgbuf, sizeof(msgbuf)-1, format_str, ap ); - va_end( ap ); + Input: format_str - Format string, as used in printf(), et. al. + ... - Variable argument list. - format_debug_text( msgbuf ); + ..or.. va_alist - Old style variable parameter list starting point. - return( True ); - } /* dbgtext */ + Output: Always True. See dbghdr() for more info, though this is not + likely to be used in the same way. +***************************************************************************/ -/* ************************************************************************** */ + BOOL dbgtext( const char *format_str, ... ) +{ + va_list ap; + pstring msgbuf; + + va_start( ap, format_str ); + vslprintf( msgbuf, sizeof(msgbuf)-1, format_str, ap ); + va_end( ap ); + + format_debug_text( msgbuf ); + + return( True ); +} diff --git a/source/lib/fsusage.c b/source/lib/fsusage.c index bb7cff06453..036f276319f 100644 --- a/source/lib/fsusage.c +++ b/source/lib/fsusage.c @@ -26,12 +26,17 @@ */ static SMB_BIG_UINT adjust_blocks(SMB_BIG_UINT blocks, SMB_BIG_UINT fromsize, SMB_BIG_UINT tosize) { - if (fromsize == tosize) /* e.g., from 512 to 512 */ + if (fromsize == tosize) { /* e.g., from 512 to 512 */ return blocks; - else if (fromsize > tosize) /* e.g., from 2048 to 512 */ + } else if (fromsize > tosize) { /* e.g., from 2048 to 512 */ return blocks * (fromsize / tosize); - else /* e.g., from 256 to 512 */ + } else { /* e.g., from 256 to 512 */ + /* Protect against broken filesystems... */ + if (fromsize == 0) { + fromsize = tosize; + } return (blocks + 1) / (tosize / fromsize); + } } /* this does all of the system specific guff to get the free disk space. diff --git a/source/lib/genrand.c b/source/lib/genrand.c index bc9f21c6403..9ccddfa4c53 100644 --- a/source/lib/genrand.c +++ b/source/lib/genrand.c @@ -24,21 +24,32 @@ static unsigned char hash[258]; static uint32 counter; -static unsigned char *reseed_data; -static size_t reseed_data_size; + +static BOOL done_reseed = False; +static void (*reseed_callback)(int *newseed); /**************************************************************** Copy any user given reseed data. *****************************************************************/ -void set_rand_reseed_data(unsigned char *data, size_t len) +void set_rand_reseed_callback(void (*fn)(int *)) { - SAFE_FREE(reseed_data); - reseed_data_size = 0; + reseed_callback = fn; + set_need_random_reseed(); +} - reseed_data = (unsigned char *)memdup(data, len); - if (reseed_data) - reseed_data_size = len; +void set_need_random_reseed(void) +{ + done_reseed = False; +} + +static void get_rand_reseed_data(int *reseed_data) +{ + if (reseed_callback) { + reseed_callback(reseed_data); + } else { + *reseed_data = 0; + } } /**************************************************************** @@ -136,6 +147,7 @@ static int do_reseed(BOOL use_fd, int fd) unsigned char seed_inbuf[40]; uint32 v1, v2; struct timeval tval; pid_t mypid; struct passwd *pw; + int reseed_data = 0; if (use_fd) { if (fd != -1) @@ -183,10 +195,11 @@ static int do_reseed(BOOL use_fd, int fd) * Add any user-given reseed data. */ + get_rand_reseed_data(&reseed_data); if (reseed_data) { size_t i; for (i = 0; i < sizeof(seed_inbuf); i++) - seed_inbuf[i] ^= reseed_data[i % reseed_data_size]; + seed_inbuf[i] ^= ((char *)(&reseed_data))[i % sizeof(reseed_data)]; } seed_random_stream(seed_inbuf, sizeof(seed_inbuf)); @@ -198,15 +211,14 @@ static int do_reseed(BOOL use_fd, int fd) Interface to the (hopefully) good crypto random number generator. ********************************************************************/ -void generate_random_buffer( unsigned char *out, int len, BOOL do_reseed_now) +void generate_random_buffer( unsigned char *out, int len) { - static BOOL done_reseed = False; static int urand_fd = -1; unsigned char md4_buf[64]; unsigned char tmp_buf[16]; unsigned char *p; - if(!done_reseed || do_reseed_now) { + if(!done_reseed) { urand_fd = do_reseed(True, urand_fd); done_reseed = True; } @@ -257,7 +269,7 @@ char *generate_random_str(size_t len) if (len > sizeof(retstr)-1) len = sizeof(retstr) -1; - generate_random_buffer( retstr, len, False); + generate_random_buffer( retstr, len); for (i = 0; i < len; i++) retstr[i] = c_list[ retstr[i] % (sizeof(c_list)-1) ]; diff --git a/source/lib/smbldap.c b/source/lib/smbldap.c index f07187c68a0..0980b763adb 100644 --- a/source/lib/smbldap.c +++ b/source/lib/smbldap.c @@ -100,6 +100,8 @@ ATTRIB_MAP_ENTRY attrib_map_v30[] = { { LDAP_ATTR_MUNGED_DIAL, "sambaMungedDial" }, { LDAP_ATTR_BAD_PASSWORD_COUNT, "sambaBadPasswordCount" }, { LDAP_ATTR_BAD_PASSWORD_TIME, "sambaBadPasswordTime" }, + { LDAP_ATTR_PWD_HISTORY, "sambaPasswordHistory" }, + { LDAP_ATTR_MOD_TIMESTAMP, "modifyTimestamp" }, { LDAP_ATTR_LIST_END, NULL } }; @@ -345,19 +347,19 @@ static BOOL fetch_ldap_pw(char **dn, char** pw) /* sanity checks on the mod values */ - if (attribute == NULL || *attribute == '\0') + if (attribute == NULL || *attribute == '\0') { return; + } + #if 0 /* commented out after discussion with abartlet. Do not reenable. left here so other so re-add similar code --jerry */ if (value == NULL || *value == '\0') return; #endif - if (mods == NULL) - { + if (mods == NULL) { mods = (LDAPMod **) malloc(sizeof(LDAPMod *)); - if (mods == NULL) - { + if (mods == NULL) { DEBUG(0, ("make_a_mod: out of memory!\n")); return; } @@ -369,17 +371,14 @@ static BOOL fetch_ldap_pw(char **dn, char** pw) break; } - if (mods[i] == NULL) - { + if (mods[i] == NULL) { mods = (LDAPMod **) Realloc (mods, (i + 2) * sizeof (LDAPMod *)); - if (mods == NULL) - { + if (mods == NULL) { DEBUG(0, ("make_a_mod: out of memory!\n")); return; } mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod)); - if (mods[i] == NULL) - { + if (mods[i] == NULL) { DEBUG(0, ("make_a_mod: out of memory!\n")); return; } @@ -389,8 +388,7 @@ static BOOL fetch_ldap_pw(char **dn, char** pw) mods[i + 1] = NULL; } - if (value != NULL) - { + if (value != NULL) { char *utf8_value = NULL; j = 0; @@ -881,37 +879,69 @@ static NTSTATUS smbldap_close(struct smbldap_state *ldap_state) return NT_STATUS_OK; } -int smbldap_retry_open(struct smbldap_state *ldap_state, int *attempts) +static BOOL got_alarm; + +static void (*old_handler)(int); + +static void gotalarm_sig(int dummy) { - int rc; + got_alarm = True; +} - SMB_ASSERT(ldap_state && attempts); - - if (*attempts != 0) { - unsigned int sleep_time; - uint8 rand_byte; - - /* Sleep for a random timeout */ - rand_byte = (char)(sys_random()); - - sleep_time = (((*attempts)*(*attempts))/2)*rand_byte*2; - /* we retry after (0.5, 1, 2, 3, 4.5, 6) seconds - on average. - */ - DEBUG(3, ("Sleeping for %u milliseconds before reconnecting\n", - sleep_time)); - smb_msleep(sleep_time); +static int another_ldap_try(struct smbldap_state *ldap_state, int *rc, + int *attempts, time_t endtime) +{ + time_t now = time(NULL); + int open_rc = LDAP_SERVER_DOWN; + + if (*rc != LDAP_SERVER_DOWN) + goto no_next; + + now = time(NULL); + + if (now >= endtime) { + smbldap_close(ldap_state); + *rc = LDAP_TIMEOUT; + goto no_next; } - (*attempts)++; - if ((rc = smbldap_open(ldap_state))) { - DEBUG(1,("Connection to LDAP Server failed for the %d try!\n",*attempts)); - return rc; - } - - return LDAP_SUCCESS; -} + if (*attempts == 0) { + got_alarm = False; + old_handler = CatchSignal(SIGALRM, gotalarm_sig); + alarm(endtime - now); + } + + while (1) { + if (*attempts != 0) + smb_msleep(1000); + + *attempts += 1; + + open_rc = smbldap_open(ldap_state); + + if (open_rc == LDAP_SUCCESS) { + ldap_state->last_use = now; + return True; + } + + if (got_alarm) { + *rc = LDAP_TIMEOUT; + break; + } + + if (open_rc != LDAP_SUCCESS) { + DEBUG(1, ("Connection to LDAP server failed for the " + "%d try!\n", *attempts)); + } + } + + no_next: + CatchSignal(SIGALRM, old_handler); + alarm(0); + ldap_state->last_use = now; + return False; +} /********************************************************************* ********************************************************************/ @@ -924,6 +954,7 @@ int smbldap_search(struct smbldap_state *ldap_state, int rc = LDAP_SERVER_DOWN; int attempts = 0; char *utf8_filter; + time_t endtime = time(NULL)+lp_ldap_timeout(); SMB_ASSERT(ldap_state); @@ -957,22 +988,10 @@ int smbldap_search(struct smbldap_state *ldap_state, return LDAP_NO_MEMORY; } - while ((rc == LDAP_SERVER_DOWN) && (attempts < SMBLDAP_NUM_RETRIES)) { - - if ((rc = smbldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) - continue; - + while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) rc = ldap_search_s(ldap_state->ldap_struct, base, scope, utf8_filter, attrs, attrsonly, res); - } - if (rc == LDAP_SERVER_DOWN) { - DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); - smbldap_close(ldap_state); - } - - ldap_state->last_use = time(NULL); - SAFE_FREE(utf8_filter); return rc; } @@ -982,6 +1001,7 @@ int smbldap_modify(struct smbldap_state *ldap_state, const char *dn, LDAPMod *at int rc = LDAP_SERVER_DOWN; int attempts = 0; char *utf8_dn; + time_t endtime = time(NULL)+lp_ldap_timeout(); SMB_ASSERT(ldap_state); @@ -991,21 +1011,9 @@ int smbldap_modify(struct smbldap_state *ldap_state, const char *dn, LDAPMod *at return LDAP_NO_MEMORY; } - while ((rc == LDAP_SERVER_DOWN) && (attempts < SMBLDAP_NUM_RETRIES)) { - - if ((rc = smbldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) - continue; - + while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) rc = ldap_modify_s(ldap_state->ldap_struct, utf8_dn, attrs); - } - - if (rc == LDAP_SERVER_DOWN) { - DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); - smbldap_close(ldap_state); - } - - ldap_state->last_use = time(NULL); - + SAFE_FREE(utf8_dn); return rc; } @@ -1015,6 +1023,7 @@ int smbldap_add(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs int rc = LDAP_SERVER_DOWN; int attempts = 0; char *utf8_dn; + time_t endtime = time(NULL)+lp_ldap_timeout(); SMB_ASSERT(ldap_state); @@ -1024,21 +1033,9 @@ int smbldap_add(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs return LDAP_NO_MEMORY; } - while ((rc == LDAP_SERVER_DOWN) && (attempts < SMBLDAP_NUM_RETRIES)) { - - if ((rc = smbldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) - continue; - + while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) rc = ldap_add_s(ldap_state->ldap_struct, utf8_dn, attrs); - } - if (rc == LDAP_SERVER_DOWN) { - DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); - smbldap_close(ldap_state); - } - - ldap_state->last_use = time(NULL); - SAFE_FREE(utf8_dn); return rc; } @@ -1048,6 +1045,7 @@ int smbldap_delete(struct smbldap_state *ldap_state, const char *dn) int rc = LDAP_SERVER_DOWN; int attempts = 0; char *utf8_dn; + time_t endtime = time(NULL)+lp_ldap_timeout(); SMB_ASSERT(ldap_state); @@ -1057,21 +1055,9 @@ int smbldap_delete(struct smbldap_state *ldap_state, const char *dn) return LDAP_NO_MEMORY; } - while ((rc == LDAP_SERVER_DOWN) && (attempts < SMBLDAP_NUM_RETRIES)) { - - if ((rc = smbldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) - continue; - + while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) rc = ldap_delete_s(ldap_state->ldap_struct, utf8_dn); - } - if (rc == LDAP_SERVER_DOWN) { - DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); - smbldap_close(ldap_state); - } - - ldap_state->last_use = time(NULL); - SAFE_FREE(utf8_dn); return rc; } @@ -1083,26 +1069,15 @@ int smbldap_extended_operation(struct smbldap_state *ldap_state, { int rc = LDAP_SERVER_DOWN; int attempts = 0; + time_t endtime = time(NULL)+lp_ldap_timeout(); if (!ldap_state) return (-1); - while ((rc == LDAP_SERVER_DOWN) && (attempts < SMBLDAP_NUM_RETRIES)) { - - if ((rc = smbldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) - continue; - - rc = ldap_extended_operation_s(ldap_state->ldap_struct, reqoid, reqdata, - serverctrls, clientctrls, retoidp, retdatap); - } - - if (rc == LDAP_SERVER_DOWN) { - DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); - smbldap_close(ldap_state); - } - - ldap_state->last_use = time(NULL); - + while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) + rc = ldap_extended_operation_s(ldap_state->ldap_struct, reqoid, + reqdata, serverctrls, + clientctrls, retoidp, retdatap); return rc; } diff --git a/source/lib/util_str.c b/source/lib/util_str.c index 7c5fa11c92d..1083076edd4 100644 --- a/source/lib/util_str.c +++ b/source/lib/util_str.c @@ -1949,7 +1949,9 @@ DATA_BLOB base64_decode_data_blob(const char *s) s++; i++; } - if (*s == '=') n -= 1; + if ((n > 0) && (*s == '=')) { + n -= 1; + } /* fix up length */ decoded.length = n; @@ -1962,9 +1964,15 @@ DATA_BLOB base64_decode_data_blob(const char *s) void base64_decode_inplace(char *s) { DATA_BLOB decoded = base64_decode_data_blob(s); - memcpy(s, decoded.data, decoded.length); - /* null terminate */ - s[decoded.length] = '\0'; + + if ( decoded.length != 0 ) { + memcpy(s, decoded.data, decoded.length); + + /* null terminate */ + s[decoded.length] = '\0'; + } else { + *s = '\0'; + } data_blob_free(&decoded); } diff --git a/source/lib/util_uuid.c b/source/lib/util_uuid.c index dc9bc920230..8f86c2109ea 100644 --- a/source/lib/util_uuid.c +++ b/source/lib/util_uuid.c @@ -57,7 +57,7 @@ void smb_uuid_generate_random(struct uuid *uu) { UUID_FLAT tmp; - generate_random_buffer(tmp.info, sizeof(tmp.info), True); + generate_random_buffer(tmp.info, sizeof(tmp.info)); smb_uuid_unpack(tmp, uu); uu->clock_seq[0] = (uu->clock_seq[0] & 0x3F) | 0x80; diff --git a/source/libsmb/cliconnect.c b/source/libsmb/cliconnect.c index afbd2079eac..559538aac9b 100644 --- a/source/libsmb/cliconnect.c +++ b/source/libsmb/cliconnect.c @@ -81,7 +81,10 @@ static BOOL cli_session_setup_lanman2(struct cli_state *cli, const char *user, if (passlen > 0 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen != 24) { /* Encrypted mode needed, and non encrypted password supplied. */ lm_response = data_blob(NULL, 24); - SMBencrypt(pass, cli->secblob.data,(uchar *)lm_response.data); + if (!SMBencrypt(pass, cli->secblob.data,(uchar *)lm_response.data)) { + DEBUG(1, ("Password is > 14 chars in length, and is therefore incompatible with Lanman authentication\n")); + return False; + } } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen == 24) { /* Encrypted mode needed, and encrypted password supplied. */ lm_response = data_blob(pass, passlen); @@ -106,7 +109,7 @@ static BOOL cli_session_setup_lanman2(struct cli_state *cli, const char *user, p = smb_buf(cli->outbuf); memcpy(p,lm_response.data,lm_response.length); - p += passlen; + p += lm_response.length; p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER); p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER); p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE); @@ -675,7 +678,7 @@ static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *use for checking the first reply from the server */ cli_calculate_sign_mac(cli); - if (!cli_check_sign_mac(cli, True)) { + if (!cli_check_sign_mac(cli)) { nt_status = NT_STATUS_ACCESS_DENIED; } } diff --git a/source/libsmb/clidgram.c b/source/libsmb/clidgram.c index c4675f1938a..ba65c46d16e 100644 --- a/source/libsmb/clidgram.c +++ b/source/libsmb/clidgram.c @@ -63,7 +63,7 @@ int cli_send_mailslot(int dgram_sock, BOOL unique, const char *mailslot, /* Setup the smb part. */ ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */ memcpy(tmp,ptr,4); - set_message(ptr,17,17 + len,True); + set_message(ptr,17,strlen(mailslot) + 1 + len,True); memcpy(ptr,tmp,4); SCVAL(ptr,smb_com,SMBtrans); diff --git a/source/libsmb/clientgen.c b/source/libsmb/clientgen.c index 281ee3af845..974ebf91f5c 100644 --- a/source/libsmb/clientgen.c +++ b/source/libsmb/clientgen.c @@ -117,7 +117,7 @@ BOOL cli_receive_smb(struct cli_state *cli) return ret; } - if (!cli_check_sign_mac(cli, True)) { + if (!cli_check_sign_mac(cli)) { DEBUG(0, ("SMB Signature verification failed on incoming packet!\n")); cli->smb_rw_error = READ_BAD_SIG; close(cli->fd); diff --git a/source/libsmb/clikrb5.c b/source/libsmb/clikrb5.c index b9a3dda4944..5fcde4654ad 100644 --- a/source/libsmb/clikrb5.c +++ b/source/libsmb/clikrb5.c @@ -442,8 +442,6 @@ failed: krb5_error_code err; BOOL ret = False; - memset(session_key, 0, 16); - if (remote) err = krb5_auth_con_getremotesubkey(context, auth_context, &skey); else diff --git a/source/libsmb/ntlmssp.c b/source/libsmb/ntlmssp.c index 66d48afc463..6e41a61bf1b 100644 --- a/source/libsmb/ntlmssp.c +++ b/source/libsmb/ntlmssp.c @@ -103,7 +103,7 @@ void debug_ntlmssp_flags(uint32 neg_flags) static const uint8 *get_challenge(const struct ntlmssp_state *ntlmssp_state) { static uchar chal[8]; - generate_random_buffer(chal, sizeof(chal), False); + generate_random_buffer(chal, sizeof(chal)); return chal; } @@ -960,7 +960,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, E_md4hash(ntlmssp_state->password, nt_hash); lm_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24); - generate_random_buffer(lm_response.data, 8, False); + generate_random_buffer(lm_response.data, 8); memset(lm_response.data+8, 0, 16); memcpy(session_nonce, challenge_blob.data, 8); @@ -1022,7 +1022,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) { /* Make up a new session key */ uint8 client_session_key[16]; - generate_random_buffer(client_session_key, sizeof(client_session_key), False); + generate_random_buffer(client_session_key, sizeof(client_session_key)); /* Encrypt the new session key with the old one */ encrypted_session_key = data_blob(client_session_key, sizeof(client_session_key)); diff --git a/source/libsmb/passchange.c b/source/libsmb/passchange.c index 9f46c131fee..8bce9c86a1e 100644 --- a/source/libsmb/passchange.c +++ b/source/libsmb/passchange.c @@ -144,6 +144,8 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name, init_creds(&creds, "", "", NULL); cli_init_creds(&cli, &creds); + cli.pipe_auth_flags = 0; + result = NT_STATUS_UNSUCCESSFUL; /* OK, this is ugly, but... */ diff --git a/source/libsmb/smb_signing.c b/source/libsmb/smb_signing.c index 8c59e49ebb9..39131debf5e 100644 --- a/source/libsmb/smb_signing.c +++ b/source/libsmb/smb_signing.c @@ -627,9 +627,9 @@ void cli_calculate_sign_mac(struct cli_state *cli) * which had a bad checksum, True otherwise. */ -BOOL cli_check_sign_mac(struct cli_state *cli, BOOL must_be_ok) +BOOL cli_check_sign_mac(struct cli_state *cli) { - if (!cli->sign_info.check_incoming_message(cli->inbuf, &cli->sign_info, must_be_ok)) { + if (!cli->sign_info.check_incoming_message(cli->inbuf, &cli->sign_info, True)) { free_signing_context(&cli->sign_info); return False; } diff --git a/source/libsmb/smbencrypt.c b/source/libsmb/smbencrypt.c index 44f7428086b..9f936b77aec 100644 --- a/source/libsmb/smbencrypt.c +++ b/source/libsmb/smbencrypt.c @@ -352,7 +352,7 @@ static DATA_BLOB NTLMv2_generate_client_data(const DATA_BLOB *names_blob) DATA_BLOB response = data_blob(NULL, 0); char long_date[8]; - generate_random_buffer(client_chal, sizeof(client_chal), False); + generate_random_buffer(client_chal, sizeof(client_chal)); put_long_date(long_date, time(NULL)); @@ -406,7 +406,7 @@ static DATA_BLOB LMv2_generate_response(const uchar ntlm_v2_hash[16], /* LMv2 */ /* client-supplied random data */ - generate_random_buffer(lmv2_client_data.data, lmv2_client_data.length, False); + generate_random_buffer(lmv2_client_data.data, lmv2_client_data.length); /* Given that data, and the challenge from the server, generate a response */ SMBOWFencrypt_ntv2(ntlm_v2_hash, server_chal, &lmv2_client_data, lmv2_response); @@ -476,7 +476,7 @@ BOOL encode_pw_buffer(char buffer[516], const char *password, int string_flags) memcpy(&buffer[512 - new_pw_len], new_pw, new_pw_len); - generate_random_buffer((unsigned char *)buffer, 512 - new_pw_len, True); + generate_random_buffer((unsigned char *)buffer, 512 - new_pw_len); /* * The length of the new password is in the last 4 bytes of diff --git a/source/nsswitch/wbinfo.c b/source/nsswitch/wbinfo.c index ce48e9ae652..0028982d201 100644 --- a/source/nsswitch/wbinfo.c +++ b/source/nsswitch/wbinfo.c @@ -398,6 +398,27 @@ static BOOL wbinfo_sid_to_uid(char *sid) ZERO_STRUCT(request); ZERO_STRUCT(response); + /* First see whether the SID is actually a user -- otherwise + * winbind might end up a uid number for a group SID and this + * is asking for trouble later. */ + + fstrcpy(request.data.sid, sid); + + if (winbindd_request(WINBINDD_LOOKUPSID, &request, &response) != + NSS_STATUS_SUCCESS) { + d_printf("Could not lookup sid %s\n", sid); + return False; + } + + if (response.data.name.type != SID_NAME_USER) { + d_printf("SID is of type %s\n", + sid_type_lookup(response.data.name.type)); + return False; + } + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + /* Send request */ fstrcpy(request.data.sid, sid); @@ -421,6 +442,26 @@ static BOOL wbinfo_sid_to_gid(char *sid) ZERO_STRUCT(request); ZERO_STRUCT(response); + /* First see whether the SID is actually a group -- otherwise + * winbind might end up a gid number for a user SID and this + * is asking for trouble later. */ + + fstrcpy(request.data.sid, sid); + + if (winbindd_request(WINBINDD_LOOKUPSID, &request, &response) != + NSS_STATUS_SUCCESS) { + d_printf("Could not lookup sid %s\n", sid); + return False; + } + + if ((response.data.name.type != SID_NAME_DOM_GRP) && + (response.data.name.type != SID_NAME_ALIAS) && + (response.data.name.type != SID_NAME_WKN_GRP)) { + d_printf("SID is of type %s\n", + sid_type_lookup(response.data.name.type)); + return False; + } + /* Send request */ fstrcpy(request.data.sid, sid); @@ -580,7 +621,7 @@ static BOOL wbinfo_auth_crap(char *username) return False; } - generate_random_buffer(request.data.auth_crap.chal, 8, False); + generate_random_buffer(request.data.auth_crap.chal, 8); SMBencrypt(pass, request.data.auth_crap.chal, (uchar *)request.data.auth_crap.lm_resp); diff --git a/source/nsswitch/winbindd.c b/source/nsswitch/winbindd.c index 50b6f0a87fb..d08aa84face 100644 --- a/source/nsswitch/winbindd.c +++ b/source/nsswitch/winbindd.c @@ -188,6 +188,17 @@ static void sighup_handler(int signum) sys_select_signal(); } +static void sigchld_handler(int signum) +{ + pid_t pid; + int status; + + while ((pid = wait(&status)) != -1 || errno == EINTR) { + continue; /* Reap children */ + } + sys_select_signal(); +} + /* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/ static void msg_reload_services(int msg_type, pid_t src, void *buf, size_t len) { @@ -888,12 +899,14 @@ int main(int argc, char **argv) BlockSignals(False, SIGUSR1); BlockSignals(False, SIGUSR2); BlockSignals(False, SIGHUP); + BlockSignals(False, SIGCHLD); /* Setup signal handlers */ CatchSignal(SIGINT, termination_handler); /* Exit on these sigs */ CatchSignal(SIGQUIT, termination_handler); CatchSignal(SIGTERM, termination_handler); + CatchSignal(SIGCHLD, sigchld_handler); CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */ diff --git a/source/nsswitch/winbindd_cm.c b/source/nsswitch/winbindd_cm.c index 04f87fc1a2f..ad49df3982b 100644 --- a/source/nsswitch/winbindd_cm.c +++ b/source/nsswitch/winbindd_cm.c @@ -70,7 +70,6 @@ struct winbindd_cm_conn { fstring domain; fstring controller; fstring pipe_name; - size_t mutex_ref_count; struct cli_state *cli; POLICY_HND pol; }; diff --git a/source/nsswitch/winbindd_pam.c b/source/nsswitch/winbindd_pam.c index 25f53e7a535..81d4e69ccd6 100644 --- a/source/nsswitch/winbindd_pam.c +++ b/source/nsswitch/winbindd_pam.c @@ -190,7 +190,7 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) /* do password magic */ - generate_random_buffer(chal, 8, False); + generate_random_buffer(chal, 8); SMBencrypt(state->request.data.auth.pass, chal, local_lm_response); SMBNTencrypt(state->request.data.auth.pass, chal, local_nt_response); diff --git a/source/nsswitch/wins.c b/source/nsswitch/wins.c index b71995998f5..a1c4f4deec0 100644 --- a/source/nsswitch/wins.c +++ b/source/nsswitch/wins.c @@ -90,7 +90,7 @@ static struct in_addr *lookup_byname_backend(const char *name, int *count) { int fd = -1; struct ip_service *address = NULL; - struct in_addr *ret; + struct in_addr *ret = NULL; int j, flags = 0; if (!initialised) { diff --git a/source/param/loadparm.c b/source/param/loadparm.c index 0710c36514b..978ea89d5c6 100644 --- a/source/param/loadparm.c +++ b/source/param/loadparm.c @@ -176,7 +176,7 @@ typedef struct BOOL bWinbindTrustedDomainsOnly; BOOL bWinbindNestedGroups; char *szWinbindBackend; - char *szIdmapBackend; + char **szIdmapBackend; char *szAddShareCommand; char *szChangeShareCommand; char *szDeleteShareCommand; @@ -1165,7 +1165,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}, - {"idmap backend", P_STRING, P_GLOBAL, &Globals.szIdmapBackend, 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}, {"idmap gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_ADVANCED}, @@ -1710,7 +1710,7 @@ FN_GLOBAL_BOOL(lp_winbind_use_default_domain, &Globals.bWinbindUseDefaultDomain) FN_GLOBAL_BOOL(lp_winbind_trusted_domains_only, &Globals.bWinbindTrustedDomainsOnly) FN_GLOBAL_BOOL(lp_winbind_nested_groups, &Globals.bWinbindNestedGroups) -FN_GLOBAL_STRING(lp_idmap_backend, &Globals.szIdmapBackend) +FN_GLOBAL_LIST(lp_idmap_backend, &Globals.szIdmapBackend) FN_GLOBAL_BOOL(lp_enable_rid_algorithm, &Globals.bEnableRidAlgorithm) #ifdef WITH_LDAP_SAMCONFIG @@ -3552,14 +3552,14 @@ static void dump_a_service(service * pService, FILE * f) ((char *)pService) + pdiff, f); fprintf(f, "\n"); } + } - if (pService->param_opt != NULL) { - data = pService->param_opt; - while(data) { - fprintf(f, "\t%s = %s\n", data->key, data->value); - data = data->next; - } - } + if (pService->param_opt != NULL) { + data = pService->param_opt; + while(data) { + fprintf(f, "\t%s = %s\n", data->key, data->value); + data = data->next; + } } } @@ -4320,7 +4320,7 @@ int lp_maxprintjobs(int snum) BOOL lp_use_sendfile(int snum) { - return (_lp_use_sendfile(snum) && !srv_is_signing_active()); + return (_lp_use_sendfile(snum) && (get_remote_arch() != RA_WIN95) && !srv_is_signing_active()); } /******************************************************************* diff --git a/source/passdb/machine_sid.c b/source/passdb/machine_sid.c index 47b9e2d487e..ce1354ce818 100644 --- a/source/passdb/machine_sid.c +++ b/source/passdb/machine_sid.c @@ -67,7 +67,7 @@ static void generate_random_sid(DOM_SID *sid) sid->num_auths = 0; sid->sub_auths[sid->num_auths++] = 21; - generate_random_buffer(raw_sid_data, 12, True); + generate_random_buffer(raw_sid_data, 12); for (i = 0; i < 3; i++) sid->sub_auths[sid->num_auths++] = IVAL(raw_sid_data, i*4); } diff --git a/source/passdb/passdb.c b/source/passdb/passdb.c index c3a423c2636..2f9742e17da 100644 --- a/source/passdb/passdb.c +++ b/source/passdb/passdb.c @@ -932,7 +932,7 @@ BOOL local_password_change(const char *user_name, int local_flags, if ((local_flags & LOCAL_ADD_USER) || (local_flags & LOCAL_DELETE_USER)) { /* Might not exist in /etc/passwd. Use rid algorithm here */ if (!NT_STATUS_IS_OK(pdb_init_sam_new(&sam_pass, user_name, 0))) { - slprintf(err_str, err_str_len-1, "Failed to initialise SAM_ACCOUNT for user %s.\n", user_name); + slprintf(err_str, err_str_len-1, "Failed to initialise SAM_ACCOUNT for user %s. Does this user exist in the UNIX password database ?\n", user_name); return False; } } else { @@ -1301,6 +1301,7 @@ BOOL local_sid_to_gid(gid_t *pgid, const DOM_SID *psid, enum SID_NAME_USE *name_ #define TDB_FORMAT_STRING_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd" #define TDB_FORMAT_STRING_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd" +#define TDB_FORMAT_STRING_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd" /********************************************************************** Intialize a SAM_ACCOUNT struct from a BYTE buffer of size len @@ -1308,7 +1309,7 @@ BOOL local_sid_to_gid(gid_t *pgid, const DOM_SID *psid, enum SID_NAME_USE *name_ BOOL init_sam_from_buffer(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) { - return(init_sam_from_buffer_v1(sampass, buf, buflen)); + return(init_sam_from_buffer_v2(sampass, buf, buflen)); } /********************************************************************** @@ -1317,7 +1318,7 @@ BOOL init_sam_from_buffer(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) uint32 init_buffer_from_sam (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL size_only) { - return(init_buffer_from_sam_v1(buf, sampass, size_only)); + return(init_buffer_from_sam_v2(buf, sampass, size_only)); } @@ -1354,48 +1355,50 @@ BOOL init_sam_from_buffer_v0(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) uint16 acct_ctrl, logon_divs; uint16 bad_password_count, logon_count; uint8 *hours; - static uint8 *lm_pw_ptr, *nt_pw_ptr; + uint8 *lm_pw_ptr, *nt_pw_ptr; uint32 len = 0; uint32 lm_pw_len, nt_pw_len, hourslen; BOOL ret = True; if(sampass == NULL || buf == NULL) { - DEBUG(0, ("init_sam_from_buffer: NULL parameters found!\n")); + DEBUG(0, ("init_sam_from_buffer_v0: NULL parameters found!\n")); return False; } - + +/* TDB_FORMAT_STRING_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd" */ + /* unpack the buffer into variables */ len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V0, - &logon_time, - &logoff_time, - &kickoff_time, - &pass_last_set_time, - &pass_can_change_time, - &pass_must_change_time, - &username_len, &username, - &domain_len, &domain, - &nt_username_len, &nt_username, - &fullname_len, &fullname, - &homedir_len, &homedir, - &dir_drive_len, &dir_drive, - &logon_script_len, &logon_script, - &profile_path_len, &profile_path, - &acct_desc_len, &acct_desc, - &workstations_len, &workstations, - &unknown_str_len, &unknown_str, - &munged_dial_len, &munged_dial, - &user_rid, - &group_rid, - &lm_pw_len, &lm_pw_ptr, - &nt_pw_len, &nt_pw_ptr, - &acct_ctrl, - &remove_me, /* remove on the next TDB_FORMAT upgarde */ - &logon_divs, - &hours_len, - &hourslen, &hours, - &bad_password_count, - &logon_count, - &unknown_6); + &logon_time, /* d */ + &logoff_time, /* d */ + &kickoff_time, /* d */ + &pass_last_set_time, /* d */ + &pass_can_change_time, /* d */ + &pass_must_change_time, /* d */ + &username_len, &username, /* B */ + &domain_len, &domain, /* B */ + &nt_username_len, &nt_username, /* B */ + &fullname_len, &fullname, /* B */ + &homedir_len, &homedir, /* B */ + &dir_drive_len, &dir_drive, /* B */ + &logon_script_len, &logon_script, /* B */ + &profile_path_len, &profile_path, /* B */ + &acct_desc_len, &acct_desc, /* B */ + &workstations_len, &workstations, /* B */ + &unknown_str_len, &unknown_str, /* B */ + &munged_dial_len, &munged_dial, /* B */ + &user_rid, /* d */ + &group_rid, /* d */ + &lm_pw_len, &lm_pw_ptr, /* B */ + &nt_pw_len, &nt_pw_ptr, /* B */ + &acct_ctrl, /* w */ + &remove_me, /* remove on the next TDB_FORMAT upgarde */ /* d */ + &logon_divs, /* w */ + &hours_len, /* d */ + &hourslen, &hours, /* B */ + &bad_password_count, /* w */ + &logon_count, /* w */ + &unknown_6); /* d */ if (len == (uint32) -1) { ret = False; @@ -1465,6 +1468,7 @@ BOOL init_sam_from_buffer_v0(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) } } + pdb_set_pw_history(sampass, NULL, 0, PDB_SET); pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET); pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET); pdb_set_hours_len(sampass, hours_len, PDB_SET); @@ -1489,15 +1493,15 @@ done: SAFE_FREE(workstations); SAFE_FREE(munged_dial); SAFE_FREE(unknown_str); + SAFE_FREE(lm_pw_ptr); + SAFE_FREE(nt_pw_ptr); SAFE_FREE(hours); return ret; } - -uint32 init_buffer_from_sam_v0 (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL size_only) +BOOL init_sam_from_buffer_v1(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) { - size_t len, buflen; /* times are stored as 32bit integer take care on system with 64bit wide time_t @@ -1505,237 +1509,184 @@ uint32 init_buffer_from_sam_v0 (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL si uint32 logon_time, logoff_time, kickoff_time, + bad_password_time, pass_last_set_time, pass_can_change_time, pass_must_change_time; - - uint32 user_rid, group_rid; - - const char *username; - const char *domain; - const char *nt_username; - const char *dir_drive; - const char *unknown_str; - const char *munged_dial; - const char *fullname; - const char *homedir; - const char *logon_script; - const char *profile_path; - const char *acct_desc; - const char *workstations; + char *username; + char *domain; + char *nt_username; + char *dir_drive; + char *unknown_str; + char *munged_dial; + char *fullname; + char *homedir; + char *logon_script; + char *profile_path; + char *acct_desc; + char *workstations; uint32 username_len, domain_len, nt_username_len, dir_drive_len, unknown_str_len, munged_dial_len, fullname_len, homedir_len, logon_script_len, profile_path_len, acct_desc_len, workstations_len; - - const uint8 *lm_pw; - const uint8 *nt_pw; - uint32 lm_pw_len = 16; - uint32 nt_pw_len = 16; - - /* do we have a valid SAM_ACCOUNT pointer? */ - if (sampass == NULL) { - DEBUG(0, ("init_buffer_from_sam: SAM_ACCOUNT is NULL!\n")); - return -1; - } + + uint32 user_rid, group_rid, remove_me, hours_len, unknown_6; + uint16 acct_ctrl, logon_divs; + uint16 bad_password_count, logon_count; + uint8 *hours; + uint8 *lm_pw_ptr, *nt_pw_ptr; + uint32 len = 0; + uint32 lm_pw_len, nt_pw_len, hourslen; + BOOL ret = True; - *buf = NULL; - buflen = 0; + if(sampass == NULL || buf == NULL) { + DEBUG(0, ("init_sam_from_buffer_v1: NULL parameters found!\n")); + return False; + } - logon_time = (uint32)pdb_get_logon_time(sampass); - logoff_time = (uint32)pdb_get_logoff_time(sampass); - kickoff_time = (uint32)pdb_get_kickoff_time(sampass); - pass_can_change_time = (uint32)pdb_get_pass_can_change_time(sampass); - pass_must_change_time = (uint32)pdb_get_pass_must_change_time(sampass); - pass_last_set_time = (uint32)pdb_get_pass_last_set_time(sampass); +/* TDB_FORMAT_STRING_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd" */ - user_rid = pdb_get_user_rid(sampass); - group_rid = pdb_get_group_rid(sampass); + /* unpack the buffer into variables */ + len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V1, + &logon_time, /* d */ + &logoff_time, /* d */ + &kickoff_time, /* d */ + /* Change from V0 is addition of bad_password_time field. */ + &bad_password_time, /* d */ + &pass_last_set_time, /* d */ + &pass_can_change_time, /* d */ + &pass_must_change_time, /* d */ + &username_len, &username, /* B */ + &domain_len, &domain, /* B */ + &nt_username_len, &nt_username, /* B */ + &fullname_len, &fullname, /* B */ + &homedir_len, &homedir, /* B */ + &dir_drive_len, &dir_drive, /* B */ + &logon_script_len, &logon_script, /* B */ + &profile_path_len, &profile_path, /* B */ + &acct_desc_len, &acct_desc, /* B */ + &workstations_len, &workstations, /* B */ + &unknown_str_len, &unknown_str, /* B */ + &munged_dial_len, &munged_dial, /* B */ + &user_rid, /* d */ + &group_rid, /* d */ + &lm_pw_len, &lm_pw_ptr, /* B */ + &nt_pw_len, &nt_pw_ptr, /* B */ + &acct_ctrl, /* w */ + &remove_me, /* d */ + &logon_divs, /* w */ + &hours_len, /* d */ + &hourslen, &hours, /* B */ + &bad_password_count, /* w */ + &logon_count, /* w */ + &unknown_6); /* d */ + + if (len == (uint32) -1) { + ret = False; + goto done; + } - username = pdb_get_username(sampass); - if (username) - username_len = strlen(username) +1; - else - username_len = 0; + pdb_set_logon_time(sampass, logon_time, PDB_SET); + pdb_set_logoff_time(sampass, logoff_time, PDB_SET); + pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET); - domain = pdb_get_domain(sampass); - if (domain) - domain_len = strlen(domain) +1; - else - domain_len = 0; + /* Change from V0 is addition of bad_password_time field. */ + pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET); + pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET); + pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET); + pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET); - nt_username = pdb_get_nt_username(sampass); - if (nt_username) - nt_username_len = strlen(nt_username) +1; - else - nt_username_len = 0; + pdb_set_username(sampass, username, PDB_SET); + pdb_set_domain(sampass, domain, PDB_SET); + pdb_set_nt_username(sampass, nt_username, PDB_SET); + pdb_set_fullname(sampass, fullname, PDB_SET); - fullname = pdb_get_fullname(sampass); - if (fullname) - fullname_len = strlen(fullname) +1; - else - fullname_len = 0; + if (homedir) { + pdb_set_homedir(sampass, homedir, PDB_SET); + } + else { + pdb_set_homedir(sampass, + talloc_sub_basic(sampass->mem_ctx, username, lp_logon_home()), + PDB_DEFAULT); + } - /* - * Only updates fields which have been set (not defaults from smb.conf) - */ + if (dir_drive) + pdb_set_dir_drive(sampass, dir_drive, PDB_SET); + else { + pdb_set_dir_drive(sampass, + talloc_sub_basic(sampass->mem_ctx, username, lp_logon_drive()), + PDB_DEFAULT); + } - if (!IS_SAM_DEFAULT(sampass, PDB_DRIVE)) - dir_drive = pdb_get_dir_drive(sampass); - else - dir_drive = NULL; - if (dir_drive) - dir_drive_len = strlen(dir_drive) +1; - else - dir_drive_len = 0; + if (logon_script) + pdb_set_logon_script(sampass, logon_script, PDB_SET); + else { + pdb_set_logon_script(sampass, + talloc_sub_basic(sampass->mem_ctx, username, lp_logon_script()), + PDB_DEFAULT); + } + + if (profile_path) { + pdb_set_profile_path(sampass, profile_path, PDB_SET); + } else { + pdb_set_profile_path(sampass, + talloc_sub_basic(sampass->mem_ctx, username, lp_logon_path()), + PDB_DEFAULT); + } - if (!IS_SAM_DEFAULT(sampass, PDB_SMBHOME)) - homedir = pdb_get_homedir(sampass); - else - homedir = NULL; - if (homedir) - homedir_len = strlen(homedir) +1; - else - homedir_len = 0; + pdb_set_acct_desc(sampass, acct_desc, PDB_SET); + pdb_set_workstations(sampass, workstations, PDB_SET); + pdb_set_munged_dial(sampass, munged_dial, PDB_SET); - if (!IS_SAM_DEFAULT(sampass, PDB_LOGONSCRIPT)) - logon_script = pdb_get_logon_script(sampass); - else - logon_script = NULL; - if (logon_script) - logon_script_len = strlen(logon_script) +1; - else - logon_script_len = 0; + if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) { + if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) { + ret = False; + goto done; + } + } - if (!IS_SAM_DEFAULT(sampass, PDB_PROFILE)) - profile_path = pdb_get_profile_path(sampass); - else - profile_path = NULL; - if (profile_path) - profile_path_len = strlen(profile_path) +1; - else - profile_path_len = 0; - - lm_pw = pdb_get_lanman_passwd(sampass); - if (!lm_pw) - lm_pw_len = 0; - - nt_pw = pdb_get_nt_passwd(sampass); - if (!nt_pw) - nt_pw_len = 0; - - acct_desc = pdb_get_acct_desc(sampass); - if (acct_desc) - acct_desc_len = strlen(acct_desc) +1; - else - acct_desc_len = 0; + if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) { + if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) { + ret = False; + goto done; + } + } - workstations = pdb_get_workstations(sampass); - if (workstations) - workstations_len = strlen(workstations) +1; - else - workstations_len = 0; + pdb_set_pw_history(sampass, NULL, 0, PDB_SET); - unknown_str = NULL; - unknown_str_len = 0; + pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET); + pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET); + pdb_set_hours_len(sampass, hours_len, PDB_SET); + pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET); + pdb_set_logon_count(sampass, logon_count, PDB_SET); + pdb_set_unknown_6(sampass, unknown_6, PDB_SET); + pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET); + pdb_set_logon_divs(sampass, logon_divs, PDB_SET); + pdb_set_hours(sampass, hours, PDB_SET); - munged_dial = pdb_get_munged_dial(sampass); - if (munged_dial) - munged_dial_len = strlen(munged_dial) +1; - else - munged_dial_len = 0; - - /* one time to get the size needed */ - len = tdb_pack(NULL, 0, TDB_FORMAT_STRING_V0, - logon_time, - logoff_time, - kickoff_time, - pass_last_set_time, - pass_can_change_time, - pass_must_change_time, - username_len, username, - domain_len, domain, - nt_username_len, nt_username, - fullname_len, fullname, - homedir_len, homedir, - dir_drive_len, dir_drive, - logon_script_len, logon_script, - profile_path_len, profile_path, - acct_desc_len, acct_desc, - workstations_len, workstations, - unknown_str_len, unknown_str, - munged_dial_len, munged_dial, - user_rid, - group_rid, - lm_pw_len, lm_pw, - nt_pw_len, nt_pw, - pdb_get_acct_ctrl(sampass), - 0, /* was: fileds_present, to be removed on format change */ - pdb_get_logon_divs(sampass), - pdb_get_hours_len(sampass), - MAX_HOURS_LEN, pdb_get_hours(sampass), - pdb_get_bad_password_count(sampass), - pdb_get_logon_count(sampass), - pdb_get_unknown_6(sampass)); - - - if (size_only) - return buflen; +done: - /* malloc the space needed */ - if ( (*buf=(uint8*)malloc(len)) == NULL) { - DEBUG(0,("init_buffer_from_sam: Unable to malloc() memory for buffer!\n")); - return (-1); - } - - /* now for the real call to tdb_pack() */ - buflen = tdb_pack((char *)*buf, len, TDB_FORMAT_STRING_V0, - logon_time, - logoff_time, - kickoff_time, - pass_last_set_time, - pass_can_change_time, - pass_must_change_time, - username_len, username, - domain_len, domain, - nt_username_len, nt_username, - fullname_len, fullname, - homedir_len, homedir, - dir_drive_len, dir_drive, - logon_script_len, logon_script, - profile_path_len, profile_path, - acct_desc_len, acct_desc, - workstations_len, workstations, - unknown_str_len, unknown_str, - munged_dial_len, munged_dial, - user_rid, - group_rid, - lm_pw_len, lm_pw, - nt_pw_len, nt_pw, - pdb_get_acct_ctrl(sampass), - 0, /* was: fileds_present, to be removed on format change */ - pdb_get_logon_divs(sampass), - pdb_get_hours_len(sampass), - MAX_HOURS_LEN, pdb_get_hours(sampass), - pdb_get_bad_password_count(sampass), - pdb_get_logon_count(sampass), - pdb_get_unknown_6(sampass)); - - - /* check to make sure we got it correct */ - if (buflen != len) { - DEBUG(0, ("init_buffer_from_sam: somthing odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n", - (unsigned long)buflen, (unsigned long)len)); - /* error */ - SAFE_FREE (*buf); - return (-1); - } + SAFE_FREE(username); + SAFE_FREE(domain); + SAFE_FREE(nt_username); + SAFE_FREE(fullname); + SAFE_FREE(homedir); + SAFE_FREE(dir_drive); + SAFE_FREE(logon_script); + SAFE_FREE(profile_path); + SAFE_FREE(acct_desc); + SAFE_FREE(workstations); + SAFE_FREE(munged_dial); + SAFE_FREE(unknown_str); + SAFE_FREE(lm_pw_ptr); + SAFE_FREE(nt_pw_ptr); + SAFE_FREE(hours); - return (buflen); + return ret; } -BOOL init_sam_from_buffer_v1(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) +BOOL init_sam_from_buffer_v2(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) { /* times are stored as 32bit integer @@ -1765,53 +1716,58 @@ BOOL init_sam_from_buffer_v1(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) fullname_len, homedir_len, logon_script_len, profile_path_len, acct_desc_len, workstations_len; - uint32 user_rid, group_rid, remove_me, hours_len, unknown_6; + uint32 user_rid, group_rid, hours_len, unknown_6; uint16 acct_ctrl, logon_divs; uint16 bad_password_count, logon_count; uint8 *hours; - static uint8 *lm_pw_ptr, *nt_pw_ptr; + uint8 *lm_pw_ptr, *nt_pw_ptr, *nt_pw_hist_ptr; uint32 len = 0; - uint32 lm_pw_len, nt_pw_len, hourslen; + uint32 lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen; + uint32 pwHistLen = 0; BOOL ret = True; if(sampass == NULL || buf == NULL) { - DEBUG(0, ("init_sam_from_buffer: NULL parameters found!\n")); + DEBUG(0, ("init_sam_from_buffer_v2: NULL parameters found!\n")); return False; } +/* TDB_FORMAT_STRING_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd" */ + /* unpack the buffer into variables */ - len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V1, - &logon_time, - &logoff_time, - &kickoff_time, - &bad_password_time, - &pass_last_set_time, - &pass_can_change_time, - &pass_must_change_time, - &username_len, &username, - &domain_len, &domain, - &nt_username_len, &nt_username, - &fullname_len, &fullname, - &homedir_len, &homedir, - &dir_drive_len, &dir_drive, - &logon_script_len, &logon_script, - &profile_path_len, &profile_path, - &acct_desc_len, &acct_desc, - &workstations_len, &workstations, - &unknown_str_len, &unknown_str, - &munged_dial_len, &munged_dial, - &user_rid, - &group_rid, - &lm_pw_len, &lm_pw_ptr, - &nt_pw_len, &nt_pw_ptr, - &acct_ctrl, - &remove_me, - &logon_divs, - &hours_len, - &hourslen, &hours, - &bad_password_count, - &logon_count, - &unknown_6); + len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V2, + &logon_time, /* d */ + &logoff_time, /* d */ + &kickoff_time, /* d */ + &bad_password_time, /* d */ + &pass_last_set_time, /* d */ + &pass_can_change_time, /* d */ + &pass_must_change_time, /* d */ + &username_len, &username, /* B */ + &domain_len, &domain, /* B */ + &nt_username_len, &nt_username, /* B */ + &fullname_len, &fullname, /* B */ + &homedir_len, &homedir, /* B */ + &dir_drive_len, &dir_drive, /* B */ + &logon_script_len, &logon_script, /* B */ + &profile_path_len, &profile_path, /* B */ + &acct_desc_len, &acct_desc, /* B */ + &workstations_len, &workstations, /* B */ + &unknown_str_len, &unknown_str, /* B */ + &munged_dial_len, &munged_dial, /* B */ + &user_rid, /* d */ + &group_rid, /* d */ + &lm_pw_len, &lm_pw_ptr, /* B */ + &nt_pw_len, &nt_pw_ptr, /* B */ + /* Change from V1 is addition of password history field. */ + &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */ + &acct_ctrl, /* w */ + /* Also "remove_me" field was removed. */ + &logon_divs, /* w */ + &hours_len, /* d */ + &hourslen, &hours, /* B */ + &bad_password_count, /* w */ + &logon_count, /* w */ + &unknown_6); /* d */ if (len == (uint32) -1) { ret = False; @@ -1882,6 +1838,33 @@ BOOL init_sam_from_buffer_v1(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) } } + /* Change from V1 is addition of password history field. */ + account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen); + if (pwHistLen) { + char *pw_hist = malloc(pwHistLen * NT_HASH_LEN); + if (!pw_hist) { + ret = False; + goto done; + } + memset(pw_hist, '\0', pwHistLen * NT_HASH_LEN); + if (nt_pw_hist_ptr && nt_pw_hist_len) { + int i; + SMB_ASSERT((nt_pw_hist_len % NT_HASH_LEN) == 0); + nt_pw_hist_len /= NT_HASH_LEN; + for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) { + memcpy(&pw_hist[i*NT_HASH_LEN], &nt_pw_hist_ptr[i*NT_HASH_LEN], NT_HASH_LEN); + } + } + if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) { + SAFE_FREE(pw_hist); + ret = False; + goto done; + } + SAFE_FREE(pw_hist); + } else { + pdb_set_pw_history(sampass, NULL, 0, PDB_SET); + } + pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET); pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET); pdb_set_hours_len(sampass, hours_len, PDB_SET); @@ -1906,13 +1889,15 @@ done: SAFE_FREE(workstations); SAFE_FREE(munged_dial); SAFE_FREE(unknown_str); + SAFE_FREE(lm_pw_ptr); + SAFE_FREE(nt_pw_ptr); + SAFE_FREE(nt_pw_hist_ptr); SAFE_FREE(hours); return ret; } - -uint32 init_buffer_from_sam_v1 (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL size_only) +uint32 init_buffer_from_sam_v2 (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL size_only) { size_t len, buflen; @@ -1948,8 +1933,11 @@ uint32 init_buffer_from_sam_v1 (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL si const uint8 *lm_pw; const uint8 *nt_pw; + const uint8 *nt_pw_hist; uint32 lm_pw_len = 16; uint32 nt_pw_len = 16; + uint32 nt_pw_hist_len; + uint32 pwHistLen = 0; /* do we have a valid SAM_ACCOUNT pointer? */ if (sampass == NULL) { @@ -1972,180 +1960,206 @@ uint32 init_buffer_from_sam_v1 (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL si group_rid = pdb_get_group_rid(sampass); username = pdb_get_username(sampass); - if (username) + if (username) { username_len = strlen(username) +1; - else + } else { username_len = 0; + } domain = pdb_get_domain(sampass); - if (domain) + if (domain) { domain_len = strlen(domain) +1; - else + } else { domain_len = 0; + } nt_username = pdb_get_nt_username(sampass); - if (nt_username) + if (nt_username) { nt_username_len = strlen(nt_username) +1; - else + } else { nt_username_len = 0; + } fullname = pdb_get_fullname(sampass); - if (fullname) + if (fullname) { fullname_len = strlen(fullname) +1; - else + } else { fullname_len = 0; + } /* * Only updates fields which have been set (not defaults from smb.conf) */ - if (!IS_SAM_DEFAULT(sampass, PDB_DRIVE)) + if (!IS_SAM_DEFAULT(sampass, PDB_DRIVE)) { dir_drive = pdb_get_dir_drive(sampass); - else + } else { dir_drive = NULL; - if (dir_drive) + } + if (dir_drive) { dir_drive_len = strlen(dir_drive) +1; - else + } else { dir_drive_len = 0; + } - if (!IS_SAM_DEFAULT(sampass, PDB_SMBHOME)) + if (!IS_SAM_DEFAULT(sampass, PDB_SMBHOME)) { homedir = pdb_get_homedir(sampass); - else + } else { homedir = NULL; - if (homedir) + } + if (homedir) { homedir_len = strlen(homedir) +1; - else + } else { homedir_len = 0; + } - if (!IS_SAM_DEFAULT(sampass, PDB_LOGONSCRIPT)) + if (!IS_SAM_DEFAULT(sampass, PDB_LOGONSCRIPT)) { logon_script = pdb_get_logon_script(sampass); - else + } else { logon_script = NULL; - if (logon_script) + } + if (logon_script) { logon_script_len = strlen(logon_script) +1; - else + } else { logon_script_len = 0; + } - if (!IS_SAM_DEFAULT(sampass, PDB_PROFILE)) + if (!IS_SAM_DEFAULT(sampass, PDB_PROFILE)) { profile_path = pdb_get_profile_path(sampass); - else + } else { profile_path = NULL; - if (profile_path) + } + if (profile_path) { profile_path_len = strlen(profile_path) +1; - else + } else { profile_path_len = 0; + } lm_pw = pdb_get_lanman_passwd(sampass); - if (!lm_pw) + if (!lm_pw) { lm_pw_len = 0; + } nt_pw = pdb_get_nt_passwd(sampass); - if (!nt_pw) + if (!nt_pw) { nt_pw_len = 0; - + } + + account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen); + nt_pw_hist = pdb_get_pw_history(sampass, &nt_pw_hist_len); + if (pwHistLen && nt_pw_hist && nt_pw_hist_len) { + nt_pw_hist_len *= NT_HASH_LEN; + } else { + nt_pw_hist_len = 0; + } + acct_desc = pdb_get_acct_desc(sampass); - if (acct_desc) + if (acct_desc) { acct_desc_len = strlen(acct_desc) +1; - else + } else { acct_desc_len = 0; + } workstations = pdb_get_workstations(sampass); - if (workstations) + if (workstations) { workstations_len = strlen(workstations) +1; - else + } else { workstations_len = 0; + } unknown_str = NULL; unknown_str_len = 0; munged_dial = pdb_get_munged_dial(sampass); - if (munged_dial) + if (munged_dial) { munged_dial_len = strlen(munged_dial) +1; - else + } else { munged_dial_len = 0; - + } + +/* TDB_FORMAT_STRING_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd" */ + /* one time to get the size needed */ - len = tdb_pack(NULL, 0, TDB_FORMAT_STRING_V1, - logon_time, - logoff_time, - kickoff_time, - bad_password_time, - pass_last_set_time, - pass_can_change_time, - pass_must_change_time, - username_len, username, - domain_len, domain, - nt_username_len, nt_username, - fullname_len, fullname, - homedir_len, homedir, - dir_drive_len, dir_drive, - logon_script_len, logon_script, - profile_path_len, profile_path, - acct_desc_len, acct_desc, - workstations_len, workstations, - unknown_str_len, unknown_str, - munged_dial_len, munged_dial, - user_rid, - group_rid, - lm_pw_len, lm_pw, - nt_pw_len, nt_pw, - pdb_get_acct_ctrl(sampass), - 0, - pdb_get_logon_divs(sampass), - pdb_get_hours_len(sampass), - MAX_HOURS_LEN, pdb_get_hours(sampass), - pdb_get_bad_password_count(sampass), - pdb_get_logon_count(sampass), - pdb_get_unknown_6(sampass)); - - - if (size_only) + len = tdb_pack(NULL, 0, TDB_FORMAT_STRING_V2, + logon_time, /* d */ + logoff_time, /* d */ + kickoff_time, /* d */ + bad_password_time, /* d */ + pass_last_set_time, /* d */ + pass_can_change_time, /* d */ + pass_must_change_time, /* d */ + username_len, username, /* B */ + domain_len, domain, /* B */ + nt_username_len, nt_username, /* B */ + fullname_len, fullname, /* B */ + homedir_len, homedir, /* B */ + dir_drive_len, dir_drive, /* B */ + logon_script_len, logon_script, /* B */ + profile_path_len, profile_path, /* B */ + acct_desc_len, acct_desc, /* B */ + workstations_len, workstations, /* B */ + unknown_str_len, unknown_str, /* B */ + munged_dial_len, munged_dial, /* B */ + user_rid, /* d */ + group_rid, /* d */ + lm_pw_len, lm_pw, /* B */ + nt_pw_len, nt_pw, /* B */ + nt_pw_hist_len, nt_pw_hist, /* B */ + pdb_get_acct_ctrl(sampass), /* w */ + pdb_get_logon_divs(sampass), /* w */ + pdb_get_hours_len(sampass), /* d */ + MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */ + pdb_get_bad_password_count(sampass), /* w */ + pdb_get_logon_count(sampass), /* w */ + pdb_get_unknown_6(sampass)); /* d */ + + if (size_only) { return buflen; + } /* malloc the space needed */ if ( (*buf=(uint8*)malloc(len)) == NULL) { - DEBUG(0,("init_buffer_from_sam: Unable to malloc() memory for buffer!\n")); + DEBUG(0,("init_buffer_from_sam_v2: Unable to malloc() memory for buffer!\n")); return (-1); } /* now for the real call to tdb_pack() */ - buflen = tdb_pack((char *)*buf, len, TDB_FORMAT_STRING_V1, - logon_time, - logoff_time, - kickoff_time, - bad_password_time, - pass_last_set_time, - pass_can_change_time, - pass_must_change_time, - username_len, username, - domain_len, domain, - nt_username_len, nt_username, - fullname_len, fullname, - homedir_len, homedir, - dir_drive_len, dir_drive, - logon_script_len, logon_script, - profile_path_len, profile_path, - acct_desc_len, acct_desc, - workstations_len, workstations, - unknown_str_len, unknown_str, - munged_dial_len, munged_dial, - user_rid, - group_rid, - lm_pw_len, lm_pw, - nt_pw_len, nt_pw, - pdb_get_acct_ctrl(sampass), - 0, - pdb_get_logon_divs(sampass), - pdb_get_hours_len(sampass), - MAX_HOURS_LEN, pdb_get_hours(sampass), - pdb_get_bad_password_count(sampass), - pdb_get_logon_count(sampass), - pdb_get_unknown_6(sampass)); - + buflen = tdb_pack((char *)*buf, len, TDB_FORMAT_STRING_V2, + logon_time, /* d */ + logoff_time, /* d */ + kickoff_time, /* d */ + bad_password_time, /* d */ + pass_last_set_time, /* d */ + pass_can_change_time, /* d */ + pass_must_change_time, /* d */ + username_len, username, /* B */ + domain_len, domain, /* B */ + nt_username_len, nt_username, /* B */ + fullname_len, fullname, /* B */ + homedir_len, homedir, /* B */ + dir_drive_len, dir_drive, /* B */ + logon_script_len, logon_script, /* B */ + profile_path_len, profile_path, /* B */ + acct_desc_len, acct_desc, /* B */ + workstations_len, workstations, /* B */ + unknown_str_len, unknown_str, /* B */ + munged_dial_len, munged_dial, /* B */ + user_rid, /* d */ + group_rid, /* d */ + lm_pw_len, lm_pw, /* B */ + nt_pw_len, nt_pw, /* B */ + nt_pw_hist_len, nt_pw_hist, /* B */ + pdb_get_acct_ctrl(sampass), /* w */ + pdb_get_logon_divs(sampass), /* w */ + pdb_get_hours_len(sampass), /* d */ + MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */ + pdb_get_bad_password_count(sampass), /* w */ + pdb_get_logon_count(sampass), /* w */ + pdb_get_unknown_6(sampass)); /* d */ /* check to make sure we got it correct */ if (buflen != len) { - DEBUG(0, ("init_buffer_from_sam: somthing odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n", + DEBUG(0, ("init_buffer_from_sam_v2: somthing odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n", (unsigned long)buflen, (unsigned long)len)); /* error */ SAFE_FREE (*buf); @@ -2155,7 +2169,6 @@ uint32 init_buffer_from_sam_v1 (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL si return (buflen); } - /********************************************************************** **********************************************************************/ @@ -2236,7 +2249,9 @@ BOOL pdb_update_bad_password_count(SAM_ACCOUNT *sampass, BOOL *updated) if (time(NULL) > (LastBadPassword + (time_t)resettime*60)){ pdb_set_bad_password_count(sampass, 0, PDB_CHANGED); pdb_set_bad_password_time(sampass, 0, PDB_CHANGED); - if (updated) *updated = True; + if (updated) { + *updated = True; + } } return True; @@ -2254,7 +2269,8 @@ BOOL pdb_update_autolock_flag(SAM_ACCOUNT *sampass, BOOL *updated) if (!sampass) return False; if (!(pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK)) { - DEBUG(9, ("Account not autolocked, no check needed\n")); + DEBUG(9, ("pdb_update_autolock_flag: Account %s not autolocked, no check needed\n", + pdb_get_username(sampass))); return True; } @@ -2265,20 +2281,30 @@ BOOL pdb_update_autolock_flag(SAM_ACCOUNT *sampass, BOOL *updated) /* First, check if there is a duration to compare */ if ((duration == (uint32) -1) || (duration == 0)) { - DEBUG(9, ("No reset duration, can't reset autolock\n")); + DEBUG(9, ("pdb_update_autolock_flag: No reset duration, can't reset autolock\n")); return True; } LastBadPassword = pdb_get_bad_password_time(sampass); - DEBUG(7, ("LastBadPassword=%d, duration=%d, current time =%d.\n", - (uint32)LastBadPassword, duration*60, (uint32)time(NULL))); + DEBUG(7, ("pdb_update_autolock_flag: Account %s, LastBadPassword=%d, duration=%d, current time =%d.\n", + pdb_get_username(sampass), (uint32)LastBadPassword, duration*60, (uint32)time(NULL))); + + if (LastBadPassword == (time_t)0) { + DEBUG(1,("pdb_update_autolock_flag: Account %s administratively locked out with no \ +bad password time. Leaving locked out.\n", + pdb_get_username(sampass) )); + return True; + } + if ((time(NULL) > (LastBadPassword + (time_t) duration * 60))) { pdb_set_acct_ctrl(sampass, pdb_get_acct_ctrl(sampass) & ~ACB_AUTOLOCK, PDB_CHANGED); pdb_set_bad_password_count(sampass, 0, PDB_CHANGED); pdb_set_bad_password_time(sampass, 0, PDB_CHANGED); - if (updated) *updated = True; + if (updated) { + *updated = True; + } } return True; diff --git a/source/passdb/pdb_get_set.c b/source/passdb/pdb_get_set.c index e69dac524f0..dc8a2f68d21 100644 --- a/source/passdb/pdb_get_set.c +++ b/source/passdb/pdb_get_set.c @@ -150,6 +150,19 @@ const uint8* pdb_get_lanman_passwd (const SAM_ACCOUNT *sampass) return (NULL); } +const uint8* pdb_get_pw_history (const SAM_ACCOUNT *sampass, uint32 *current_hist_len) +{ + if (sampass) { + SMB_ASSERT((!sampass->private.nt_pw_his.data) + || ((sampass->private.nt_pw_his.length % NT_HASH_LEN) == 0)); + *current_hist_len = sampass->private.nt_pw_his.length / NT_HASH_LEN; + return ((uint8*)sampass->private.nt_pw_his.data); + } else { + *current_hist_len = 0; + return (NULL); + } +} + /* Return the plaintext password if known. Most of the time it isn't, so don't assume anything magic about this function. @@ -982,6 +995,30 @@ BOOL pdb_set_lanman_passwd (SAM_ACCOUNT *sampass, const uint8 pwd[LM_HASH_LEN], } /********************************************************************* + Set the user's password history hash. historyLen is the number of NT_HASH_LEN + entries to store in the history - this must match the size of the uint8 array + in pwd. +********************************************************************/ + +BOOL pdb_set_pw_history (SAM_ACCOUNT *sampass, const uint8 *pwd, uint32 historyLen, enum pdb_value_state flag) +{ + if (!sampass) + return False; + + if (historyLen && pwd){ + sampass->private.nt_pw_his = data_blob_talloc(sampass->mem_ctx, pwd, historyLen*NT_HASH_LEN); + if (!sampass->private.nt_pw_his.length) { + DEBUG(0, ("pdb_set_pw_history: data_blob_talloc() failed!\n")); + return False; + } + } else { + sampass->private.nt_pw_his = data_blob_talloc(sampass->mem_ctx, NULL, 0); + } + + return pdb_set_init_flags(sampass, PDB_PWHISTORY, flag); +} + +/********************************************************************* Set the user's plaintext password only (base procedure, see helper below) ********************************************************************/ @@ -1133,12 +1170,12 @@ BOOL pdb_set_pass_changed_now (SAM_ACCOUNT *sampass) BOOL pdb_set_plaintext_passwd (SAM_ACCOUNT *sampass, const char *plaintext) { - uchar new_lanman_p16[16]; - uchar new_nt_p16[16]; + uchar new_lanman_p16[LM_HASH_LEN]; + uchar new_nt_p16[NT_HASH_LEN]; if (!sampass || !plaintext) return False; - + /* Calculate the MD4 hash (NT compatible) of the password */ E_md4hash(plaintext, new_nt_p16); @@ -1164,6 +1201,47 @@ BOOL pdb_set_plaintext_passwd (SAM_ACCOUNT *sampass, const char *plaintext) if (!pdb_set_pass_changed_now (sampass)) return False; + /* Store the password history. */ + if (pdb_get_acct_ctrl(sampass) & ACB_NORMAL) { + uchar *pwhistory; + uint32 pwHistLen; + account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen); + if (pwHistLen != 0){ + uint32 current_history_len; + /* We need to make sure we don't have a race condition here - the + account policy history length can change between when the pw_history + was first loaded into the SAM_ACCOUNT struct and now.... JRA. */ + pwhistory = (uchar *)pdb_get_pw_history(sampass, ¤t_history_len); + + if (current_history_len != pwHistLen) { + /* After closing and reopening SAM_ACCOUNT the history + values will sync up. We can't do this here. */ + + /* current_history_len > pwHistLen is not a problem - we + have more history than we need. */ + + if (current_history_len < pwHistLen) { + /* We only have room for current_history_len entries. */ + pwHistLen = current_history_len; + } + } + if (pwhistory && pwHistLen){ + /* Make room for the new password in the history list. */ + if (pwHistLen > 1) { + memmove(&pwhistory[NT_HASH_LEN], pwhistory, (pwHistLen -1)*NT_HASH_LEN ); + } + /* Ensure we have a copy of the new password as the first history entry. */ + memcpy(pwhistory, new_nt_p16, NT_HASH_LEN); + pdb_set_pw_history(sampass, pwhistory, pwHistLen, PDB_CHANGED); + } else { + DEBUG (10,("pdb_get_set.c: pdb_set_plaintext_passwd: pwhistory was NULL!\n")); + } + } else { + /* Set the history length to zero. */ + pdb_set_pw_history(sampass, NULL, 0, PDB_CHANGED); + } + } + return True; } diff --git a/source/passdb/pdb_ldap.c b/source/passdb/pdb_ldap.c index d2ee9a2d9dc..fed92cea568 100644 --- a/source/passdb/pdb_ldap.c +++ b/source/passdb/pdb_ldap.c @@ -81,8 +81,6 @@ #define SAM_ACCOUNT struct sam_passwd #endif -#define MODIFY_TIMESTAMP_STRING "modifyTimestamp" - #include "smbldap.h" struct ldapsam_privates { @@ -301,7 +299,9 @@ static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state, really exist. */ for (attrib = attrs; *attrib != NULL; attrib++) { - if (StrCaseCmp(*attrib, name) == 0) { + if ((StrCaseCmp(*attrib, name) == 0) && + !(StrCaseCmp(*attrib, + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_MOD_TIMESTAMP)))) { DEBUG(10, ("ldapsam_delete_entry: deleting attribute %s\n", name)); smbldap_set_mod(&mods, LDAP_MOD_DELETE, name, NULL); } @@ -400,8 +400,9 @@ static time_t ldapsam_get_entry_timestamp( pstring temp; struct tm tm; - if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, - entry, MODIFY_TIMESTAMP_STRING, temp)) + if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, + get_userattr_key2string(ldap_state->schema_ver,LDAP_ATTR_MOD_TIMESTAMP), + temp)) return (time_t) 0; strptime(temp, "%Y%m%d%H%M%SZ", &tm); @@ -448,6 +449,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, uint8 hours[MAX_HOURS_LEN]; pstring temp; LOGIN_CACHE *cache_entry = NULL; + int pwHistLen; /* * do a little initialization @@ -694,6 +696,37 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, ZERO_STRUCT(smbntpwd); } + account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen); + if (pwHistLen > 0){ + uint8 *pwhist = NULL; + int i; + + if ((pwhist = malloc(NT_HASH_LEN * pwHistLen)) == NULL){ + DEBUG(0, ("init_sam_from_ldap: malloc failed!\n")); + return False; + } + memset(pwhist, '\0', NT_HASH_LEN * pwHistLen); + + if (!smbldap_get_single_pstring (ldap_state->smbldap_state->ldap_struct, entry, + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_HISTORY), temp)) { + /* leave as default - zeros */ + } else { + for (i = 0; i < pwHistLen; i++){ + if (!pdb_gethexpwd(&temp[i*32], smbntpwd)) { + break; + } + memset(&temp[i*32], '\0', 32); + memcpy(&pwhist[i*NT_HASH_LEN], smbntpwd, NT_HASH_LEN); + ZERO_STRUCT(smbntpwd); + } + } + if (!pdb_set_pw_history(sampass, pwhist, pwHistLen, PDB_SET)){ + SAFE_FREE(pwhist); + return False; + } + SAFE_FREE(pwhist); + } + if (!smbldap_get_single_pstring (ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ACB_INFO), temp)) { acct_ctrl |= ACB_NORMAL; @@ -781,7 +814,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, } /********************************************************************** - Initialize SAM_ACCOUNT from an LDAP query. + Initialize the ldap db from a SAM_ACCOUNT. Called on update. (Based on init_buffer_from_sam in pdb_tdb.c) *********************************************************************/ @@ -985,6 +1018,29 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, } } + if (need_update(sampass, PDB_PWHISTORY)) { + int pwHistLen = 0; + account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen); + if (pwHistLen == 0) { + /* Remove any password history from the LDAP store. */ + pstrcpy(temp, "00000000000000000000000000000000"); + } else { + int i, currHistLen = 0; + const uint8 *pwhist = pdb_get_pw_history(sampass, &currHistLen); + if (pwhist != NULL) { + /* We can only store (sizeof(pstring)-1)/32 password history entries. */ + pwHistLen = MIN(pwHistLen, ((sizeof(temp)-1)/32)); + for (i=0; i< pwHistLen && i < currHistLen; i++) { + pdb_sethexpwd (&temp[i*32], &pwhist[i*NT_HASH_LEN], 0); + DEBUG(100, ("temp=%s\n", temp)); + } + } + } + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_HISTORY), + temp); + } + if (need_update(sampass, PDB_PASSLASTSET)) { slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_last_set_time(sampass)); smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, @@ -1162,7 +1218,7 @@ static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT int rc; attr_list = get_userattr_list( ldap_state->schema_ver ); - append_attr(&attr_list, MODIFY_TIMESTAMP_STRING); + append_attr(&attr_list, get_userattr_key2string(ldap_state->schema_ver,LDAP_ATTR_MOD_TIMESTAMP)); rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result, attr_list); free_attr_list( attr_list ); @@ -1208,7 +1264,7 @@ static int ldapsam_get_ldap_user_by_sid(struct ldapsam_privates *ldap_state, switch ( ldap_state->schema_ver ) { case SCHEMAVER_SAMBASAMACCOUNT: attr_list = get_userattr_list(ldap_state->schema_ver); - append_attr(&attr_list, MODIFY_TIMESTAMP_STRING); + append_attr(&attr_list, get_userattr_key2string(ldap_state->schema_ver,LDAP_ATTR_MOD_TIMESTAMP)); rc = ldapsam_search_suffix_by_sid(ldap_state, sid, result, attr_list); free_attr_list( attr_list ); diff --git a/source/passdb/pdb_tdb.c b/source/passdb/pdb_tdb.c index 9bfb10c4009..5fb5ce38913 100644 --- a/source/passdb/pdb_tdb.c +++ b/source/passdb/pdb_tdb.c @@ -37,7 +37,7 @@ static int tdbsam_debug_level = DBGC_ALL; #endif -#define TDBSAM_VERSION 1 /* Most recent TDBSAM version */ +#define TDBSAM_VERSION 2 /* Most recent TDBSAM version */ #define TDBSAM_VERSION_STRING "INFO/version" #define PASSDB_FILE_NAME "passdb.tdb" #define USERPREFIX "USER_" @@ -125,6 +125,9 @@ static BOOL tdbsam_convert(TDB_CONTEXT *pdb_tdb, tdbsamver_t from) case 1: ret = init_sam_from_buffer_v1(user, (uint8 *)data.dptr, data.dsize); break; + case 2: + ret = init_sam_from_buffer_v2(user, (uint8 *)data.dptr, data.dsize); + break; default: /* unknown tdbsam version */ ret = False; @@ -135,6 +138,9 @@ static BOOL tdbsam_convert(TDB_CONTEXT *pdb_tdb, tdbsamver_t from) return False; } + /* We're finished with the old data. */ + SAFE_FREE(data.dptr); + /* pack from the buffer into the new format */ DEBUG(10,("tdbsam_convert: Try packing a record (key:%s) (version:%d)\n", key.dptr, from)); if ((data.dsize=init_buffer_from_sam (&buf, user, False)) == -1) { @@ -746,4 +752,3 @@ NTSTATUS pdb_tdbsam_init(void) { return smb_register_passdb(PASSDB_INTERFACE_VERSION, "tdbsam", pdb_init_tdbsam); } - diff --git a/source/passdb/secrets.c b/source/passdb/secrets.c index 2b3175bed23..e7637f689d2 100644 --- a/source/passdb/secrets.c +++ b/source/passdb/secrets.c @@ -30,10 +30,27 @@ static TDB_CONTEXT *tdb; +/** + * Use a TDB to store an incrementing random seed. + * + * Initialised to the current pid, the very first time Samba starts, + * and incremented by one each time it is needed. + * + * @note Not called by systems with a working /dev/urandom. + */ +static void get_rand_seed(int *new_seed) +{ + *new_seed = sys_getpid(); + if (tdb) { + tdb_change_int32_atomic(tdb, "INFO/random_seed", new_seed, 1); + } +} + /* open up the secrets database */ BOOL secrets_init(void) { pstring fname; + char dummy; if (tdb) return True; @@ -47,6 +64,18 @@ BOOL secrets_init(void) DEBUG(0,("Failed to open %s\n", fname)); return False; } + + /** + * Set a reseed function for the crypto random generator + * + * This avoids a problem where systems without /dev/urandom + * could send the same challenge to multiple clients + */ + set_rand_reseed_callback(get_rand_seed); + + /* Ensure that the reseed is done now, while we are root, etc */ + generate_random_buffer(&dummy, sizeof(dummy)); + return True; } @@ -504,37 +533,6 @@ BOOL trusted_domain_password_delete(const char *domain) } -/******************************************************************* - Reset the 'done' variables so after a client process is created - from a fork call these calls will be re-done. This should be - expanded if more variables need reseting. - ******************************************************************/ - -void reset_globals_after_fork(void) -{ - unsigned char dummy; - - secrets_init(); - - /* - * Increment the global seed value to ensure every smbd starts - * with a new random seed. - */ - - if (tdb) { - uint32 initial_val = sys_getpid(); - tdb_change_int32_atomic(tdb, "INFO/random_seed", (int *)&initial_val, 1); - set_rand_reseed_data((unsigned char *)&initial_val, sizeof(initial_val)); - } - - /* - * Re-seed the random crypto generator, so all smbd's - * started from the same parent won't generate the same - * sequence. - */ - generate_random_buffer( &dummy, 1, True); -} - BOOL secrets_store_ldap_pw(const char* dn, char* pw) { char *key = NULL; diff --git a/source/printing/printing.c b/source/printing/printing.c index 8beea9d0cec..10ca7e47e71 100644 --- a/source/printing/printing.c +++ b/source/printing/printing.c @@ -600,7 +600,6 @@ void pjob_delete(int snum, uint32 jobid) tdb_delete(pdb->tdb, print_key(jobid)); release_print_db(pdb); rap_jobid_delete(snum, jobid); - remove_from_jobs_changed( snum, jobid ); } /**************************************************************************** @@ -1685,8 +1684,6 @@ pause, or resume print job. User name: %s. Printer name: %s.", *errcode = map_werror_from_unix(errno); return False; } - - return True; } if (!print_job_delete1(snum, jobid)) { diff --git a/source/python/py_winbind.c b/source/python/py_winbind.c index 130f78d7e12..7256f77002b 100644 --- a/source/python/py_winbind.c +++ b/source/python/py_winbind.c @@ -432,7 +432,7 @@ static PyObject *py_auth_crap(PyObject *self, PyObject *args, PyObject *kw) return NULL; } - generate_random_buffer(request.data.auth_crap.chal, 8, False); + generate_random_buffer(request.data.auth_crap.chal, 8); if (use_lm_hash) { SMBencrypt((uchar *)password, request.data.auth_crap.chal, @@ -481,7 +481,7 @@ static PyObject *py_auth_smbd(PyObject *self, PyObject *args, PyObject *kw) return NULL; } - generate_random_buffer(request.data.smbd_auth_crap.chal, 8, False); + generate_random_buffer(request.data.smbd_auth_crap.chal, 8); if (use_lm_hash) { SMBencrypt((uchar *)password, diff --git a/source/rpc_client/cli_netlogon.c b/source/rpc_client/cli_netlogon.c index 02d2611d88c..3fb032234f5 100644 --- a/source/rpc_client/cli_netlogon.c +++ b/source/rpc_client/cli_netlogon.c @@ -247,7 +247,7 @@ NTSTATUS cli_nt_setup_creds(struct cli_state *cli, /******************* Request Challenge ********************/ - generate_random_buffer(clnt_chal.data, 8, False); + generate_random_buffer(clnt_chal.data, 8); /* send a client challenge; receive a server challenge */ result = cli_net_req_chal(cli, &clnt_chal, &srv_chal); @@ -580,7 +580,7 @@ NTSTATUS cli_netlogon_sam_logon(struct cli_state *cli, TALLOC_CTX *mem_ctx, unsigned char local_lm_response[24]; unsigned char local_nt_response[24]; - generate_random_buffer(chal, 8, False); + generate_random_buffer(chal, 8); SMBencrypt(password, chal, local_lm_response); SMBNTencrypt(password, chal, local_nt_response); diff --git a/source/rpc_client/cli_srvsvc.c b/source/rpc_client/cli_srvsvc.c index 555703cf4d8..68eb17074f6 100644 --- a/source/rpc_client/cli_srvsvc.c +++ b/source/rpc_client/cli_srvsvc.c @@ -181,6 +181,42 @@ WERROR cli_srvsvc_net_share_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx, init_unistr2(&info2->info_2_str.uni_passwd, s, UNI_STR_TERMINATE); } break; + /* adding info-level 502 here */ + case 502: + ctr->share.info502 = (SRV_SHARE_INFO_502 *)talloc( + mem_ctx, sizeof(SRV_SHARE_INFO_502) * ctr->num_entries); + + memset(ctr->share.info502, 0, sizeof(SRV_SHARE_INFO_502)); + + for (i = 0; i < ctr->num_entries; i++) { + SRV_SHARE_INFO_502 *info502 = &ctr->share.info502[i]; + char *s; + + /* Copy pointer crap */ + memcpy(&info502->info_502, &r.ctr.share.info502[i].info_502, + sizeof(SH_INFO_502)); + + /* Duplicate strings */ + + s = unistr2_tdup(mem_ctx, &r.ctr.share.info502[i].info_502_str.uni_netname); + if (s) + init_unistr2(&info502->info_502_str.uni_netname, s, UNI_STR_TERMINATE); + + s = unistr2_tdup(mem_ctx, &r.ctr.share.info502[i].info_502_str.uni_remark); + if (s) + init_unistr2(&info502->info_502_str.uni_remark, s, UNI_STR_TERMINATE); + + s = unistr2_tdup(mem_ctx, &r.ctr.share.info502[i].info_502_str.uni_path); + if (s) + init_unistr2(&info502->info_502_str.uni_path, s, UNI_STR_TERMINATE); + + s = unistr2_tdup(mem_ctx, &r.ctr.share.info502[i].info_502_str.uni_passwd); + if (s) + init_unistr2(&info502->info_502_str.uni_passwd, s, UNI_STR_TERMINATE); + + info502->info_502_str.sd = dup_sec_desc(mem_ctx, r.ctr.share.info502[i].info_502_str.sd); + } + break; } done: prs_mem_free(&qbuf); diff --git a/source/rpc_parse/parse_prs.c b/source/rpc_parse/parse_prs.c index 92c5b13632a..c70011c6484 100644 --- a/source/rpc_parse/parse_prs.c +++ b/source/rpc_parse/parse_prs.c @@ -1471,7 +1471,7 @@ void netsec_encode(struct netsec_auth_struct *a, int auth_flags, } /* fill the 'confounder' with random data */ - generate_random_buffer(confounder, sizeof(confounder), False); + generate_random_buffer(confounder, sizeof(confounder)); dump_data_pw("a->sess_key:\n", a->sess_key, sizeof(a->sess_key)); diff --git a/source/rpc_server/srv_netlog_nt.c b/source/rpc_server/srv_netlog_nt.c index 264b7a74a79..b5871a7e56d 100644 --- a/source/rpc_server/srv_netlog_nt.c +++ b/source/rpc_server/srv_netlog_nt.c @@ -276,7 +276,7 @@ NTSTATUS _net_req_chal(pipes_struct *p, NET_Q_REQ_CHAL *q_u, NET_R_REQ_CHAL *r_u /* create a server challenge for the client */ /* Set these to random values. */ - generate_random_buffer(p->dc.srv_chal.data, 8, False); + generate_random_buffer(p->dc.srv_chal.data, 8); memcpy(p->dc.srv_cred.challenge.data, p->dc.srv_chal.data, 8); diff --git a/source/rpc_server/srv_pipe.c b/source/rpc_server/srv_pipe.c index 36929150e54..bcf5eb533fd 100644 --- a/source/rpc_server/srv_pipe.c +++ b/source/rpc_server/srv_pipe.c @@ -52,28 +52,28 @@ struct dcinfo last_dcinfo; static void NTLMSSPcalc_p( pipes_struct *p, unsigned char *data, int len) { - unsigned char *hash = p->ntlmssp_hash; - unsigned char index_i = hash[256]; - unsigned char index_j = hash[257]; - int ind; + unsigned char *hash = p->ntlmssp_hash; + unsigned char index_i = hash[256]; + unsigned char index_j = hash[257]; + int ind; - for( ind = 0; ind < len; ind++) { - unsigned char tc; - unsigned char t; + for( ind = 0; ind < len; ind++) { + unsigned char tc; + unsigned char t; - index_i++; - index_j += hash[index_i]; + index_i++; + index_j += hash[index_i]; - tc = hash[index_i]; - hash[index_i] = hash[index_j]; - hash[index_j] = tc; + tc = hash[index_i]; + hash[index_i] = hash[index_j]; + hash[index_j] = tc; - t = hash[index_i] + hash[index_j]; - data[ind] = data[ind] ^ hash[t]; - } + t = hash[index_i] + hash[index_j]; + data[ind] = data[ind] ^ hash[t]; + } - hash[256] = index_i; - hash[257] = index_j; + hash[256] = index_i; + hash[257] = index_j; } /******************************************************************* @@ -501,6 +501,9 @@ succeeded authentication on named pipe %s, but session key was of incorrect leng * Store the UNIX credential data (uid/gid pair) in the pipe structure. */ + if (p->session_key.data) { + data_blob_free(&p->session_key); + } p->session_key = data_blob(server_info->lm_session_key.data, server_info->lm_session_key.length); p->pipe_user.uid = server_info->uid; @@ -1094,7 +1097,7 @@ BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) RPC_AUTH_VERIFIER auth_verifier; RPC_AUTH_NTLMSSP_CHAL ntlmssp_chal; - generate_random_buffer(p->challenge, 8, False); + generate_random_buffer(p->challenge, 8); /*** Authentication info ***/ diff --git a/source/rpc_server/srv_pipe_hnd.c b/source/rpc_server/srv_pipe_hnd.c index 7f7a3025a90..562b55b8f76 100644 --- a/source/rpc_server/srv_pipe_hnd.c +++ b/source/rpc_server/srv_pipe_hnd.c @@ -1092,6 +1092,22 @@ BOOL close_rpc_pipe_hnd(smb_np_struct *p) } /**************************************************************************** + Close all pipes on a connection. +****************************************************************************/ + +void pipe_close_conn(connection_struct *conn) +{ + smb_np_struct *p, *next; + + for (p=Pipes;p;p=next) { + next = p->next; + if (p->conn == conn) { + close_rpc_pipe_hnd(p); + } + } +} + +/**************************************************************************** Close an rpc pipe. ****************************************************************************/ @@ -1114,9 +1130,6 @@ static BOOL close_internal_rpc_pipe_hnd(void *np_conn) /* Free the handles database. */ close_policy_by_pipe(p); - if (p->session_key.data != NULL) - data_blob_free(&p->session_key); - delete_nt_token(&p->pipe_user.nt_user_token); data_blob_free(&p->session_key); SAFE_FREE(p->pipe_user.groups); diff --git a/source/rpc_server/srv_spoolss_nt.c b/source/rpc_server/srv_spoolss_nt.c index 06ba5435976..e3c9ff08d93 100644 --- a/source/rpc_server/srv_spoolss_nt.c +++ b/source/rpc_server/srv_spoolss_nt.c @@ -671,7 +671,11 @@ static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type, * might use the flags though instead of the NOTIFY_OPTION_INFO * --jerry */ - + + if (!option) { + return False; + } + if (p->notify.flags) return is_monitoring_event_flags( p->notify.flags, notify_type, notify_field); @@ -3725,6 +3729,12 @@ static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd, info->data=NULL; info->count=0; + /* a bug in xp sp2 rc2 causes it to send a fnpcn request without + sending a ffpcn() request first */ + + if ( !option ) + return WERR_BADFID; + for (i=0; icount; i++) { option_type=&(option->ctr.type[i]); @@ -3787,6 +3797,12 @@ static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY info->data=NULL; info->count=0; + /* a bug in xp sp2 rc2 causes it to send a fnpcn request without + sending a ffpcn() request first */ + + if ( !option ) + return WERR_BADFID; + get_printer_snum(p, hnd, &snum); for (i=0; icount; i++) { diff --git a/source/rpcclient/cmd_netlogon.c b/source/rpcclient/cmd_netlogon.c index 9e281fefce4..b55306ddc88 100644 --- a/source/rpcclient/cmd_netlogon.c +++ b/source/rpcclient/cmd_netlogon.c @@ -266,10 +266,10 @@ static NTSTATUS cmd_netlogon_sam_logon(struct cli_state *cli, username = argv[1]; password = argv[2]; - if (argc == 4) + if (argc >= 4) sscanf(argv[3], "%i", &logon_type); - if (argc == 5) + if (argc >= 5) sscanf(argv[4], "%i", &neg_flags); if (argc == 6) @@ -283,10 +283,6 @@ static NTSTATUS cmd_netlogon_sam_logon(struct cli_state *cli, clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &ret_creds); - result = cli_netlogon_sam_logon(cli, mem_ctx, &ret_creds, username, password, logon_type); - - clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &ret_creds); - if (!NT_STATUS_IS_OK(result)) goto done; @@ -339,7 +335,7 @@ struct cmd_set netlogon_commands[] = { { "samsync", RPC_RTYPE_NTSTATUS, cmd_netlogon_sam_sync, NULL, PI_NETLOGON, "Sam Synchronisation", "" }, { "samdeltas", RPC_RTYPE_NTSTATUS, cmd_netlogon_sam_deltas, NULL, PI_NETLOGON, "Query Sam Deltas", "" }, { "samlogon", RPC_RTYPE_NTSTATUS, cmd_netlogon_sam_logon, NULL, PI_NETLOGON, "Sam Logon", "" }, - { "samlogon", RPC_RTYPE_NTSTATUS, cmd_netlogon_change_trust_pw, NULL, PI_NETLOGON, "Change Trust Account Password", "" }, + { "change_trust_pw", RPC_RTYPE_NTSTATUS, cmd_netlogon_change_trust_pw, NULL, PI_NETLOGON, "Change Trust Account Password", "" }, { NULL } }; diff --git a/source/rpcclient/cmd_srvsvc.c b/source/rpcclient/cmd_srvsvc.c index 3e569f51cea..6e295a50fa9 100644 --- a/source/rpcclient/cmd_srvsvc.c +++ b/source/rpcclient/cmd_srvsvc.c @@ -246,6 +246,25 @@ static void display_share_info_2(SRV_SHARE_INFO_2 *info2) printf("\tpassword:\t%s\n", passwd); } +static void display_share_info_502(SRV_SHARE_INFO_502 *info502) +{ + fstring netname = "", remark = "", path = "", passwd = ""; + + rpcstr_pull_unistr2_fstring(netname, &info502->info_502_str.uni_netname); + rpcstr_pull_unistr2_fstring(remark, &info502->info_502_str.uni_remark); + rpcstr_pull_unistr2_fstring(path, &info502->info_502_str.uni_path); + rpcstr_pull_unistr2_fstring(passwd, &info502->info_502_str.uni_passwd); + + printf("netname: %s\n", netname); + printf("\tremark:\t%s\n", remark); + printf("\tpath:\t%s\n", path); + printf("\tpassword:\t%s\n", passwd); + + if (info502->info_502_str.sd) + display_sec_desc(info502->info_502_str.sd); + +} + static WERROR cmd_srvsvc_net_share_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) @@ -283,6 +302,10 @@ static WERROR cmd_srvsvc_net_share_enum(struct cli_state *cli, for (i = 0; i < ctr.num_entries; i++) display_share_info_2(&ctr.share.info2[i]); break; + case 502: + for (i = 0; i < ctr.num_entries; i++) + display_share_info_502(&ctr.share.info502[i]); + break; default: printf("unsupported info level %d\n", info_level); break; diff --git a/source/sam/idmap.c b/source/sam/idmap.c index bbb4980c766..d541776f391 100644 --- a/source/sam/idmap.c +++ b/source/sam/idmap.c @@ -96,7 +96,7 @@ NTSTATUS smb_register_idmap(int version, const char *name, struct idmap_methods Initialise idmap cache and a remote backend (if configured). **********************************************************************/ -BOOL idmap_init(const char *remote_backend) +BOOL idmap_init(const char **remote_backend) { if (!backends) static_init_idmap; @@ -115,8 +115,9 @@ BOOL idmap_init(const char *remote_backend) } } - if (!remote_map && remote_backend && *remote_backend != 0) { - char *rem_backend = smb_xstrdup(remote_backend); + if ((remote_map == NULL) && (remote_backend != NULL) && + (*remote_backend != NULL) && (**remote_backend != '\0')) { + char *rem_backend = smb_xstrdup(*remote_backend); fstring params = ""; char *pparams; diff --git a/source/script/installswat.sh b/source/script/installswat.sh index 67586a89674..9e3ab689b4d 100755 --- a/source/script/installswat.sh +++ b/source/script/installswat.sh @@ -75,7 +75,7 @@ done if [ -d $SRCDIR../docs/htmldocs/ ]; then - for dir in htmldocs/ htmldocs/howto htmldocs/guide htmldocs/devel + for dir in htmldocs/ htmldocs/Samba-HOWTO-Collection htmldocs/Samba-Guide htmldocs/Samba-Developers-Guide do if [ ! -d $SRCDIR../docs/$dir ]; then diff --git a/source/smbd/chgpasswd.c b/source/smbd/chgpasswd.c index ca13a167fb0..a1b90c8fed4 100644 --- a/source/smbd/chgpasswd.c +++ b/source/smbd/chgpasswd.c @@ -933,6 +933,65 @@ static NTSTATUS check_oem_password(const char *user, } /*********************************************************** + This routine takes the given password and checks it against + the password history. Returns True if this password has been + found in the history list. +************************************************************/ + +static BOOL check_passwd_history(SAM_ACCOUNT *sampass, const char *plaintext) +{ + uchar new_nt_p16[NT_HASH_LEN]; + uchar zero_nt_pw[NT_HASH_LEN]; + const uint8 *nt_pw; + const uint8 *pwhistory; + BOOL found = False; + int i, pwHisLen, curr_pwHisLen; + + account_policy_get(AP_PASSWORD_HISTORY, &pwHisLen); + if (pwHisLen == 0) { + return False; + } + + pwhistory = pdb_get_pw_history(sampass, &curr_pwHisLen); + if (!pwhistory || curr_pwHisLen == 0) { + return False; + } + + /* Only examine the minimum of the current history len and + the stored history len. Avoids race conditions. */ + pwHisLen = MIN(pwHisLen,curr_pwHisLen); + + nt_pw = pdb_get_nt_passwd(sampass); + + E_md4hash(plaintext, new_nt_p16); + + if (!memcmp(nt_pw, new_nt_p16, NT_HASH_LEN)) { + DEBUG(10,("check_passwd_history: proposed new password for user %s is the same as the current password !\n", + pdb_get_username(sampass) )); + return True; + } + + dump_data(100, new_nt_p16, NT_HASH_LEN); + dump_data(100, pwhistory, NT_HASH_LEN*pwHisLen); + + memset(zero_nt_pw, '\0', NT_HASH_LEN); + for (i=0; icheck_cache(s); + return mangle_fns->check_cache(s, maxlen); } /* diff --git a/source/smbd/mangle_hash.c b/source/smbd/mangle_hash.c index d7239b82a79..13ec99a917f 100644 --- a/source/smbd/mangle_hash.c +++ b/source/smbd/mangle_hash.c @@ -557,7 +557,7 @@ static void cache_mangled_name( char *mangled_name, char *raw_name ) * Check for a name on the mangled name stack * * Input: s - Input *and* output string buffer. - * + * maxlen - space in i/o string buffer. * Output: True if the name was found in the cache, else False. * * Notes: If a reverse map is found, the function will overwrite the string @@ -568,7 +568,7 @@ static void cache_mangled_name( char *mangled_name, char *raw_name ) * ************************************************************************** ** */ -static BOOL check_cache( char *s ) +static BOOL check_cache( char *s, size_t maxlen ) { ubi_cacheEntryPtr FoundPtr; char *ext_start = NULL; @@ -602,7 +602,7 @@ static BOOL check_cache( char *s ) if( !FoundPtr ) { if(saved_ext) { /* Replace the saved_ext as it was truncated. */ - (void)pstrcat( s, saved_ext ); + (void)safe_strcat( s, saved_ext, maxlen ); SAFE_FREE(saved_ext); } return( False ); @@ -612,10 +612,10 @@ static BOOL check_cache( char *s ) found_name = (char *)(FoundPtr + 1); found_name += (strlen( found_name ) + 1); - (void)pstrcpy( s, found_name ); + (void)safe_strcpy( s, found_name, maxlen ); if( saved_ext ) { /* Replace the saved_ext as it was truncated. */ - (void)pstrcat( s, saved_ext ); + (void)safe_strcat( s, saved_ext, maxlen ); SAFE_FREE(saved_ext); } diff --git a/source/smbd/mangle_hash2.c b/source/smbd/mangle_hash2.c index dcfd7663ba3..f68873687bd 100644 --- a/source/smbd/mangle_hash2.c +++ b/source/smbd/mangle_hash2.c @@ -362,10 +362,8 @@ static void mangle_reset(void) /* try to find a 8.3 name in the cache, and if found then replace the string with the original long name. - - The filename must be able to hold at least sizeof(fstring) */ -static BOOL check_cache(char *name) +static BOOL check_cache(char *name, size_t maxlen) { u32 hash, multiplier; unsigned int i; @@ -403,10 +401,10 @@ static BOOL check_cache(char *name) if (extension[0]) { M_DEBUG(10,("check_cache: %s -> %s.%s\n", name, prefix, extension)); - slprintf(name, sizeof(fstring), "%s.%s", prefix, extension); + slprintf(name, maxlen, "%s.%s", prefix, extension); } else { M_DEBUG(10,("check_cache: %s -> %s\n", name, prefix)); - fstrcpy(name, prefix); + safe_strcpy(name, prefix, maxlen); } return True; diff --git a/source/smbd/password.c b/source/smbd/password.c index b2dbde151d0..3be1516cf04 100644 --- a/source/smbd/password.c +++ b/source/smbd/password.c @@ -253,19 +253,23 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key, /* Register a home dir service for this user iff (a) This is not a guest connection, - (b) we have a home directory defined, and - (c) there s not an existing static share by that name */ - - if ( (!vuser->guest) - && vuser->unix_homedir - && *(vuser->unix_homedir) - && (lp_servicenumber(vuser->user.unix_name) == -1) ) - { - DEBUG(3, ("Adding/updating homes service for user '%s' using home directory: '%s'\n", + (b) we have a home directory defined + If a share exists by this name (autoloaded or not) reuse it so + long as the home directory is the same as the share directory. */ + + if ( (!vuser->guest) && vuser->unix_homedir && *(vuser->unix_homedir)) { + int servicenumber = lp_servicenumber(vuser->user.unix_name); + if ( servicenumber == -1 ) { + DEBUG(3, ("Adding homes service for user '%s' using home directory: '%s'\n", vuser->user.unix_name, vuser->unix_homedir)); - vuser->homes_snum = add_home_service(vuser->user.unix_name, - vuser->user.unix_name, vuser->unix_homedir); + vuser->user.unix_name, vuser->unix_homedir); + } else if (strcmp(lp_pathname(servicenumber),vuser->unix_homedir) == 0) { + DEBUG(3, ("Reusing homes service for user '%s' using home directory: '%s'\n", + vuser->user.unix_name, vuser->unix_homedir)); + + vuser->homes_snum = servicenumber; + } } else { vuser->homes_snum = -1; } diff --git a/source/smbd/reply.c b/source/smbd/reply.c index 71efb793af0..f3ab709df48 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -1583,7 +1583,7 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) */ if (!rc && mangle_is_mangled(mask)) - mangle_check_cache( mask ); + mangle_check_cache( mask, sizeof(pstring)-1 ); if (!has_wild) { pstrcat(directory,"/"); @@ -3738,7 +3738,7 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, ui */ if (!rc && mangle_is_mangled(mask)) - mangle_check_cache( mask ); + mangle_check_cache( mask, sizeof(pstring)-1 ); has_wild = ms_has_wild(mask); @@ -4216,7 +4216,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, */ if (!rc && mangle_is_mangled(mask)) - mangle_check_cache( mask ); + mangle_check_cache( mask, sizeof(pstring)-1 ); has_wild = ms_has_wild(mask); diff --git a/source/smbd/server.c b/source/smbd/server.c index c3e0da542e2..16281dd86cb 100644 --- a/source/smbd/server.c +++ b/source/smbd/server.c @@ -409,11 +409,12 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ in smbstatus for port 445 connects */ set_remote_machine_name(get_peer_addr(smbd_server_fd()), False); - /* Reset global variables in util.c so - that client substitutions will be - done correctly in the process. */ - reset_globals_after_fork(); + /* Reset the state of the random + * number generation system, so + * children do not get the same random + * numbers as each other */ + set_need_random_reseed(); /* tdb needs special fork handling - remove CLEAR_IF_FIRST flags */ if (tdb_reopen_all() == -1) { DEBUG(0,("tdb_reopen_all failed.\n")); @@ -717,7 +718,7 @@ void build_options(BOOL screen); /* we want to re-seed early to prevent time delays causing client problems at a later date. (tridge) */ - generate_random_buffer(NULL, 0, False); + generate_random_buffer(NULL, 0); /* make absolutely sure we run as root - to handle cases where people are crazy enough to have it setuid */ diff --git a/source/smbd/service.c b/source/smbd/service.c index 3b499d5cc1d..794b5332ac5 100644 --- a/source/smbd/service.c +++ b/source/smbd/service.c @@ -823,8 +823,12 @@ void close_cnum(connection_struct *conn, uint16 vuid) { DirCacheFlush(SNUM(conn)); - file_close_conn(conn); - dptr_closecnum(conn); + if (IS_IPC(conn)) { + pipe_close_conn(conn); + } else { + file_close_conn(conn); + dptr_closecnum(conn); + } change_to_root_user(); diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c index a7db9daf7d6..f3176940c2f 100644 --- a/source/smbd/trans2.c +++ b/source/smbd/trans2.c @@ -3358,16 +3358,15 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", * a new info level should be used for mknod. JRA. */ -#if !defined(HAVE_MAKEDEV_FN) - return(ERROR_DOS(ERRDOS,ERRnoaccess)); -#else /* HAVE_MAKEDEV_FN */ uint32 file_type = IVAL(pdata,0); +#if defined(HAVE_MAKEDEV) uint32 dev_major = IVAL(pdata,4); uint32 dev_minor = IVAL(pdata,12); +#endif uid_t myuid = geteuid(); gid_t mygid = getegid(); - SMB_DEV_T dev; + SMB_DEV_T dev = (SMB_DEV_T)0; if (tran_call == TRANSACT2_SETFILEINFO) return(ERROR_DOS(ERRDOS,ERRnoaccess)); @@ -3375,7 +3374,9 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", if (raw_unixmode == SMB_MODE_NO_CHANGE) return(ERROR_DOS(ERRDOS,ERRinvalidparam)); +#if defined(HAVE_MAKEDEV) dev = makedev(dev_major, dev_minor); +#endif /* We can only create as the owner/group we are. */ @@ -3384,10 +3385,30 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE)) return(ERROR_DOS(ERRDOS,ERRnoaccess)); - if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV && - file_type != UNIX_TYPE_FIFO && - file_type != UNIX_TYPE_SOCKET) - return(ERROR_DOS(ERRDOS,ERRnoaccess)); + switch (file_type) { +#if defined(S_IFIFO) + case UNIX_TYPE_FIFO: + unixmode |= S_IFIFO; + break; +#endif +#if defined(S_IFSOCK) + case UNIX_TYPE_SOCKET: + unixmode |= S_IFSOCK; + break; +#endif +#if defined(S_IFCHR) + case UNIX_TYPE_CHARDEV: + unixmode |= S_IFCHR; + break; +#endif +#if defined(S_IFBLK) + case UNIX_TYPE_BLKDEV: + unixmode |= S_IFBLK; + break; +#endif + default: + return(ERROR_DOS(ERRDOS,ERRnoaccess)); + } DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \ 0%o for file %s\n", (double)dev, unixmode, fname )); @@ -3401,8 +3422,6 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", SSVAL(params,0,0); send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); return(-1); -#endif /* HAVE_MAKEDEV_FN */ - } /* diff --git a/source/torture/mangle_test.c b/source/torture/mangle_test.c index f31621b23b7..5acad2d015d 100644 --- a/source/torture/mangle_test.c +++ b/source/torture/mangle_test.c @@ -150,6 +150,10 @@ static void gen_name(char *name) s[4] = 0; } } + + /* ..... and a 100% proability of a file not ending in "." */ + if (p[strlen(p)-1] == '.') + p[strlen(p)-1] = '_'; } diff --git a/source/torture/torture.c b/source/torture/torture.c index e3960d34061..6c3860e233e 100644 --- a/source/torture/torture.c +++ b/source/torture/torture.c @@ -493,7 +493,7 @@ static BOOL rw_torture2(struct cli_state *c1, struct cli_state *c2) printf("%d\r", i); fflush(stdout); } - generate_random_buffer(buf, buf_size, False); + generate_random_buffer(buf, buf_size); if (cli_write(c1, fnum1, 0, buf, 0, buf_size) != buf_size) { printf("write failed (%s)\n", cli_errstr(c1)); diff --git a/source/utils/ntlm_auth.c b/source/utils/ntlm_auth.c index 39dcd9993d0..4d369630ab3 100644 --- a/source/utils/ntlm_auth.c +++ b/source/utils/ntlm_auth.c @@ -181,7 +181,7 @@ DATA_BLOB get_challenge(void) chal = data_blob(NULL, 8); - generate_random_buffer(chal.data, chal.length, False); + generate_random_buffer(chal.data, chal.length); return chal; } @@ -1557,7 +1557,7 @@ static void manage_ntlm_server_1_request(enum stdio_helper_mode stdio_helper_mod if (nt_response.length < 24) { x_fprintf(x_stdout, "Error: hex decode of %s failed! (only got %d bytes, needed at least 24)\n.\n", parameter, - (int)opt_nt_response.length); + (int)nt_response.length); nt_response = data_blob(NULL, 0); } } else if (strequal(request, "LANMAN-Response")) { diff --git a/source/utils/pdbedit.c b/source/utils/pdbedit.c index 3f7aba83668..1201cf88fcf 100644 --- a/source/utils/pdbedit.c +++ b/source/utils/pdbedit.c @@ -57,9 +57,12 @@ Add all currently available users to another db ********************************************************/ -static int export_database (struct pdb_context *in, struct pdb_context *out) { +static int export_database (struct pdb_context *in, struct pdb_context + *out, const char *username) { SAM_ACCOUNT *user = NULL; + DEBUG(3, ("called with username=\"%s\"\n", username)); + if (NT_STATUS_IS_ERR(in->pdb_setsampwent(in, 0))) { fprintf(stderr, "Can't sampwent!\n"); return 1; @@ -71,10 +74,17 @@ static int export_database (struct pdb_context *in, struct pdb_context *out) { } while (NT_STATUS_IS_OK(in->pdb_getsampwent(in, user))) { - out->pdb_add_sam_account(out, user); - if (!NT_STATUS_IS_OK(pdb_reset_sam(user))){ - fprintf(stderr, "Can't reset SAM_ACCOUNT!\n"); - return 1; + DEBUG(4, ("Processing account %s\n", + user->private.username)); + if (!username || + (strcmp(username, user->private.username) + == 0)) { + out->pdb_add_sam_account(out, user); + if (!NT_STATUS_IS_OK(pdb_reset_sam(user))) { + fprintf(stderr, + "Can't reset SAM_ACCOUNT!\n"); + return 1; + } } } @@ -192,7 +202,6 @@ static int print_user_info (struct pdb_context *in, const char *username, BOOL v { SAM_ACCOUNT *sam_pwent=NULL; BOOL ret; - BOOL updated_autolock = False, updated_badpw = False; if (!NT_STATUS_IS_OK(pdb_init_sam (&sam_pwent))) { return -1; @@ -206,19 +215,6 @@ static int print_user_info (struct pdb_context *in, const char *username, BOOL v return -1; } - if (!pdb_update_autolock_flag(sam_pwent, &updated_autolock)) - DEBUG(2,("pdb_update_autolock_flag failed.\n")); - - if (!pdb_update_bad_password_count(sam_pwent, &updated_badpw)) - DEBUG(2,("pdb_update_bad_password_count failed.\n")); - - if (updated_autolock || updated_badpw) { - become_root(); - if(!pdb_update_sam_account(sam_pwent)) - DEBUG(1, ("Failed to modify entry.\n")); - unbecome_root(); - } - ret=print_sam_info (sam_pwent, verbosity, smbpwdstyle); pdb_free_sam(&sam_pwent); @@ -300,6 +296,7 @@ static int set_user_info (struct pdb_context *in, const char *username, const char *user_sid, const char *group_sid, const BOOL badpw) { + BOOL updated_autolock = False, updated_badpw = False; SAM_ACCOUNT *sam_pwent=NULL; BOOL ret; @@ -312,6 +309,14 @@ static int set_user_info (struct pdb_context *in, const char *username, return -1; } + if (!pdb_update_autolock_flag(sam_pwent, &updated_autolock)) { + DEBUG(2,("pdb_update_autolock_flag failed.\n")); + } + + if (!pdb_update_bad_password_count(sam_pwent, &updated_badpw)) { + DEBUG(2,("pdb_update_bad_password_count failed.\n")); + } + if (fullname) pdb_set_fullname(sam_pwent, fullname, PDB_CHANGED); if (homedir) @@ -374,7 +379,7 @@ static int set_user_info (struct pdb_context *in, const char *username, pdb_set_bad_password_count(sam_pwent, 0, PDB_CHANGED); pdb_set_bad_password_time(sam_pwent, 0, PDB_CHANGED); } - + if (NT_STATUS_IS_OK(in->pdb_update_sam_account (in, sam_pwent))) print_user_info (in, username, True, False); else { @@ -736,7 +741,12 @@ int main (int argc, char **argv) uint32 value; int field = account_policy_name_to_fieldnum(account_policy); if (field == 0) { + char *apn = account_policy_names_list(); fprintf(stderr, "No account policy by that name\n"); + if (apn) { + fprintf(stderr, "Account policy names are :\n%s\n", apn); + } + SAFE_FREE(apn); exit(1); } if (!account_policy_get(field, &value)) { @@ -759,7 +769,7 @@ int main (int argc, char **argv) /* import and export operations */ if (((checkparms & BIT_IMPORT) || (checkparms & BIT_EXPORT)) - && !(checkparms & ~(BIT_IMPORT +BIT_EXPORT))) { + && !(checkparms & ~(BIT_IMPORT +BIT_EXPORT +BIT_USER))) { if (backend_in) { if (!NT_STATUS_IS_OK(make_pdb_context_string(&bin, backend_in))) { fprintf(stderr, "Can't initialize passdb backend.\n"); @@ -777,9 +787,15 @@ int main (int argc, char **argv) bout = bdef; } if (transfer_groups) { - return export_groups(bin, bout); + if (!(checkparms & BIT_USER)) + return export_groups(bin, bout); } else { - return export_database(bin, bout); + if (checkparms & BIT_USER) + return export_database(bin, bout, + user_name); + else + return export_database(bin, bout, + NULL); } } diff --git a/source/utils/smbpasswd.c b/source/utils/smbpasswd.c index 0476a2e39c0..74480f5fc53 100644 --- a/source/utils/smbpasswd.c +++ b/source/utils/smbpasswd.c @@ -29,9 +29,9 @@ extern char *optarg; extern int optind; /* forced running in root-mode */ -static BOOL got_pass = False, got_username = False; +static BOOL got_username = False; static BOOL stdin_passwd_get = False; -static fstring user_name, user_password; +static fstring user_name; static char *new_passwd = NULL; static const char *remote_machine = NULL; @@ -44,9 +44,9 @@ static fstring ldap_secret; static void usage(void) { printf("When run by root:\n"); - printf(" smbpasswd [options] [username] [password]\n"); + printf(" smbpasswd [options] [username]\n"); printf("otherwise:\n"); - printf(" smbpasswd [options] [password]\n\n"); + printf(" smbpasswd [options]\n\n"); printf("options:\n"); printf(" -L local mode (must be first option)\n"); @@ -79,6 +79,7 @@ static void set_line_buffering(FILE *f) /******************************************************************* Process command line options ******************************************************************/ + static int process_options(int argc, char **argv, int local_flags) { int ch; @@ -88,7 +89,6 @@ static int process_options(int argc, char **argv, int local_flags) local_flags |= LOCAL_SET_PASSWORD; ZERO_STRUCT(user_name); - ZERO_STRUCT(user_password); user_name[0] = '\0'; @@ -150,19 +150,8 @@ static int process_options(int argc, char **argv, int local_flags) DEBUGLEVEL = atoi(optarg); break; case 'U': { - char *lp; - got_username = True; fstrcpy(user_name, optarg); - - if ((lp = strchr(user_name, '%'))) { - *lp = 0; - fstrcpy(user_password, lp + 1); - got_pass = True; - memset(strchr_m(optarg, '%') + 1, 'X', - strlen(user_password)); - } - break; } case 'h': @@ -181,7 +170,7 @@ static int process_options(int argc, char **argv, int local_flags) break; case 1: if (!(local_flags & LOCAL_AM_ROOT)) { - new_passwd = argv[0]; + usage(); } else { if (got_username) { usage(); @@ -190,14 +179,6 @@ static int process_options(int argc, char **argv, int local_flags) } } break; - case 2: - if (!(local_flags & LOCAL_AM_ROOT) || got_username || got_pass) { - usage(); - } - - fstrcpy(user_name, argv[0]); - new_passwd = smb_xstrdup(argv[1]); - break; default: usage(); } diff --git a/source/wrepld/server.c b/source/wrepld/server.c index 80694a616bb..d78e0b206f3 100644 --- a/source/wrepld/server.c +++ b/source/wrepld/server.c @@ -551,7 +551,7 @@ static void process(void) /* we want to re-seed early to prevent time delays causing client problems at a later date. (tridge) */ - generate_random_buffer(NULL, 0, False); + generate_random_buffer(NULL, 0); /* make absolutely sure we run as root - to handle cases where people are crazy enough to have it setuid */ -- 2.11.4.GIT