From 9ebd9a02892b0233080df2c2b435930b3b9f683b Mon Sep 17 00:00:00 2001 From: Hallvard Furuseth Date: Sat, 3 Apr 1999 03:19:07 +0000 Subject: [PATCH] Add -U and -G options to set user and group id. Move socket setup to set_socket(), called before the uid/gid change. --- configure | 4 ++ configure.in | 4 ++ doc/man/man8/slapd.8 | 18 +++++- include/portable.h.in | 12 ++++ servers/slapd/Makefile.in | 4 +- servers/slapd/daemon.c | 40 ++++++++---- servers/slapd/main.c | 36 +++++++++-- servers/slapd/proto-slap.h | 10 ++- servers/slapd/user.c | 128 +++++++++++++++++++++++++++++++++++++ 9 files changed, 232 insertions(+), 24 deletions(-) create mode 100644 servers/slapd/user.c diff --git a/configure b/configure index da27db8ec7..5a0e5e994c 100755 --- a/configure +++ b/configure @@ -8945,6 +8945,7 @@ for ac_hdr in \ fcntl.h \ filio.h \ getopt.h \ + grp.h \ libutil.h \ limits.h \ locale.h \ @@ -10274,8 +10275,11 @@ fi for ac_func in \ bcopy \ + endgrent \ + endpwent \ flock \ getdtablesize \ + getgrgid \ gethostname \ getpass \ getpwuid \ diff --git a/configure.in b/configure.in index 7b772d6995..19f2a6d3e2 100644 --- a/configure.in +++ b/configure.in @@ -1634,6 +1634,7 @@ AC_CHECK_HEADERS( \ fcntl.h \ filio.h \ getopt.h \ + grp.h \ libutil.h \ limits.h \ locale.h \ @@ -1707,8 +1708,11 @@ fi AC_CHECK_FUNCS( \ bcopy \ + endgrent \ + endpwent \ flock \ getdtablesize \ + getgrgid \ gethostname \ getpass \ getpwuid \ diff --git a/doc/man/man8/slapd.8 b/doc/man/man8/slapd.8 index 36bd63c588..f1b89126a9 100644 --- a/doc/man/man8/slapd.8 +++ b/doc/man/man8/slapd.8 @@ -1,10 +1,11 @@ -.TH SLAPD 8C "20 January 1999" "OpenLDAP LDVERSION" +.TH SLAPD 8C "3 April 1999" "OpenLDAP LDVERSION" .SH NAME slapd \- Stand-alone LDAP Daemon .SH SYNOPSIS .B LIBEXECDIR/slapd [\-d debug\-level] .B [\-f slapd\-config\-file] [\-a address] [\-p port\-number] .B [\-s syslog\-level] [\-l syslog\-local\-user] [\-i] +.B [\-U user] [\-G group] .B .SH DESCRIPTION .LP @@ -98,12 +99,27 @@ Internet standard '.' format. will listen on the default LDAP port (389) unless this option is given to override the default. A numeric port number is expected. .TP +.BI \-U " user" +.B slapd +will run slapd with the specified user name or id, and that user's +supplementary group access list as set with initgroups(3). The group ID +is also changed to this user's gid, unless the -G option is used to +override. +.TP +.BI \-G " group" +.B slapd +will run with the specified group name or id. +.TP .B \-i This option tells .B slapd that it is being run from .BR inetd(8) , the Internet protocol daemon. +.LP +Note that on some systems, running as a non-privileged user will prevent +passwd back-ends from accessing the encrypted passwords. Note also that +any shell back-ends will run as the specified non-privileged user. .SH EXAMPLES To start .I slapd diff --git a/include/portable.h.in b/include/portable.h.in index 1d6fa18936..77a7280ef8 100644 --- a/include/portable.h.in +++ b/include/portable.h.in @@ -213,12 +213,21 @@ /* Define if you have the ctime_r function. */ #undef HAVE_CTIME_R +/* Define if you have the endgrent function. */ +#undef HAVE_ENDGRENT + +/* Define if you have the endpwent function. */ +#undef HAVE_ENDPWENT + /* Define if you have the flock function. */ #undef HAVE_FLOCK /* Define if you have the getdtablesize function. */ #undef HAVE_GETDTABLESIZE +/* Define if you have the getgrgid function. */ +#undef HAVE_GETGRGID + /* Define if you have the gethostbyaddr_r function. */ #undef HAVE_GETHOSTBYADDR_R @@ -240,6 +249,9 @@ /* Define if you have the gettimeofday function. */ #undef HAVE_GETTIMEOFDAY +/* Define if you have the header file. */ +#undef HAVE_GRP_H + /* Define if you have the lockf function. */ #undef HAVE_LOCKF diff --git a/servers/slapd/Makefile.in b/servers/slapd/Makefile.in index b1e51d9624..11030fac1a 100644 --- a/servers/slapd/Makefile.in +++ b/servers/slapd/Makefile.in @@ -8,14 +8,14 @@ SRCS = main.c daemon.c connection.c search.c filter.c add.c charray.c \ attr.c entry.c config.c backend.c result.c operation.c \ dn.c compare.c modify.c delete.c modrdn.c ch_malloc.c \ value.c ava.c bind.c unbind.c abandon.c filterentry.c \ - phonetic.c acl.c str2filter.c aclparse.c init.c \ + phonetic.c acl.c str2filter.c aclparse.c init.c user.c \ repl.c lock.c \ suffixalias.c schema.c schemaparse.c monitor.c configinfo.c OBJS = main.o daemon.o connection.o search.o filter.o add.o charray.o \ attr.o entry.o config.o backend.o result.o operation.o \ dn.o compare.o modify.o delete.o modrdn.o ch_malloc.o \ value.o ava.o bind.o unbind.o abandon.o filterentry.o \ - phonetic.o acl.o str2filter.o aclparse.o init.o \ + phonetic.o acl.o str2filter.o aclparse.o init.o user.o \ repl.o lock.o \ suffixalias.o schema.o schemaparse.o monitor.o configinfo.o diff --git a/servers/slapd/daemon.c b/servers/slapd/daemon.c index 15a8bf8efa..2fd3116b43 100644 --- a/servers/slapd/daemon.c +++ b/servers/slapd/daemon.c @@ -146,12 +146,9 @@ static void slapd_close(int s) { tcp_close(s); } -static void * -slapd_daemon_task( - void *ptr -) +int +set_socket( struct sockaddr_in *addr ) { - struct sockaddr_in *addr = ptr; int tcps = -1; #ifdef HAVE_SYSCONF @@ -177,12 +174,6 @@ slapd_daemon_task( } #endif - connections_init(); - - ldap_pvt_thread_mutex_init( &slap_daemon.sd_mutex ); - FD_ZERO( &slap_daemon.sd_readers ); - FD_ZERO( &slap_daemon.sd_writers ); - if( addr != NULL ) { int tmp; @@ -223,7 +214,27 @@ slapd_daemon_task( ? sys_errlist[errno] : "unknown" ); exit( 1 ); } + } + + return tcps; +} + +static void * +slapd_daemon_task( + void *ptr +) +{ + int inetd = ((int *)ptr) [0]; + int tcps = ((int *)ptr) [1]; + free( ptr ); + + connections_init(); + + ldap_pvt_thread_mutex_init( &slap_daemon.sd_mutex ); + FD_ZERO( &slap_daemon.sd_readers ); + FD_ZERO( &slap_daemon.sd_writers ); + if( !inetd ) { if ( listen( tcps, 5 ) == -1 ) { Debug( LDAP_DEBUG_ANY, "daemon: listen(%d, 5) failed errno %d (%s)\n", @@ -569,12 +580,15 @@ slapd_daemon_task( return NULL; } -int slapd_daemon( struct sockaddr_in *addr ) +int slapd_daemon( int inetd, int tcps ) { int status; + int *args = ch_malloc( sizeof( int[2] ) ); + args[0] = inetd; + args[1] = tcps; status = ldap_pvt_thread_create( &listener_tid, 0, - slapd_daemon_task, addr ); + slapd_daemon_task, args ); if ( status != 0 ) { Debug( LDAP_DEBUG_ANY, diff --git a/servers/slapd/main.c b/servers/slapd/main.c index b18db5651c..a3cbae3b2d 100644 --- a/servers/slapd/main.c +++ b/servers/slapd/main.c @@ -63,6 +63,9 @@ usage( char *name ) #endif #ifdef LOG_LOCAL4 fprintf( stderr, " [-l sysloguser]" ); +#endif +#if defined(HAVE_PWD_H) && defined(HAVE_GRP_H) + fprintf( stderr, " [-U user] [-G group]" ); #endif fprintf( stderr, "\n" ); } @@ -75,10 +78,14 @@ main( int argc, char **argv ) int i; int inetd = 0; int rc; - struct sockaddr_in bind_addr, *slapd_addr; + struct sockaddr_in bind_addr; + int tcps; int udp; #ifdef LOG_LOCAL4 int syslogUser = DEFAULT_SYSLOG_USER; +#endif +#if defined(HAVE_PWD_H) && defined(HAVE_GRP_H) + char *username = NULL, *groupname = NULL; #endif char *configfile; char *serverName; @@ -101,6 +108,9 @@ main( int argc, char **argv ) #endif #ifdef SLAPD_BDB2 "t" +#endif +#if defined(HAVE_PWD_H) && defined(HAVE_GRP_H) + "U:G:" #endif )) != EOF ) { switch ( i ) { @@ -195,6 +205,16 @@ main( int argc, char **argv ) break; #endif +#if defined(HAVE_PWD_H) && defined(HAVE_GRP_H) + case 'U': /* user name */ + username = ch_strdup( optarg ); + break; + + case 'G': /* group name */ + groupname = ch_strdup( optarg ); + break; +#endif /* HAVE_PWD_H && HAVE_GRP_H */ + default: usage( argv[0] ); exit( 1 ); @@ -219,6 +239,13 @@ main( int argc, char **argv ) openlog( serverName, OPENLOG_OPTIONS ); #endif + tcps = set_socket( inetd ? NULL : &bind_addr ); + +#if defined(HAVE_PWD_H) && defined(HAVE_GRP_H) + if ( username != NULL || groupname != NULL ) + slap_init_user( username, groupname ); +#endif + if ( slap_init( serverMode, serverName ) != 0 ) { rc = 1; goto destroy; @@ -261,8 +288,6 @@ main( int argc, char **argv ) if(!inetd) { FILE *fp; - slapd_addr = &bind_addr; - Debug( LDAP_DEBUG_ANY, "slapd starting\n", 0, 0, 0 ); if (( slapd_pid_file != NULL ) && @@ -281,14 +306,11 @@ main( int argc, char **argv ) fprintf( fp, "\n" ); fclose( fp ); } - - } else { - slapd_addr = NULL; } time( &starttime ); - rc = slapd_daemon( slapd_addr ); + rc = slapd_daemon( inetd, tcps ); shutdown: /* remember an error during shutdown */ diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index 7907d6a623..72f4b115c6 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -256,6 +256,13 @@ int value_find LDAP_P(( struct berval **vals, struct berval *v, int syntax, */ char *suffixAlias LDAP_P(( char *dn, Operation *op, Backend *be )); +/* + * user.c + */ +#if defined(HAVE_PWD_H) && defined(HAVE_GRP_H) +void slap_init_user LDAP_P(( char *username, char *groupname )); +#endif + /* * Other... */ @@ -308,7 +315,8 @@ extern int slap_shutdown LDAP_P((int dbnum)); extern int slap_destroy LDAP_P((void)); struct sockaddr_in; -extern int slapd_daemon LDAP_P((struct sockaddr_in *addr)); +extern int set_socket LDAP_P((struct sockaddr_in *addr)); +extern int slapd_daemon LDAP_P((int inetd, int tcps)); extern void slapd_set_write LDAP_P((int s, int wake)); extern void slapd_clr_write LDAP_P((int s, int wake)); diff --git a/servers/slapd/user.c b/servers/slapd/user.c new file mode 100644 index 0000000000..e7d7252e01 --- /dev/null +++ b/servers/slapd/user.c @@ -0,0 +1,128 @@ +/* user.c - set user id, group id and group access list + * + * Copyright 1999 by PM Lashley and The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted only + * as authorized by the OpenLDAP Public License. A copy of this + * license is available at http://www.OpenLDAP.org/license.html or + * in file LICENSE in the top-level directory of the distribution. +*/ + +#include "portable.h" + +#if defined(HAVE_PWD_H) && defined(HAVE_GRP_H) + +#include +#include +#include +#include + +#include +#include + +#include "slap.h" + + +/* + * Set real and effective user id and group id, and group access list + */ + +void +slap_init_user( char *user, char *group ) +{ + uid_t uid = (gid_t) -1; + gid_t gid = (gid_t) -1; + + if ( user ) { + struct passwd *pwd; + if ( isdigit( (unsigned char) *user )) { + uid = atoi( user ); +#ifdef HAVE_GETPWUID + pwd = getpwuid( uid ); + goto did_getpw; +#endif + } else { + pwd = getpwnam( user ); + did_getpw: + if ( pwd == NULL ) { + Debug( LDAP_DEBUG_ANY, "No passwd entry for user %s\n", + user, 0, 0 ); + exit( 1 ); + } + if ( uid >= 0 ) { + free( user ); + user = (pwd != NULL ? ch_strdup( pwd->pw_name ) : NULL); + } else { + uid = pwd->pw_uid; + } + gid = pwd->pw_gid; +#ifdef HAVE_ENDPWENT + endpwent(); +#endif + } + } + + if ( group ) { + struct group *grp; + if ( isdigit( (unsigned char) *group )) { + gid = atoi( group ); +#ifdef HAVE_GETGRGID + grp = getgrgid( gid ); + goto did_group; +#endif + } else { + grp = getgrnam( group ); + if ( grp != NULL ) + gid = grp->gr_gid; + did_group: + if ( grp == NULL ) { + Debug( LDAP_DEBUG_ANY, "No group entry for group %s\n", + group, 0, 0 ); + exit( 1 ); + } + } + free( group ); + } + + if ( user ) { + if ( getuid() == 0 && initgroups( user, gid ) != 0 ) { + Debug( LDAP_DEBUG_ANY, + "Could not set the group access (gid) list\n", 0, 0, 0 ); + exit( 1 ); + } + free( user ); + } + +#ifdef HAVE_ENDGRENT + endgrent(); +#endif + + if ( gid >= 0 ) { + if ( setgid( gid ) != 0 ) { + Debug( LDAP_DEBUG_ANY, "Could not set real group id to %d\n", + gid, 0, 0 ); + exit( 1 ); + } + if ( setegid( gid ) != 0 ) { + Debug( LDAP_DEBUG_ANY, "Could not set effective group id to %d\n", + gid, 0, 0 ); + exit( 1 ); + } + } + + if ( uid >= 0 ) { + if ( setuid( uid ) != 0 ) { + Debug( LDAP_DEBUG_ANY, "Could not set effective user id to %d\n", + uid, 0, 0 ); + exit( 1 ); + } + if ( seteuid( uid ) != 0 ) { + Debug( LDAP_DEBUG_ANY, "Could not set real user id to %d\n", + uid, 0, 0 ); + exit( 1 ); + } + } +} + +#endif /* HAVE_PWD_H && HAVE_GRP_H */ -- 2.39.5