X-Git-Url: http://git.samba.org/?a=blobdiff_plain;f=source3%2Fsmbd%2Fservice.c;h=8039d16586eb164f576f4c4def3a919aac6feff1;hb=bd269443e311d96ef495a9db47d1b95eb83bb8f4;hp=ed8061e2f79c6e90b51b7eac7ab9bea42fc6541e;hpb=b92c3e281c66127dbd2b16b7c71e2cba4e0c1de9;p=samba.git diff --git a/source3/smbd/service.c b/source3/smbd/service.c index ed8061e2f79..8039d16586e 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -18,6 +18,7 @@ */ #include "includes.h" +#include "smbd/globals.h" extern userdom_struct current_user_info; @@ -55,7 +56,12 @@ bool set_conn_connectpath(connection_struct *conn, const char *connectpath) const char *s = connectpath; bool start_of_name_component = true; - destname = SMB_STRDUP(connectpath); + if (connectpath == NULL || connectpath[0] == '\0') { + return false; + } + + /* Allocate for strlen + '\0' + possible leading '/' */ + destname = SMB_MALLOC(strlen(connectpath) + 2); if (!destname) { return false; } @@ -167,8 +173,6 @@ bool set_conn_connectpath(connection_struct *conn, const char *connectpath) bool set_current_service(connection_struct *conn, uint16 flags, bool do_chdir) { - static connection_struct *last_conn; - static uint16 last_flags; int snum; if (!conn) { @@ -183,8 +187,8 @@ bool set_current_service(connection_struct *conn, uint16 flags, bool do_chdir) if (do_chdir && vfs_ChDir(conn,conn->connectpath) != 0 && vfs_ChDir(conn,conn->origpath) != 0) { - DEBUG(0,("chdir (%s) failed\n", - conn->connectpath)); + DEBUG(((errno!=EACCES)?0:3),("chdir (%s) failed, reason: %s\n", + conn->connectpath, strerror(errno))); return(False); } @@ -221,92 +225,34 @@ bool set_current_service(connection_struct *conn, uint16 flags, bool do_chdir) static int load_registry_service(const char *servicename) { - struct registry_key *key; - char *path; - WERROR err; - - uint32 i; - char *value_name; - struct registry_value *value; - - int res = -1; - if (!lp_registry_shares()) { return -1; } - if (asprintf(&path, "%s\\%s", KEY_SMBCONF, servicename) == -1) { + if ((servicename == NULL) || (*servicename == '\0')) { return -1; } - err = reg_open_path(NULL, path, REG_KEY_READ, get_root_nt_token(), - &key); - SAFE_FREE(path); - - if (!W_ERROR_IS_OK(err)) { - return -1; + if (strequal(servicename, GLOBAL_NAME)) { + return -2; } - res = lp_add_service(servicename, -1); - if (res == -1) { - goto error; - } - - for (i=0; - W_ERROR_IS_OK(reg_enumvalue(key, key, i, &value_name, &value)); - i++) { - switch (value->type) { - case REG_DWORD: { - char *tmp; - if (asprintf(&tmp, "%d", value->v.dword) == -1) { - continue; - } - lp_do_parameter(res, value_name, tmp); - SAFE_FREE(tmp); - break; - } - case REG_SZ: { - lp_do_parameter(res, value_name, value->v.sz.str); - break; - } - default: - /* Ignore all the rest */ - break; - } - - TALLOC_FREE(value_name); - TALLOC_FREE(value); + if (!process_registry_service(servicename)) { + return -1; } - error: - - TALLOC_FREE(key); - return res; + return lp_servicenumber(servicename); } void load_registry_shares(void) { - struct registry_key *key; - char *name; - WERROR err; - int i; - + DEBUG(8, ("load_registry_shares()\n")); if (!lp_registry_shares()) { return; } - err = reg_open_path(NULL, KEY_SMBCONF, REG_KEY_READ, - get_root_nt_token(), &key); - if (!(W_ERROR_IS_OK(err))) { - return; - } - - for (i=0; W_ERROR_IS_OK(reg_enumkey(key, key, i, &name, NULL)); i++) { - load_registry_service(name); - TALLOC_FREE(name); - } + process_registry_shares(); - TALLOC_FREE(key); return; } @@ -318,7 +264,7 @@ int add_home_service(const char *service, const char *username, const char *home { int iHomeService; - if (!service || !homedir) + if (!service || !homedir || homedir[0] == '\0') return -1; if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0) { @@ -360,6 +306,7 @@ int add_home_service(const char *service, const char *username, const char *home int find_service(fstring service) { int iService; + struct smbd_server_connection *sconn = smbd_server_conn; all_string_sub(service,"\\","/",0); @@ -374,7 +321,7 @@ int find_service(fstring service) * Try mapping the servicename, it may * be a Windows to unix mapped user name. */ - if(map_username(service)) + if(map_username(sconn, service)) phome_dir = get_user_home_dir( talloc_tos(), service); } @@ -518,31 +465,6 @@ static NTSTATUS share_sanity_checks(int snum, fstring dev) return NT_STATUS_OK; } -static NTSTATUS find_forced_user(connection_struct *conn, bool vuser_is_guest, fstring username) -{ - int snum = conn->params->service; - char *fuser, *found_username; - NTSTATUS result; - - if (!(fuser = talloc_string_sub(conn->mem_ctx, lp_force_user(snum), "%S", - lp_servicename(snum)))) { - return NT_STATUS_NO_MEMORY; - } - - result = create_token_from_username(conn->mem_ctx, fuser, vuser_is_guest, - &conn->uid, &conn->gid, &found_username, - &conn->nt_user_token); - if (!NT_STATUS_IS_OK(result)) { - return result; - } - - fstrcpy(username, found_username); - - TALLOC_FREE(fuser); - TALLOC_FREE(found_username); - return NT_STATUS_OK; -} - /* * Go through lookup_name etc to find the force'd group. * @@ -556,23 +478,14 @@ static NTSTATUS find_forced_group(bool force_user, gid_t *pgid) { NTSTATUS result = NT_STATUS_NO_SUCH_GROUP; - TALLOC_CTX *mem_ctx; + TALLOC_CTX *frame = talloc_stackframe(); DOM_SID group_sid; enum lsa_SidType type; char *groupname; bool user_must_be_member = False; gid_t gid; - ZERO_STRUCTP(pgroup_sid); - *pgid = (gid_t)-1; - - mem_ctx = talloc_new(NULL); - if (mem_ctx == NULL) { - DEBUG(0, ("talloc_new failed\n")); - return NT_STATUS_NO_MEMORY; - } - - groupname = talloc_strdup(mem_ctx, lp_force_group(snum)); + groupname = talloc_strdup(talloc_tos(), lp_force_group(snum)); if (groupname == NULL) { DEBUG(1, ("talloc_strdup failed\n")); result = NT_STATUS_NO_MEMORY; @@ -584,10 +497,15 @@ static NTSTATUS find_forced_group(bool force_user, groupname += 1; } - groupname = talloc_string_sub(mem_ctx, groupname, + groupname = talloc_string_sub(talloc_tos(), groupname, "%S", lp_servicename(snum)); + if (groupname == NULL) { + DEBUG(1, ("talloc_string_sub failed\n")); + result = NT_STATUS_NO_MEMORY; + goto done; + } - if (!lookup_name_smbconf(mem_ctx, groupname, + if (!lookup_name_smbconf(talloc_tos(), groupname, LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP, NULL, NULL, &group_sid, &type)) { DEBUG(10, ("lookup_name_smbconf(%s) failed\n", @@ -636,144 +554,139 @@ static NTSTATUS find_forced_group(bool force_user, result = NT_STATUS_OK; done: - TALLOC_FREE(mem_ctx); + TALLOC_FREE(frame); return result; } +/**************************************************************************** + Create an auth_serversupplied_info structure for a connection_struct +****************************************************************************/ + +static NTSTATUS create_connection_server_info(struct smbd_server_connection *sconn, + TALLOC_CTX *mem_ctx, int snum, + struct auth_serversupplied_info *vuid_serverinfo, + DATA_BLOB password, + struct auth_serversupplied_info **presult) +{ + if (lp_guest_only(snum)) { + return make_server_info_guest(mem_ctx, presult); + } + + if (vuid_serverinfo != NULL) { + + struct auth_serversupplied_info *result; + + /* + * This is the normal security != share case where we have a + * valid vuid from the session setup. */ + + if (vuid_serverinfo->guest) { + if (!lp_guest_ok(snum)) { + DEBUG(2, ("guest user (from session setup) " + "not permitted to access this share " + "(%s)\n", lp_servicename(snum))); + return NT_STATUS_ACCESS_DENIED; + } + } else { + if (!user_ok_token(vuid_serverinfo->unix_name, + pdb_get_domain(vuid_serverinfo->sam_account), + vuid_serverinfo->ptok, snum)) { + DEBUG(2, ("user '%s' (from session setup) not " + "permitted to access this share " + "(%s)\n", + vuid_serverinfo->unix_name, + lp_servicename(snum))); + return NT_STATUS_ACCESS_DENIED; + } + } + + result = copy_serverinfo(mem_ctx, vuid_serverinfo); + if (result == NULL) { + return NT_STATUS_NO_MEMORY; + } + + *presult = result; + return NT_STATUS_OK; + } + + if (lp_security() == SEC_SHARE) { + + fstring user; + bool guest; + + /* add the sharename as a possible user name if we + are in share mode security */ + + add_session_user(sconn, lp_servicename(snum)); + + /* shall we let them in? */ + + if (!authorise_login(sconn, snum,user,password,&guest)) { + DEBUG( 2, ( "Invalid username/password for [%s]\n", + lp_servicename(snum)) ); + return NT_STATUS_WRONG_PASSWORD; + } + + return make_serverinfo_from_username(mem_ctx, user, guest, + presult); + } + + DEBUG(0, ("invalid VUID (vuser) but not in security=share\n")); + return NT_STATUS_ACCESS_DENIED; +} + + /**************************************************************************** Make a connection, given the snum to connect to, and the vuser of the connecting user if appropriate. ****************************************************************************/ -static connection_struct *make_connection_snum(int snum, user_struct *vuser, - DATA_BLOB password, - const char *pdev, - NTSTATUS *status) +connection_struct *make_connection_snum(struct smbd_server_connection *sconn, + int snum, user_struct *vuser, + DATA_BLOB password, + const char *pdev, + NTSTATUS *pstatus) { - struct passwd *pass = NULL; - bool guest = False; connection_struct *conn; - SMB_STRUCT_STAT st; - fstring user; + struct smb_filename *smb_fname_cpath = NULL; fstring dev; int ret; char addr[INET6_ADDRSTRLEN]; bool on_err_call_dis_hook = false; + NTSTATUS status; - *user = 0; fstrcpy(dev, pdev); - SET_STAT_INVALID(st); - if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) { + if (NT_STATUS_IS_ERR(*pstatus = share_sanity_checks(snum, dev))) { return NULL; } - conn = conn_new(); + conn = conn_new(sconn); if (!conn) { DEBUG(0,("Couldn't find free connection.\n")); - *status = NT_STATUS_INSUFFICIENT_RESOURCES; + *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES; return NULL; } conn->params->service = snum; - conn->nt_user_token = NULL; - - if (lp_guest_only(snum)) { - const char *guestname = lp_guestaccount(); - NTSTATUS status2; - char *found_username = NULL; - - guest = True; - pass = getpwnam_alloc(NULL, guestname); - if (!pass) { - DEBUG(0,("make_connection_snum: Invalid guest " - "account %s??\n",guestname)); - conn_free(conn); - *status = NT_STATUS_NO_SUCH_USER; - return NULL; - } - status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True, - &conn->uid, &conn->gid, - &found_username, - &conn->nt_user_token); - if (!NT_STATUS_IS_OK(status2)) { - TALLOC_FREE(pass); - conn_free(conn); - *status = status2; - return NULL; - } - fstrcpy(user, found_username); - string_set(&conn->user,user); - conn->force_user = True; - TALLOC_FREE(found_username); - TALLOC_FREE(pass); - DEBUG(3,("Guest only user %s\n",user)); - } 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))); - conn_free(conn); - *status = NT_STATUS_ACCESS_DENIED; - return NULL; - } - } else { - if (!user_ok_token(vuser->user.unix_name, - vuser->nt_user_token, snum)) { - 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; - } - } - conn->vuid = vuser->vuid; - conn->uid = vuser->uid; - conn->gid = vuser->gid; - string_set(&conn->user,vuser->user.unix_name); - fstrcpy(user,vuser->user.unix_name); - guest = vuser->guest; - } else if (lp_security() == SEC_SHARE) { - NTSTATUS status2; - char *found_username = NULL; - - /* add it as a possible user name if we - are in share mode security */ - add_session_user(lp_servicename(snum)); - /* shall we let them in? */ - if (!authorise_login(snum,user,password,&guest)) { - DEBUG( 2, ( "Invalid username/password for [%s]\n", - lp_servicename(snum)) ); - conn_free(conn); - *status = NT_STATUS_WRONG_PASSWORD; - return NULL; - } - pass = Get_Pwnam_alloc(talloc_tos(), user); - status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True, - &conn->uid, &conn->gid, - &found_username, - &conn->nt_user_token); - TALLOC_FREE(pass); - if (!NT_STATUS_IS_OK(status2)) { - conn_free(conn); - *status = status2; - return NULL; - } - fstrcpy(user, found_username); - string_set(&conn->user,user); - TALLOC_FREE(found_username); - conn->force_user = True; - } else { - DEBUG(0, ("invalid VUID (vuser) but not in security=share\n")); + + status = create_connection_server_info(sconn, + conn, snum, vuser ? vuser->server_info : NULL, password, + &conn->server_info); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("create_connection_server_info failed: %s\n", + nt_errstr(status))); + *pstatus = status; conn_free(conn); - *status = NT_STATUS_ACCESS_DENIED; return NULL; } - add_session_user(user); + if ((lp_guest_only(snum)) || (lp_security() == SEC_SHARE)) { + conn->force_user = true; + } + + add_session_user(sconn, conn->server_info->unix_name); safe_strcpy(conn->client_address, client_addr(get_client_fd(),addr,sizeof(addr)), @@ -784,7 +697,6 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->printer = (strncmp(dev,"LPT",3) == 0); 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) { @@ -804,127 +716,92 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->hide_list = NULL; conn->veto_oplock_list = NULL; conn->aio_write_behind_list = NULL; - string_set(&conn->dirpath,""); - string_set(&conn->user,user); conn->read_only = lp_readonly(SNUM(conn)); conn->admin_user = False; - /* - * If force user is true, then store the given userid and the gid of - * the user we're forcing. - * For auxiliary groups see below. - */ - if (*lp_force_user(snum)) { - NTSTATUS status2; - status2 = find_forced_user(conn, - (vuser != NULL) && vuser->guest, - user); - if (!NT_STATUS_IS_OK(status2)) { + /* + * Replace conn->server_info with a completely faked up one + * from the username we are forced into :-) + */ + + char *fuser; + struct auth_serversupplied_info *forced_serverinfo; + + fuser = talloc_string_sub(conn, lp_force_user(snum), "%S", + lp_servicename(snum)); + if (fuser == NULL) { + conn_free(conn); + *pstatus = NT_STATUS_NO_MEMORY; + return NULL; + } + + status = make_serverinfo_from_username( + conn, fuser, conn->server_info->guest, + &forced_serverinfo); + if (!NT_STATUS_IS_OK(status)) { conn_free(conn); - *status = status2; + *pstatus = status; return NULL; } - string_set(&conn->user,user); + + TALLOC_FREE(conn->server_info); + conn->server_info = forced_serverinfo; + conn->force_user = True; - DEBUG(3,("Forced user %s\n",user)); + DEBUG(3,("Forced user %s\n", fuser)); } /* * If force group is true, then override * any groupid stored for the connecting user. */ - + if (*lp_force_group(snum)) { - NTSTATUS status2; - DOM_SID group_sid; - status2 = find_forced_group(conn->force_user, - snum, user, - &group_sid, &conn->gid); - if (!NT_STATUS_IS_OK(status2)) { + status = find_forced_group( + conn->force_user, snum, conn->server_info->unix_name, + &conn->server_info->ptok->user_sids[1], + &conn->server_info->utok.gid); + + if (!NT_STATUS_IS_OK(status)) { conn_free(conn); - *status = status2; + *pstatus = status; return NULL; } - if ((conn->nt_user_token == NULL) && (vuser != NULL)) { - - /* Not force user and not security=share, but force - * group. vuser has a token to copy */ - - conn->nt_user_token = dup_nt_token( - NULL, vuser->nt_user_token); - if (conn->nt_user_token == NULL) { - DEBUG(0, ("dup_nt_token failed\n")); - conn_free(conn); - *status = NT_STATUS_NO_MEMORY; - return NULL; - } - } - - /* If conn->nt_user_token is still NULL, we have - * security=share. This means ignore the SID, as we had no - * vuser to copy from */ - - if (conn->nt_user_token != NULL) { - /* Overwrite the primary group sid */ - sid_copy(&conn->nt_user_token->user_sids[1], - &group_sid); - - } - conn->force_group = True; + /* + * We need to cache this gid, to use within + * change_to_user() separately from the conn->server_info + * struct. We only use conn->server_info directly if + * "force_user" was set. + */ + conn->force_group_gid = conn->server_info->utok.gid; } - if (conn->nt_user_token != NULL) { - size_t i; - - /* We have a share-specific token from force [user|group]. - * This means we have to create the list of unix groups from - * the list of sids. */ - - conn->ngroups = 0; - conn->groups = NULL; - - for (i=0; int_user_token->num_sids; i++) { - gid_t gid; - DOM_SID *sid = &conn->nt_user_token->user_sids[i]; - - if (!sid_to_gid(sid, &gid)) { - DEBUG(10, ("Could not convert SID %s to gid, " - "ignoring it\n", - sid_string_dbg(sid))); - continue; - } - if (!add_gid_to_array_unique(conn->mem_ctx, gid, &conn->groups, - &conn->ngroups)) { - DEBUG(0, ("add_gid_to_array_unique failed\n")); - conn_free(conn); - *status = NT_STATUS_NO_MEMORY; - return NULL; - } - } - } + conn->vuid = (vuser != NULL) ? vuser->vuid : UID_FIELD_INVALID; { char *s = talloc_sub_advanced(talloc_tos(), - lp_servicename(SNUM(conn)), conn->user, - conn->connectpath, conn->gid, - get_current_username(), - current_user_info.domain, + lp_servicename(SNUM(conn)), + conn->server_info->unix_name, + conn->connectpath, + conn->server_info->utok.gid, + conn->server_info->sanitized_username, + pdb_get_domain(conn->server_info->sam_account), lp_pathname(snum)); if (!s) { conn_free(conn); - *status = NT_STATUS_NO_MEMORY; + *pstatus = NT_STATUS_NO_MEMORY; return NULL; } if (!set_conn_connectpath(conn,s)) { TALLOC_FREE(s); conn_free(conn); - *status = NT_STATUS_NO_MEMORY; + *pstatus = NT_STATUS_NO_MEMORY; return NULL; } DEBUG(3,("Connect path is '%s' for service [%s]\n",s, @@ -941,32 +818,13 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, { bool can_write = False; - NT_USER_TOKEN *token = conn->nt_user_token ? - conn->nt_user_token : - (vuser ? vuser->nt_user_token : NULL); - /* - * I don't believe this can happen. But the - * logic above is convoluted enough to confuse - * automated checkers, so be sure. JRA. - */ - - if (token == NULL) { - DEBUG(0,("make_connection: connection to %s " - "denied due to missing " - "NT token.\n", - lp_servicename(snum))); - conn_free(conn); - *status = NT_STATUS_ACCESS_DENIED; - return NULL; - } - - can_write = share_access_check(token, - lp_servicename(snum), - FILE_WRITE_DATA); + can_write = share_access_check(conn->server_info->ptok, + lp_servicename(snum), + FILE_WRITE_DATA); if (!can_write) { - if (!share_access_check(token, + if (!share_access_check(conn->server_info->ptok, lp_servicename(snum), FILE_READ_DATA)) { /* No access, read or write. */ @@ -975,7 +833,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, "descriptor.\n", lp_servicename(snum))); conn_free(conn); - *status = NT_STATUS_ACCESS_DENIED; + *pstatus = NT_STATUS_ACCESS_DENIED; return NULL; } else { conn->read_only = True; @@ -988,7 +846,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, DEBUG(0, ("vfs_init failed for service %s\n", lp_servicename(snum))); conn_free(conn); - *status = NT_STATUS_BAD_NETWORK_NAME; + *pstatus = NT_STATUS_BAD_NETWORK_NAME; return NULL; } @@ -1006,13 +864,13 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, lp_servicename(snum), conn->connectpath)); conn_free(conn); - *status = NT_STATUS_BAD_NETWORK_NAME; + *pstatus = NT_STATUS_BAD_NETWORK_NAME; return NULL; } } if ((!conn->printer) && (!conn->ipc)) { - conn->notify_ctx = notify_init(conn->mem_ctx, server_id_self(), + conn->notify_ctx = notify_init(conn, server_id_self(), smbd_messaging_context(), smbd_event_context(), conn); @@ -1030,7 +888,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, DEBUG(1, ("Max connections (%d) exceeded for %s\n", lp_max_connections(snum), lp_servicename(snum))); conn_free(conn); - *status = NT_STATUS_INSUFFICIENT_RESOURCES; + *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES; return NULL; } @@ -1040,7 +898,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, if (!claim_connection(conn, lp_servicename(snum), 0)) { DEBUG(1, ("Could not store connections entry\n")); conn_free(conn); - *status = NT_STATUS_INTERNAL_DB_ERROR; + *pstatus = NT_STATUS_INTERNAL_DB_ERROR; return NULL; } @@ -1049,10 +907,12 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, /* execute any "root preexec = " line */ if (*lp_rootpreexec(snum)) { char *cmd = talloc_sub_advanced(talloc_tos(), - lp_servicename(SNUM(conn)), conn->user, - conn->connectpath, conn->gid, - get_current_username(), - current_user_info.domain, + lp_servicename(SNUM(conn)), + conn->server_info->unix_name, + conn->connectpath, + conn->server_info->utok.gid, + conn->server_info->sanitized_username, + pdb_get_domain(conn->server_info->sam_account), lp_rootpreexec(snum)); DEBUG(5,("cmd=%s\n",cmd)); ret = smbrun(cmd,NULL); @@ -1062,7 +922,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, "connection\n", ret)); yield_connection(conn, lp_servicename(snum)); conn_free(conn); - *status = NT_STATUS_ACCESS_DENIED; + *pstatus = NT_STATUS_ACCESS_DENIED; return NULL; } } @@ -1073,7 +933,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, DEBUG(0,("Can't become connected user!\n")); yield_connection(conn, lp_servicename(snum)); conn_free(conn); - *status = NT_STATUS_LOGON_FAILURE; + *pstatus = NT_STATUS_LOGON_FAILURE; return NULL; } @@ -1086,17 +946,19 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, /* execute any "preexec = " line */ if (*lp_preexec(snum)) { char *cmd = talloc_sub_advanced(talloc_tos(), - lp_servicename(SNUM(conn)), conn->user, - conn->connectpath, conn->gid, - get_current_username(), - current_user_info.domain, + lp_servicename(SNUM(conn)), + conn->server_info->unix_name, + conn->connectpath, + conn->server_info->utok.gid, + conn->server_info->sanitized_username, + pdb_get_domain(conn->server_info->sam_account), lp_preexec(snum)); ret = smbrun(cmd,NULL); TALLOC_FREE(cmd); if (ret != 0 && lp_preexec_close(snum)) { DEBUG(1,("preexec gave %d - failing connection\n", ret)); - *status = NT_STATUS_ACCESS_DENIED; + *pstatus = NT_STATUS_ACCESS_DENIED; goto err_root_exit; } } @@ -1112,29 +974,39 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, set_namearray( &conn->veto_list, lp_veto_files(snum)); set_namearray( &conn->hide_list, lp_hide_files(snum)); set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum)); + set_namearray( &conn->aio_write_behind_list, + lp_aio_write_behind(snum)); } /* 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) { + if (SMB_VFS_CONNECT(conn, lp_servicename(snum), + conn->server_info->unix_name) < 0) { DEBUG(0,("make_connection: VFS make connection failed!\n")); - *status = NT_STATUS_UNSUCCESSFUL; + *pstatus = NT_STATUS_UNSUCCESSFUL; goto err_root_exit; } /* Any error exit after here needs to call the disconnect hook. */ on_err_call_dis_hook = true; + status = create_synthetic_smb_fname(talloc_tos(), conn->connectpath, + NULL, NULL, &smb_fname_cpath); + if (!NT_STATUS_IS_OK(status)) { + *pstatus = status; + goto err_root_exit; + } + /* win2000 does not check the permissions on the directory during the tree connect, instead relying on permission 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 == 0 && !S_ISDIR(st.st_mode)) { + if ((ret = SMB_VFS_STAT(conn, smb_fname_cpath)) != 0 || + !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) { + if (ret == 0 && !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) { DEBUG(0,("'%s' is not a directory, when connecting to " "[%s]\n", conn->connectpath, lp_servicename(snum))); @@ -1144,7 +1016,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->connectpath, lp_servicename(snum), strerror(errno) )); } - *status = NT_STATUS_BAD_NETWORK_NAME; + *pstatus = NT_STATUS_BAD_NETWORK_NAME; goto err_root_exit; } @@ -1167,20 +1039,20 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, } #endif + if (lp_unix_extensions() && lp_widelinks(snum)) { + DEBUG(0,("Share '%s' has wide links and unix extensions enabled. " + "These parameters are incompatible. " + "Disabling wide links for this share.\n", + lp_servicename(snum) )); + lp_do_parameter(snum, "wide links", "False"); + } + /* Figure out the characteristics of the underlying filesystem. This * assumes that all the filesystem mounted withing a share path have * the same characteristics, which is likely but not guaranteed. */ - { - vfs_statvfs_struct svfs; - conn->fs_capabilities = - FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES; - - if (SMB_VFS_STATVFS(conn, conn->connectpath, &svfs) == 0) { - conn->fs_capabilities = svfs.FsCapabilities; - } - } + conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res); /* * Print out the 'connected as' stuff here as we need @@ -1191,9 +1063,10 @@ 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", srv_is_signing_active() ? "signed " : ""); + dbgtext( "%s", srv_is_signing_active(smbd_server_conn) ? "signed " : ""); dbgtext( "connect to service %s ", lp_servicename(snum) ); - dbgtext( "initially as user %s ", user ); + dbgtext( "initially as user %s ", + conn->server_info->unix_name ); dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() ); dbgtext( "(pid %d)\n", (int)sys_getpid() ); } @@ -1203,7 +1076,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, return(conn); err_root_exit: - + TALLOC_FREE(smb_fname_cpath); change_to_root_user(); if (on_err_call_dis_hook) { /* Call VFS disconnect hook */ @@ -1214,45 +1087,14 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, return NULL; } -/*************************************************************************************** - Simple wrapper function for make_connection() to include a call to - vfs_chdir() - **************************************************************************************/ - -connection_struct *make_connection_with_chdir(const char *service_in, - DATA_BLOB password, - const char *dev, uint16 vuid, - NTSTATUS *status) -{ - connection_struct *conn = NULL; - - conn = make_connection(service_in, password, dev, vuid, status); - - /* - * make_connection() does not change the directory for us any more - * so we have to do it as a separate step --jerry - */ - - 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", - conn->connectpath,strerror(errno))); - yield_connection(conn, lp_servicename(SNUM(conn))); - conn_free(conn); - *status = NT_STATUS_UNSUCCESSFUL; - return NULL; - } - - return conn; -} - /**************************************************************************** Make a connection to a service. * * @param service ****************************************************************************/ -connection_struct *make_connection(const char *service_in, DATA_BLOB password, +connection_struct *make_connection(struct smbd_server_connection *sconn, + const char *service_in, DATA_BLOB password, const char *pdev, uint16 vuid, NTSTATUS *status) { @@ -1273,13 +1115,13 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, smb_panic("make_connection: PANIC ERROR. Called as nonroot\n"); } - if (conn_num_open() > 2047) { + if (conn_num_open(sconn) > 2047) { *status = NT_STATUS_INSUFF_SERVER_RESOURCES; return NULL; } if(lp_security() != SEC_SHARE) { - vuser = get_valid_user_struct(vuid); + vuser = get_valid_user_struct(sconn, vuid); if (!vuser) { DEBUG(1,("make_connection: refusing to connect with " "no session setup\n")); @@ -1310,7 +1152,8 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, } DEBUG(5, ("making a connection to [homes] service " "created at session setup time\n")); - return make_connection_snum(vuser->homes_snum, + return make_connection_snum(sconn, + vuser->homes_snum, vuser, no_pw, dev, status); } else { @@ -1320,14 +1163,15 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, fstring unix_username; fstrcpy(unix_username, current_user_info.smb_name); - map_username(unix_username); + map_username(sconn, unix_username); snum = find_service(unix_username); } if (snum != -1) { DEBUG(5, ("making a connection to 'homes' " "service %s based on " "security=share\n", service_in)); - return make_connection_snum(snum, NULL, + return make_connection_snum(sconn, + snum, NULL, password, dev, status); } @@ -1338,7 +1182,8 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, DATA_BLOB no_pw = data_blob_null; DEBUG(5, ("making a connection to 'homes' service [%s] " "created at session setup time\n", service_in)); - return make_connection_snum(vuser->homes_snum, + return make_connection_snum(sconn, + vuser->homes_snum, vuser, no_pw, dev, status); } @@ -1357,7 +1202,7 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, return NULL; } - DEBUG(0,("%s (%s) couldn't find service %s\n", + DEBUG(3,("%s (%s) couldn't find service %s\n", get_remote_machine_name(), client_addr(get_client_fd(),addr,sizeof(addr)), service)); @@ -1376,7 +1221,7 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, DEBUG(5, ("making a connection to 'normal' service %s\n", service)); - return make_connection_snum(snum, vuser, + return make_connection_snum(sconn, snum, vuser, password, dev, status); } @@ -1387,10 +1232,9 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, void close_cnum(connection_struct *conn, uint16 vuid) { - if (IS_IPC(conn)) { - pipe_close_conn(conn); - } else { - file_close_conn(conn); + file_close_conn(conn); + + if (!IS_IPC(conn)) { dptr_closecnum(conn); } @@ -1413,10 +1257,12 @@ void close_cnum(connection_struct *conn, uint16 vuid) if (*lp_postexec(SNUM(conn)) && change_to_user(conn, vuid)) { char *cmd = talloc_sub_advanced(talloc_tos(), - lp_servicename(SNUM(conn)), conn->user, - conn->connectpath, conn->gid, - get_current_username(), - current_user_info.domain, + lp_servicename(SNUM(conn)), + conn->server_info->unix_name, + conn->connectpath, + conn->server_info->utok.gid, + conn->server_info->sanitized_username, + pdb_get_domain(conn->server_info->sam_account), lp_postexec(SNUM(conn))); smbrun(cmd,NULL); TALLOC_FREE(cmd); @@ -1427,10 +1273,12 @@ void close_cnum(connection_struct *conn, uint16 vuid) /* execute any "root postexec = " line */ if (*lp_rootpostexec(SNUM(conn))) { char *cmd = talloc_sub_advanced(talloc_tos(), - lp_servicename(SNUM(conn)), conn->user, - conn->connectpath, conn->gid, - get_current_username(), - current_user_info.domain, + lp_servicename(SNUM(conn)), + conn->server_info->unix_name, + conn->connectpath, + conn->server_info->utok.gid, + conn->server_info->sanitized_username, + pdb_get_domain(conn->server_info->sam_account), lp_rootpostexec(SNUM(conn))); smbrun(cmd,NULL); TALLOC_FREE(cmd);