From 94fc44a93c46cece9b9fa947bff62087dbcd89fa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 12 Feb 2001 16:18:02 +0000 Subject: Merge of JohnR's changes to appliance-head, JF's changes to 2.2, updated the POSIX_ACL code to be in sync. Jeremy. (This used to be commit c0517d6f4e3079feca1309fd1ea7b21e83f0de02) --- source3/include/debug.h | 132 +++++++++++++++++++++++++++++++------- source3/include/proto.h | 7 +- source3/lib/debug.c | 128 ++++++++++++++++++++++++++++++++++-- source3/lib/messages.c | 3 +- source3/lib/msrpc_use.c | 4 +- source3/param/loadparm.c | 23 ++++++- source3/printing/nt_printing.c | 15 ++++- source3/rpc_parse/parse_spoolss.c | 21 +++--- source3/smbd/nttrans.c | 11 +++- source3/smbd/posix_acls.c | 2 + source3/smbd/process.c | 29 ++++++++- source3/smbd/reply.c | 10 +-- source3/smbd/server.c | 17 +++++ source3/utils/smbcontrol.c | 51 +++++++++------ 14 files changed, 378 insertions(+), 75 deletions(-) (limited to 'source3') diff --git a/source3/include/debug.h b/source3/include/debug.h index 3130bc379d..d2c3b1d37e 100644 --- a/source3/include/debug.h +++ b/source3/include/debug.h @@ -66,38 +66,124 @@ BOOL dbgtext(); #define FUNCTION_MACRO ("") #endif -/* Debugging macros. - * DEBUGLVL() - If level is <= the system-wide DEBUGLEVEL then generate a - * header using the default macros for file, line, and - * function name. - * Returns True if the debug level was <= DEBUGLEVEL. - * Example usage: - * if( DEBUGLVL( 2 ) ) - * dbgtext( "Some text.\n" ); - * DEBUG() - Good old DEBUG(). Each call to DEBUG() will generate a new - * header *unless* the previous debug output was unterminated - * (i.e., no '\n'). See debug.c:dbghdr() for more info. - * Example usage: - * DEBUG( 2, ("Some text.\n") ); - * DEBUGADD() - If level <= DEBUGLEVEL, then the text is appended to the - * current message (i.e., no header). - * Usage: - * DEBUGADD( 2, ("Some additional text.\n") ); +/* + * Redefine DEBUGLEVEL because so we don't have to change every source file + * that *unnecessarily* references it. Source files neeed not extern reference + * DEBUGLEVEL, as it's extern in includes.h (which all source files include). + * Eventually, all these references should be removed, and all references to + * DEBUGLEVEL should be references to DEBUGLEVEL_CLASS[DBGC_ALL]. This could + * still be through a macro still called DEBUGLEVEL. This cannot be done now + * because some references would expand incorrectly. + */ +#define DEBUGLEVEL *debug_level + + +/* + * Define all new debug classes here. A class is represented by an entry in + * the DEBUGLEVEL_CLASS array. Index zero of this arrray is equivalent to the + * old DEBUGLEVEL. Any source file that does NOT add the following lines: + * + * #undef DBGC_CLASS + * #define DBGC_CLASS DBGC_ + * + * at the start of the file (after #include "includes.h") will default to + * using index zero, so it will behaive just like it always has. + */ +#define DBGC_CLASS 0 /* override as shown above */ +#define DBGC_ALL 0 /* index equivalent to DEBUGLEVEL */ + +#define DBGC_TDB 1 +#define DBGC_PRINTDRIVERS 2 +#define DBGC_LANMAN 3 + +#define DBGC_LAST 4 /* MUST be last class value + 1 */ + + +extern int DEBUGLEVEL_CLASS[DBGC_LAST]; + + +/* Debugging macros + * + * DEBUGLVL() + * If the 'file specific' debug class level >= level OR the system-wide + * DEBUGLEVEL (synomym for DEBUGLEVEL_CLASS[ DBGC_ALL ]) >= level then + * generate a header using the default macros for file, line, and + * function name. Returns True if the debug level was <= DEBUGLEVEL. + * + * Example: if( DEBUGLVL( 2 ) ) dbgtext( "Some text.\n" ); + * + * DEBUGLVLC() + * If the 'macro specified' debug class level >= level OR the system-wide + * DEBUGLEVEL (synomym for DEBUGLEVEL_CLASS[ DBGC_ALL ]) >= level then + * generate a header using the default macros for file, line, and + * function name. Returns True if the debug level was <= DEBUGLEVEL. + * + * Example: if( DEBUGLVL( DBGC_TDB, 2 ) ) dbgtext( "Some text.\n" ); + * + * DEBUG() + * If the 'file specific' debug class level >= level OR the system-wide + * DEBUGLEVEL (synomym for DEBUGLEVEL_CLASS[ DBGC_ALL ]) >= level then + * generate a header using the default macros for file, line, and + * function name. Each call to DEBUG() generates a new header *unless* the + * previous debug output was unterminated (i.e. no '\n'). + * See debug.c:dbghdr() for more info. + * + * Example: DEBUG( 2, ("Some text and a valu %d.\n", value) ); + * + * DEBUGC() + * If the 'macro specified' debug class level >= level OR the system-wide + * DEBUGLEVEL (synomym for DEBUGLEVEL_CLASS[ DBGC_ALL ]) >= level then + * generate a header using the default macros for file, line, and + * function name. Each call to DEBUG() generates a new header *unless* the + * previous debug output was unterminated (i.e. no '\n'). + * See debug.c:dbghdr() for more info. + * + * Example: DEBUG( DBGC_TDB, 2, ("Some text and a valu %d.\n", value) ); + * + * DEBUGADD(), DEBUGADDC() + * Same as DEBUG() and DEBUGC() except the text is appended to the previous + * DEBUG(), DEBUGC(), DEBUGADD(), DEBUGADDC() with out another interviening + * header. + * + * Example: DEBUGADD( 2, ("Some text and a valu %d.\n", value) ); + * DEBUGADDC( DBGC_TDB, 2, ("Some text and a valu %d.\n", value) ); + * + * Note: If the debug class has not be redeined (see above) then the optimizer + * will remove the extra conditional test. */ + #define DEBUGLVL( level ) \ - ( (DEBUGLEVEL >= (level)) \ + ( ((DEBUGLEVEL_CLASS[ DBGC_CLASS ] >= (level))|| \ + (DEBUGLEVEL_CLASS[ DBGC_ALL ] >= (level)) ) \ + && dbghdr( level, FILE_MACRO, FUNCTION_MACRO, (__LINE__) ) ) + + +#define DEBUGLVLC( dbgc_class, level ) \ + ( ((DEBUGLEVEL_CLASS[ dbgc_class ] >= (level))|| \ + (DEBUGLEVEL_CLASS[ DBGC_ALL ] >= (level)) ) \ && dbghdr( level, FILE_MACRO, FUNCTION_MACRO, (__LINE__) ) ) + #define DEBUG( level, body ) \ - (void)( (DEBUGLEVEL >= (level)) \ + (void)( ((DEBUGLEVEL_CLASS[ DBGC_CLASS ] >= (level))|| \ + (DEBUGLEVEL_CLASS[ DBGC_ALL ] >= (level)) ) \ + && (dbghdr( level, FILE_MACRO, FUNCTION_MACRO, (__LINE__) )) \ + && (dbgtext body) ) + +#define DEBUGC( dbgc_class, level, body ) \ + (void)( ((DEBUGLEVEL_CLASS[ dbgc_class ] >= (level))|| \ + (DEBUGLEVEL_CLASS[ DBGC_ALL ] >= (level)) ) \ && (dbghdr( level, FILE_MACRO, FUNCTION_MACRO, (__LINE__) )) \ && (dbgtext body) ) #define DEBUGADD( level, body ) \ - (void)( (DEBUGLEVEL >= (level)) && (dbgtext body) ) + (void)( ((DEBUGLEVEL_CLASS[ DBGC_CLASS ] >= (level))|| \ + (DEBUGLEVEL_CLASS[ DBGC_ALL ] >= (level)) ) \ + && (dbgtext body) ) -/* End Debugging code section. - * -------------------------------------------------------------------------- ** - */ +#define DEBUGADDC( dbgc_class, level, body ) \ + (void)( ((DEBUGLEVEL_CLASS[ dbgc_class ] >= (level))|| \ + (DEBUGLEVEL_CLASS[ DBGC_ALL ] >= (level)) ) \ + && (dbgtext body) ) #endif diff --git a/source3/include/proto.h b/source3/include/proto.h index 8196c01569..9e0ab60c24 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -49,6 +49,10 @@ uint32 crc32_calc_buffer( char *buffer, uint32 count); /*The following definitions come from lib/debug.c */ +char* debug_classname_from_index(int idx); +int debug_lookup_classname(char* classname); +BOOL debug_parse_params(char **params, int *debuglevel_class); +BOOL debug_parse_levels(char *params_str); void debug_message(int msg_type, pid_t src, void *buf, size_t len); void debug_message_send(pid_t pid, int level); void setup_logging(char *pname, BOOL interactive); @@ -179,7 +183,7 @@ void init_msrpc_use(void); void free_msrpc_use(void); struct msrpc_state *msrpc_use_add(const char* pipe_name, uint32 pid, - const struct user_creds *usr_creds, + struct user_creds *usr_creds, BOOL redir); BOOL msrpc_use_del(const char* pipe_name, const struct user_creds *usr_creds, @@ -1589,6 +1593,7 @@ int lp_maxprotocol(void); int lp_security(void); int lp_maxdisksize(void); int lp_lpqcachetime(void); +int lp_max_smbd_processes(void); int lp_totalprintjobs(void); int lp_syslog(void); int lp_client_code_page(void); diff --git a/source3/lib/debug.c b/source3/lib/debug.c index 9d520b6c2f..e7772bbd38 100644 --- a/source3/lib/debug.c +++ b/source3/lib/debug.c @@ -82,7 +82,8 @@ FILE *dbf = NULL; pstring debugf = ""; BOOL append_log = False; -int DEBUGLEVEL = 1; +int DEBUGLEVEL_CLASS[DBGC_LAST]; +int DEBUGLEVEL = DEBUGLEVEL_CLASS; /* -------------------------------------------------------------------------- ** @@ -114,22 +115,137 @@ static int syslog_level = 0; static pstring format_bufr = { '\0' }; static size_t format_pos = 0; +/* +* Define all the debug class selection names here. Names *MUST NOT* contain +* white space. There must be one name for each DBGC_, and they +* must be in the table in the order of DBGC_.. +*/ +char *classname_table[] = { + "all", /* DBGC_ALL; index references traditional DEBUGLEVEL */ + "tdb", /* DBGC_TDB */ + "printdrivers", /* DBGC_PRINTDRIVERS */ + "lanman", /* DBGC_LANMAN */ +}; + /* -------------------------------------------------------------------------- ** * Functions... */ +/**************************************************************************** +utility access to debug class names's +****************************************************************************/ +char* debug_classname_from_index(int idx) +{ + return classname_table[idx]; +} + +/**************************************************************************** +utility to translate names to debug class index's +****************************************************************************/ +int debug_lookup_classname(char* classname) +{ + int i; + + if (!classname) return -1; + + for (i=0; iinfo_2->devmode != NULL) goto done; - +#endif /* * We don't have a devicemode and we're trying to write * one. Check we have the access needed. */ + DEBUG(5,("printer_write_default_dev: access: %x\n", printer_default->access_required)); + + if ( (printer_default->access_required & PRINTER_ACCESS_ADMINISTER) != + PRINTER_ACCESS_ADMINISTER) { + DEBUG(5,("printer_write_default_dev: invalid request access to update: %x\n", printer_default->access_required)); + result = ERROR_ACCESS_DENIED; + goto done; + } if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) { DEBUG(5,("printer_write_default_dev: Access denied for printer %s\n", lp_servicename(snum) )); result = ERROR_ACCESS_DENIED; + /*result = NT_STATUS_NO_PROBLEMO;*/ goto done; } + DEBUG(5,("printer_write_default_dev: updating, check OK.\n")); + /* * Convert the on the wire devicemode format to the internal one. */ diff --git a/source3/rpc_parse/parse_spoolss.c b/source3/rpc_parse/parse_spoolss.c index 868d90ae74..0961cda195 100644 --- a/source3/rpc_parse/parse_spoolss.c +++ b/source3/rpc_parse/parse_spoolss.c @@ -4361,17 +4361,20 @@ BOOL spool_io_printer_driver_info_level_6(char *desc, SPOOL_PRINTER_DRIVER_INFO_ if(!prs_uint32("version", ps, depth, &il->version)) return False; - if (il->version != 0) { - /* - * If version != 0 then there are an extra 4 bytes. - * JohnR and I have verified this at Roseville... JRA. - */ - if(!prs_uint32("dummy4", ps, depth, &il->dummy4)) - return False; - } if(!prs_uint32("name_ptr", ps, depth, &il->name_ptr)) - return False; + return False; + /* + * If name_ptr is NULL then the next 4 bytes are the name_ptr. A driver + * with a NULL name just isn't a driver For example: "HP LaserJet 4si" + * from W2K CDROM (which uses unidriver). JohnR 010205 + */ + if (!il->name_ptr) { + DEBUG(5,("spool_io_printer_driver_info_level_6: name_ptr is NULL! Get next value\n")); + if(!prs_uint32("name_ptr", ps, depth, &il->name_ptr)) + return False; + } + if(!prs_uint32("environment_ptr", ps, depth, &il->environment_ptr)) return False; if(!prs_uint32("driverpath_ptr", ps, depth, &il->driverpath_ptr)) diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 19f5859abb..207786768b 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -291,7 +291,7 @@ static void get_filename_transact( char *fname, char *inbuf, int data_offset, in * the end here. */ - if((data_len - fname_len == 1) || (inbuf[data_offset] == '\0')) { + if((data_len == 1) || (inbuf[data_offset] == '\0')) { /* * Ensure that the data offset is aligned * on a 2 byte boundary - add one if not. @@ -1110,6 +1110,15 @@ static BOOL set_sd(files_struct *fsp, char *data, uint32 sd_len, uint security_i return False; } + if (psd->off_owner_sid==0) + security_info_sent &= ~OWNER_SECURITY_INFORMATION; + if (psd->off_grp_sid==0) + security_info_sent &= ~GROUP_SECURITY_INFORMATION; + if (psd->off_sacl==0) + security_info_sent &= ~DACL_SECURITY_INFORMATION; + if (psd->off_dacl==0) + security_info_sent &= ~SACL_SECURITY_INFORMATION; + ret = set_nt_acl( fsp, security_info_sent, psd); if (!ret) { diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index ed8c0a94c9..db2f933420 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -238,6 +238,8 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, DEBUG(3,("unpack_nt_owners: unable to validate group sid.\n")); } + DEBUG(5,("unpack_nt_owners: owner_sids validated.\n")); + return True; } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index eb18219992..461fa99f39 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -769,6 +769,30 @@ static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize) return(outsize); } +/**************************************************************************** + Keep track of the number of running smbd's. This functionality is used to + 'hard' limit Samba overhead on resource constrained systems. +****************************************************************************/ +static BOOL smbd_process_limit(void) +{ + int total_smbds; + + if (lp_max_smbd_processes()) { + + /* Always add one to the smbd process count, as exit_server() always + * subtracts one. + */ + tdb_lock_bystring(conn_tdb_ctx(), "INFO/total_smbds"); + total_smbds = tdb_fetch_int(conn_tdb_ctx(), "INFO/total_smbds"); + total_smbds = total_smbds < 0 ? 1 : total_smbds + 1; + tdb_store_int(conn_tdb_ctx(), "INFO/total_smbds", total_smbds); + tdb_unlock_bystring(conn_tdb_ctx(), "INFO/total_smbds"); + + return total_smbds > lp_max_smbd_processes(); + } + else + return False; +} /**************************************************************************** process an smb from the client - split out from the process() code so @@ -792,8 +816,9 @@ void process_smb(char *inbuf, char *outbuf) deny parameters before doing any parsing of the packet passed to us by the client. This prevents attacks on our parsing code from hosts not in the hosts allow list */ - if (!check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))) { - /* send a negative session response "not listining on calling + if (smbd_process_limit() || + !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))) { + /* send a negative session response "not listening on calling name" */ static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; DEBUG( 1, ( "Connection denied from %s\n", diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b24ec7a944..2d205543fb 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -510,9 +510,9 @@ int smb_create_user(char *unix_user, char *homedir) pstrcpy(add_script, lp_adduser_script()); if (! *add_script) return -1; - pstring_sub(add_script, "%u", unix_user); + all_string_sub(add_script, "%u", unix_user, sizeof(pstring)); if (homedir) - pstring_sub(add_script, "%H", homedir); + all_string_sub(add_script, "%H", homedir, sizeof(pstring)); ret = smbrun(add_script,NULL,False); DEBUG(3,("smb_create_user: Running the command `%s' gave %d\n",add_script,ret)); return ret; @@ -529,7 +529,7 @@ static int smb_delete_user(char *unix_user) pstrcpy(del_script, lp_deluser_script()); if (! *del_script) return -1; - pstring_sub(del_script, "%u", unix_user); + all_string_sub(del_script, "%u", unix_user, sizeof(pstring)); ret = smbrun(del_script,NULL,False); DEBUG(3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret)); return ret; @@ -898,10 +898,10 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int /* if the username exists as a domain/username pair on the unix system then use that */ - if (!getpwnam(user)) { + if (!sys_getpwnam(user)) { pstring user2; slprintf(user2,sizeof(user2),"%s%s%s", dos_to_unix(domain,False), lp_winbind_separator(), user); - if (getpwnam(user2)) { + if (sys_getpwnam(user2)) { DEBUG(3,("Using unix username %s\n", user2)); pstrcpy(user, user2); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index a13f34d506..8eacd4ed58 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -409,6 +409,22 @@ static BOOL dump_core(void) } #endif +/**************************************************************************** +update the current smbd process count +****************************************************************************/ +static void decrement_smbd_process_count(void) +{ + int total_smbds; + + if (lp_max_smbd_processes()) { + tdb_lock_bystring(conn_tdb_ctx(), "INFO/total_smbds"); + if ((total_smbds = tdb_fetch_int(conn_tdb_ctx(), "INFO/total_smbds")) > 0) + tdb_store_int(conn_tdb_ctx(), "INFO/total_smbds", total_smbds - 1); + + tdb_unlock_bystring(conn_tdb_ctx(), "INFO/total_smbds"); + } +} + /**************************************************************************** exit the server ****************************************************************************/ @@ -432,6 +448,7 @@ void exit_server(char *reason) } respond_to_all_remaining_local_messages(); + decrement_smbd_process_count(); #ifdef WITH_DFS if (dcelogin_atmost_once) { diff --git a/source3/utils/smbcontrol.c b/source3/utils/smbcontrol.c index 87d00eecbd..26c01ced9e 100644 --- a/source3/utils/smbcontrol.c +++ b/source3/utils/smbcontrol.c @@ -77,10 +77,17 @@ Prints out the current Debug level returned by MSG_DEBUGLEVEL ****************************************************************************/ void debuglevel_function(int msg_type, pid_t src, void *buf, size_t len) { - int level; - memcpy(&level, buf, sizeof(int)); + int i; + int debuglevel_class[DBGC_LAST]; + + memcpy(debuglevel_class, buf, len); + + printf("Current debug level of PID %d is %d ",src, debuglevel_class[0]); + for (i=1;i:level\n"); + return(False); + } else + send_message(dest, MSG_DEBUG, debuglevel_class, sizeof(debuglevel_class), False); break; case MSG_PROFILE: - if (!params) { + if (!params[0]) { fprintf(stderr,"MSG_PROFILE needs a parameter\n"); return(False); } - if (strequal(params, "off")) { + if (strequal(params[0], "off")) { v = 0; - } else if (strequal(params, "count")) { + } else if (strequal(params[0], "count")) { v = 1; - } else if (strequal(params, "on")) { + } else if (strequal(params[0], "on")) { v = 2; - } else if (strequal(params, "flush")) { + } else if (strequal(params[0], "flush")) { v = 3; } else { fprintf(stderr, @@ -258,12 +271,12 @@ static BOOL do_command(char *dest, char *msg_name, char *params) fprintf(stderr,"printer-notify can only be sent to smbd\n"); return(False); } - if (!params) { + if (!params[0]) { fprintf(stderr, "printer-notify needs a printer name\n"); return (False); } - retval = send_message(dest, MSG_PRINTER_NOTIFY, params, - strlen(params) + 1, False); + retval = send_message(dest, MSG_PRINTER_NOTIFY, params[0], + strlen(params[0]) + 1, False); break; case MSG_PING: @@ -271,11 +284,11 @@ static BOOL do_command(char *dest, char *msg_name, char *params) message_register(MSG_PONG, pong_function); pong_registered = True; } - if (!params) { + if (!params[0]) { fprintf(stderr,"MSG_PING needs a parameter\n"); return(False); } - n = atoi(params); + n = atoi(params[0]); pong_count = 0; for (i=0;i 2 ? argv[2] : 0)); + return (do_command(argv[0],argv[1],argc > 2 ? &argv[2] : 0)); } while (True) { @@ -350,7 +363,7 @@ static BOOL do_command(char *dest, char *msg_name, char *params) if (strequal(myargv[0],"q")) break; if (myargc < 2) usage(False); - else if (!do_command(myargv[0],myargv[1],myargc > 2 ? myargv[2] : 0)) + else if (!do_command(myargv[0],myargv[1],myargc > 2 ? &myargv[2] : 0)) usage(False); } return(0); -- cgit