diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/smbd/service.c | 194 |
1 files changed, 122 insertions, 72 deletions
diff --git a/source3/smbd/service.c b/source3/smbd/service.c index c9e2cdcf50..c5fba5b50e 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -366,7 +366,8 @@ static NTSTATUS share_sanity_checks(int snum, fstring dev) static connection_struct *make_connection_snum(int snum, user_struct *vuser, DATA_BLOB password, - const char *pdev, NTSTATUS *status) + const char *pdev, + NTSTATUS *status) { struct passwd *pass = NULL; BOOL guest = False; @@ -396,7 +397,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, guest = True; pass = getpwnam_alloc(guestname); if (!pass) { - DEBUG(0,("make_connection_snum: Invalid guest account %s??\n",guestname)); + DEBUG(0,("make_connection_snum: Invalid guest " + "account %s??\n",guestname)); conn_free(conn); *status = NT_STATUS_NO_SUCH_USER; return NULL; @@ -411,14 +413,20 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, } else if (vuser) { if (vuser->guest) { if (!lp_guest_ok(snum)) { - DEBUG(2, ("guest user (from session setup) not permitted to access this share (%s)\n", lp_servicename(snum))); + DEBUG(2, ("guest user (from session setup) " + "not permitted to access this share " + "(%s)\n", lp_servicename(snum))); conn_free(conn); *status = NT_STATUS_ACCESS_DENIED; return NULL; } } else { - if (!user_ok(vuser->user.unix_name, snum, vuser->groups, vuser->n_groups)) { - DEBUG(2, ("user '%s' (from session setup) not permitted to access this share (%s)\n", vuser->user.unix_name, lp_servicename(snum))); + if (!user_ok(vuser->user.unix_name, snum, + vuser->groups, vuser->n_groups)) { + DEBUG(2, ("user '%s' (from session setup) not " + "permitted to access this share " + "(%s)\n", vuser->user.unix_name, + lp_servicename(snum))); conn_free(conn); *status = NT_STATUS_ACCESS_DENIED; return NULL; @@ -465,12 +473,14 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->service = snum; conn->used = True; conn->printer = (strncmp(dev,"LPT",3) == 0); - conn->ipc = ( (strncmp(dev,"IPC",3) == 0) || ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) ); + conn->ipc = ( (strncmp(dev,"IPC",3) == 0) || + ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) ); conn->dirptr = NULL; /* Case options for the share. */ if (lp_casesensitive(snum) == Auto) { - /* We will be setting this per packet. Set to be case insensitive for now. */ + /* We will be setting this per packet. Set to be case + * insensitive for now. */ conn->case_sensitive = False; } else { conn->case_sensitive = (BOOL)lp_casesensitive(snum); @@ -545,30 +555,30 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, pstring_sub(gname,"%S",lp_servicename(snum)); gid = nametogid(gname); - if (gid != (gid_t)-1) { - - /* - * If the user has been forced and the forced group starts - * with a '+', then we only set the group to be the forced - * group if the forced user is a member of that group. - * Otherwise, the meaning of the '+' would be ignored. - */ - if (conn->force_user && user_must_be_member) { - if (user_in_group_list( user, gname, NULL, 0)) { - conn->gid = gid; - DEBUG(3,("Forced group %s for member %s\n",gname,user)); - } - } else { - conn->gid = gid; - DEBUG(3,("Forced group %s\n",gname)); - } - conn->force_group = True; - } else { + if (gid == (gid_t)-1) { DEBUG(1,("Couldn't find group %s\n",gname)); conn_free(conn); *status = NT_STATUS_NO_SUCH_GROUP; return NULL; } + + /* + * If the user has been forced and the forced group starts + * with a '+', then we only set the group to be the forced + * group if the forced user is a member of that group. + * Otherwise, the meaning of the '+' would be ignored. + */ + if (conn->force_user && user_must_be_member) { + if (user_in_group_list( user, gname, NULL, 0)) { + conn->gid = gid; + DEBUG(3,("Forced group %s for member %s\n", + gname,user)); + } + } else { + conn->gid = gid; + DEBUG(3,("Forced group %s\n",gname)); + } + conn->force_group = True; } #endif /* HAVE_GETGRNAM */ @@ -577,7 +587,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, pstrcpy(s,lp_pathname(snum)); standard_sub_conn(conn,s,sizeof(s)); set_conn_connectpath(conn,s); - DEBUG(3,("Connect path is '%s' for service [%s]\n",s, lp_servicename(snum))); + DEBUG(3,("Connect path is '%s' for service [%s]\n",s, + lp_servicename(snum))); } if (conn->force_user || conn->force_group) { @@ -591,9 +602,10 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, initialise_groups(conn->user, conn->uid, conn->gid); get_current_groups(conn->gid, &conn->ngroups,&conn->groups); - conn->nt_user_token = create_nt_token(conn->uid, conn->gid, - conn->ngroups, conn->groups, - guest); + conn->nt_user_token = + create_nt_token(conn->uid, conn->gid, + conn->ngroups, conn->groups, + guest); } /* @@ -604,12 +616,16 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, */ { - BOOL can_write = share_access_check(conn, snum, vuser, FILE_WRITE_DATA); + BOOL can_write = share_access_check(conn, snum, vuser, + FILE_WRITE_DATA); if (!can_write) { - if (!share_access_check(conn, snum, vuser, FILE_READ_DATA)) { + if (!share_access_check(conn, snum, vuser, + FILE_READ_DATA)) { /* No access, read or write. */ - DEBUG(0,( "make_connection: connection to %s denied due to security descriptor.\n", + DEBUG(0,("make_connection: connection to %s " + "denied due to security " + "descriptor.\n", lp_servicename(snum))); conn_free(conn); *status = NT_STATUS_ACCESS_DENIED; @@ -622,18 +638,19 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, /* Initialise VFS function pointers */ if (!smbd_vfs_init(conn)) { - DEBUG(0, ("vfs_init failed for service %s\n", lp_servicename(snum))); + DEBUG(0, ("vfs_init failed for service %s\n", + lp_servicename(snum))); conn_free(conn); *status = NT_STATUS_BAD_NETWORK_NAME; return NULL; } /* - * If widelinks are disallowed we need to canonicalise the - * connect path here to ensure we don't have any symlinks in - * the connectpath. We will be checking all paths on this - * connection are below this directory. We must do this after - * the VFS init as we depend on the realpath() pointer in the vfs table. JRA. + * If widelinks are disallowed we need to canonicalise the connect + * path here to ensure we don't have any symlinks in the + * connectpath. We will be checking all paths on this connection are + * below this directory. We must do this after the VFS init as we + * depend on the realpath() pointer in the vfs table. JRA. */ if (!lp_widelinks(snum)) { pstring s; @@ -654,7 +671,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, return NULL; } - /* Preexecs are done here as they might make the dir we are to ChDir to below */ + /* Preexecs are done here as they might make the dir we are to ChDir + * to below */ /* execute any "root preexec = " line */ if (*lp_rootpreexec(snum)) { pstring cmd; @@ -663,7 +681,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, DEBUG(5,("cmd=%s\n",cmd)); ret = smbrun(cmd,NULL); if (ret != 0 && lp_rootpreexec_close(snum)) { - DEBUG(1,("root preexec gave %d - failing connection\n", ret)); + DEBUG(1,("root preexec gave %d - failing " + "connection\n", ret)); yield_connection(conn, lp_servicename(snum)); conn_free(conn); *status = NT_STATUS_ACCESS_DENIED; @@ -681,9 +700,12 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, return NULL; } - /* Remember that a different vuid can connect later without these checks... */ + /* Remember that a different vuid can connect later without these + * checks... */ - /* Preexecs are done here as they might make the dir we are to ChDir to below */ + /* Preexecs are done here as they might make the dir we are to ChDir + * to below */ + /* execute any "preexec = " line */ if (*lp_preexec(snum)) { pstring cmd; @@ -691,7 +713,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, standard_sub_conn(conn,cmd,sizeof(cmd)); ret = smbrun(cmd,NULL); if (ret != 0 && lp_preexec_close(snum)) { - DEBUG(1,("preexec gave %d - failing connection\n", ret)); + DEBUG(1,("preexec gave %d - failing connection\n", + ret)); change_to_root_user(); yield_connection(conn, lp_servicename(snum)); conn_free(conn); @@ -713,8 +736,9 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum)); } - /* Invoke VFS make connection hook - do this before the VFS_STAT call to allow - any filesystems needing user credentials to initialize themselves. */ + /* Invoke VFS make connection hook - do this before the VFS_STAT call + to allow any filesystems needing user credentials to initialize + themselves. */ if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) { DEBUG(0,("make_connection: VFS make connection failed!\n")); @@ -730,12 +754,17 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, check during individual operations. To match this behaviour I have disabled this chdir check (tridge) */ /* the alternative is just to check the directory exists */ - if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 || !S_ISDIR(st.st_mode)) { + if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 || + !S_ISDIR(st.st_mode)) { if (ret == 0 && !S_ISDIR(st.st_mode)) { - DEBUG(0,("'%s' is not a directory, when connecting to [%s]\n", conn->connectpath, lp_servicename(snum))); + DEBUG(0,("'%s' is not a directory, when connecting to " + "[%s]\n", conn->connectpath, + lp_servicename(snum))); } else { - DEBUG(0,("'%s' does not exist or permission denied when connecting to [%s] " - "Error was %s\n", conn->connectpath, lp_servicename(snum), strerror(errno) )); + DEBUG(0,("'%s' does not exist or permission denied " + "when connecting to [%s] Error was %s\n", + conn->connectpath, lp_servicename(snum), + strerror(errno) )); } change_to_root_user(); /* Call VFS disconnect hook */ @@ -766,7 +795,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, */ if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) { - dbgtext( "%s (%s) ", get_remote_machine_name(), conn->client_address ); + dbgtext( "%s (%s) ", get_remote_machine_name(), + conn->client_address ); dbgtext( "%s", srv_is_signing_active() ? "signed " : ""); dbgtext( "connect to service %s ", lp_servicename(snum) ); dbgtext( "initially as user %s ", user ); @@ -784,8 +814,10 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, vfs_chdir() **************************************************************************************/ -connection_struct *make_connection_with_chdir(const char *service_in, DATA_BLOB password, - const char *dev, uint16 vuid, NTSTATUS *status) +connection_struct *make_connection_with_chdir(const char *service_in, + DATA_BLOB password, + const char *dev, uint16 vuid, + NTSTATUS *status) { connection_struct *conn = NULL; @@ -797,7 +829,8 @@ connection_struct *make_connection_with_chdir(const char *service_in, DATA_BLOB */ if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) { - DEBUG(0,("move_driver_to_download_area: Can't change directory to %s for [print$] (%s)\n", + DEBUG(0,("move_driver_to_download_area: Can't change " + "directory to %s for [print$] (%s)\n", conn->connectpath,strerror(errno))); yield_connection(conn, lp_servicename(SNUM(conn))); conn_free(conn); @@ -815,7 +848,8 @@ connection_struct *make_connection_with_chdir(const char *service_in, DATA_BLOB ****************************************************************************/ connection_struct *make_connection(const char *service_in, DATA_BLOB password, - const char *pdev, uint16 vuid, NTSTATUS *status) + const char *pdev, uint16 vuid, + NTSTATUS *status) { uid_t euid; user_struct *vuser = NULL; @@ -825,43 +859,52 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, fstrcpy(dev, pdev); - /* This must ONLY BE CALLED AS ROOT. As it exits this function as root. */ + /* This must ONLY BE CALLED AS ROOT. As it exits this function as + * root. */ if (!non_root_mode() && (euid = geteuid()) != 0) { - DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot (%u)\n", (unsigned int)euid )); + DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot " + "(%u)\n", (unsigned int)euid )); smb_panic("make_connection: PANIC ERROR. Called as nonroot\n"); } if(lp_security() != SEC_SHARE) { vuser = get_valid_user_struct(vuid); if (!vuser) { - DEBUG(1,("make_connection: refusing to connect with no session setup\n")); + DEBUG(1,("make_connection: refusing to connect with " + "no session setup\n")); *status = NT_STATUS_ACCESS_DENIED; return NULL; } } - /* Logic to try and connect to the correct [homes] share, preferably without too many - getpwnam() lookups. This is particulary nasty for winbind usernames, where the - share name isn't the same as unix username. + /* Logic to try and connect to the correct [homes] share, preferably + without too many getpwnam() lookups. This is particulary nasty for + winbind usernames, where the share name isn't the same as unix + username. - The snum of the homes share is stored on the vuser at session setup time. + The snum of the homes share is stored on the vuser at session setup + time. */ if (strequal(service_in,HOMES_NAME)) { if(lp_security() != SEC_SHARE) { DATA_BLOB no_pw = data_blob(NULL, 0); if (vuser->homes_snum == -1) { - DEBUG(2, ("[homes] share not available for this user because it was not found or created at session setup time\n")); + DEBUG(2, ("[homes] share not available for " + "this user because it was not found " + "or created at session setup " + "time\n")); *status = NT_STATUS_BAD_NETWORK_NAME; return NULL; } - DEBUG(5, ("making a connection to [homes] service created at session setup time\n")); + DEBUG(5, ("making a connection to [homes] service " + "created at session setup time\n")); return make_connection_snum(vuser->homes_snum, vuser, no_pw, dev, status); } else { - /* Security = share. Try with current_user_info.smb_name - * as the username. */ + /* Security = share. Try with + * current_user_info.smb_name as the username. */ if (*current_user_info.smb_name) { fstring unix_username; fstrcpy(unix_username, @@ -870,16 +913,20 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, snum = find_service(unix_username); } if (snum != -1) { - DEBUG(5, ("making a connection to 'homes' service %s based on security=share\n", service_in)); + DEBUG(5, ("making a connection to 'homes' " + "service %s based on " + "security=share\n", service_in)); return make_connection_snum(snum, NULL, password, dev, status); } } } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1) - && strequal(service_in, lp_servicename(vuser->homes_snum))) { + && strequal(service_in, + lp_servicename(vuser->homes_snum))) { DATA_BLOB no_pw = data_blob(NULL, 0); - DEBUG(5, ("making a connection to 'homes' service [%s] created at session setup time\n", service_in)); + DEBUG(5, ("making a connection to 'homes' service [%s] " + "created at session setup time\n", service_in)); return make_connection_snum(vuser->homes_snum, vuser, no_pw, dev, status); @@ -893,7 +940,8 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, if (snum < 0) { if (strequal(service,"IPC$") - || (lp_enable_asu_support() && strequal(service,"ADMIN$"))) + || (lp_enable_asu_support() && + strequal(service,"ADMIN$"))) { DEBUG(3,("refusing IPC connection to %s\n", service)); *status = NT_STATUS_ACCESS_DENIED; @@ -908,7 +956,8 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, /* Handle non-Dfs clients attempting connections to msdfs proxy */ if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) { - DEBUG(3, ("refusing connection to dfs proxy share '%s' (pointing to %s)\n", + DEBUG(3, ("refusing connection to dfs proxy share '%s' " + "(pointing to %s)\n", service, lp_msdfs_proxy(snum))); *status = NT_STATUS_BAD_NETWORK_NAME; return NULL; @@ -937,7 +986,8 @@ void close_cnum(connection_struct *conn, uint16 vuid) change_to_root_user(); DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n", - get_remote_machine_name(),conn->client_address, + get_remote_machine_name(), + conn->client_address, lp_servicename(SNUM(conn)))); /* Call VFS disconnect hook */ |