# useradd -M nmbd # chmod 775 /var/cache/samba # chgrp nmbd /var/cache/samba # chown nmbd:nmbd /var/cache/samba/messages.tdb # nmbd -D -u nmbd (look out for other permission errors) --- samba-2.2.3a/source/Makefile.in.bak 2002-04-07 02:52:55.000000000 +0300 +++ samba-2.2.3a/source/Makefile.in 2002-04-07 16:36:35.000000000 +0300 @@ -492,7 +492,7 @@ bin/smbd: $(SMBD_OBJ) bin/.dummy bin/nmbd: $(NMBD_OBJ) bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(NMBD_OBJ) $(LDFLAGS) $(LIBS) + @$(CC) $(FLAGS) -o $@ $(NMBD_OBJ) $(LDFLAGS) $(LIBS) -lcap bin/swat: $(SWAT_OBJ) bin/.dummy @echo Linking $@ --- samba-2.2.3a/source/nmbd/nmbd.c.bak 2002-04-07 02:52:55.000000000 +0300 +++ samba-2.2.3a/source/nmbd/nmbd.c 2002-04-07 17:07:30.000000000 +0300 @@ -25,6 +25,8 @@ */ +#include + #include "includes.h" pstring servicesf = CONFIGFILE; @@ -34,6 +36,7 @@ int ClientDGRAM = -1; int global_nmb_port = -1; static pstring host_file; +static pstring nmbd_user; extern pstring global_myname; extern fstring global_myworkgroup; extern char **my_netbios_names; @@ -635,7 +638,7 @@ static void usage(char *pname) { printf( "Usage: %s [-DaiohV] [-H lmhosts file] [-d debuglevel] [-l log basename]\n", pname ); - printf( " [-n name] [-p port] [-s configuration file]\n" ); + printf( " [-n name] [-p port] [-s configuration file] [-u user]\n" ); printf( "\t-D Become a daemon (default)\n" ); printf( "\t-a Append to log file (default)\n" ); printf( "\t-i Run interactive (not a daemon)\n" ); @@ -648,10 +651,66 @@ static void usage(char *pname) printf( "\t-n netbiosname. Primary netbios name\n" ); printf( "\t-p port Listen on the specified port\n" ); printf( "\t-s configuration file Configuration file name\n" ); + printf( "\t-u user Run as this uid/gid (default: root)" ); printf( "\n"); } /* usage */ +/************************************************************************ + switch user/group of nmbd process, keep CAP_NET_BIND_SERVICE capability + by Sami Farin +************************************************************************/ + +static void nmbd_droproot(void); +static void nmbd_droproot(void) +{ + struct passwd* pwd; + uid_t nmbd_uid; + gid_t nmbd_gids[1]; + cap_t nmbd_caps; + + if( (pwd = getpwnam( nmbd_user )) == NULL) { + DEBUG( 0, ( "getpwnam failed for \"%s\"\n", nmbd_user ) ); + exit(1); + } + + nmbd_uid = pwd->pw_uid; + nmbd_gids[0] = pwd->pw_gid; + + /* keep capabilities on setuid() away from uid 0 */ + if( prctl( PR_SET_KEEPCAPS, 1) != 0 ) { + DEBUG( 0, ( "prctl failed\n" ) ); + exit(1); + } + + if( setgroups( 1, nmbd_gids ) == -1 ) { + DEBUG( 0, ( "setgroups failed\n" ) ); + exit(1); + } + + if( (setegid(nmbd_gids[0]) == -1) || (seteuid(nmbd_uid) == -1) ) { + DEBUG( 0, ( "setegid and/or seteuid failed\n" ) ); + exit(1); + } + + if( (nmbd_caps = cap_from_text( "cap_net_bind_service=epi" ) ) == NULL) { + DEBUG( 0, ( "cap_from_text failed\n" ) ); + exit(1); + } + + if( cap_set_proc( nmbd_caps ) == -1) { + DEBUG( 0, ( "cap_set_proc failed\n" ) ); + exit(1); + } + + (void)cap_free( nmbd_caps ); + if( (setregid( nmbd_gids[0], nmbd_gids[0] ) == -1) || + (setreuid( nmbd_uid, nmbd_uid ) == -1) ) { + DEBUG( 0, ( "setregid and/or setreuid failed\n") ); + exit(1); + } +} + /**************************************************************************** ** Main program. **************************************************************************** */ @@ -669,6 +728,7 @@ static void usage(char *pname) global_nmb_port = NMB_PORT; *host_file = 0; + *nmbd_user = 0; global_in_nmbd = True; StartupTime = time(NULL); @@ -686,6 +746,8 @@ static void usage(char *pname) pstrcpy( host_file, LMHOSTSFILE ); #endif + pstrcpy( nmbd_user, "root" ); /* backwards compatibility */ + /* this is for people who can't start the program correctly */ while (argc > 1 && (*argv[1] != '-')) { @@ -715,13 +777,16 @@ static void usage(char *pname) #endif while( EOF != - (opt = getopt( argc, argv, "Vaos:T:I:C:bAB:N:Rn:l:d:Dip:hSH:G:f:" )) ) + (opt = getopt( argc, argv, "Vaos:T:I:C:bAB:N:Rn:l:d:Dip:hSH:G:f:u:" )) ) { switch (opt) { case 's': pstrcpy(servicesf,optarg); - break; + break; + case 'u': + pstrcpy(nmbd_user,optarg); + break; case 'N': case 'B': case 'I': @@ -844,6 +909,7 @@ static void usage(char *pname) } pidfile_create("nmbd"); + nmbd_droproot(); message_init(); message_register(MSG_FORCE_ELECTION, nmbd_message_election);