X-Git-Url: http://git.samba.org/?a=blobdiff_plain;f=source3%2Fsmbd%2Fservice.c;h=8039d16586eb164f576f4c4def3a919aac6feff1;hb=bd269443e311d96ef495a9db47d1b95eb83bb8f4;hp=eb16a2601e312e76d90e63f3401fe781cf42c356;hpb=8ee0cc24b8302097bccae7891cb6f9c0547a1815;p=samba.git diff --git a/source3/smbd/service.c b/source3/smbd/service.c index eb16a2601e3..8039d16586e 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -56,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; } @@ -182,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); } @@ -220,16 +225,6 @@ 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; } @@ -242,79 +237,22 @@ static int load_registry_service(const char *servicename) return -2; } - if (asprintf(&path, "%s\\%s", KEY_SMBCONF, servicename) == -1) { - 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)) { + if (!process_registry_service(servicename)) { return -1; } - 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); - } - - 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; - } + process_registry_shares(); - for (i=0; W_ERROR_IS_OK(reg_enumkey(key, key, i, &name, NULL)); i++) { - load_registry_service(name); - TALLOC_FREE(name); - } - - TALLOC_FREE(key); return; } @@ -326,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) { @@ -368,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); @@ -382,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); } @@ -623,7 +562,8 @@ static NTSTATUS find_forced_group(bool force_user, Create an auth_serversupplied_info structure for a connection_struct ****************************************************************************/ -static NTSTATUS create_connection_server_info(TALLOC_CTX *mem_ctx, int snum, +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) @@ -677,11 +617,11 @@ static NTSTATUS create_connection_server_info(TALLOC_CTX *mem_ctx, int snum, /* add the sharename as a possible user name if we are in share mode security */ - add_session_user(lp_servicename(snum)); + add_session_user(sconn, lp_servicename(snum)); /* shall we let them in? */ - if (!authorise_login(snum,user,password,&guest)) { + if (!authorise_login(sconn, snum,user,password,&guest)) { DEBUG( 2, ( "Invalid username/password for [%s]\n", lp_servicename(snum)) ); return NT_STATUS_WRONG_PASSWORD; @@ -701,13 +641,14 @@ static NTSTATUS create_connection_server_info(TALLOC_CTX *mem_ctx, int snum, connecting user if appropriate. ****************************************************************************/ -static connection_struct *make_connection_snum(int snum, user_struct *vuser, - DATA_BLOB password, - const char *pdev, - NTSTATUS *pstatus) +connection_struct *make_connection_snum(struct smbd_server_connection *sconn, + int snum, user_struct *vuser, + DATA_BLOB password, + const char *pdev, + NTSTATUS *pstatus) { connection_struct *conn; - SMB_STRUCT_STAT st; + struct smb_filename *smb_fname_cpath = NULL; fstring dev; int ret; char addr[INET6_ADDRSTRLEN]; @@ -715,13 +656,12 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, NTSTATUS status; fstrcpy(dev, pdev); - SET_STAT_INVALID(st); 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")); *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES; @@ -730,12 +670,12 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->params->service = snum; - status = create_connection_server_info( + status = create_connection_server_info(sconn, conn, snum, vuser ? vuser->server_info : NULL, password, &conn->server_info); if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("create_connection_server_info failed: %s\n", + DEBUG(1, ("create_connection_server_info failed: %s\n", nt_errstr(status))); *pstatus = status; conn_free(conn); @@ -746,7 +686,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->force_user = true; } - add_session_user(conn->server_info->unix_name); + add_session_user(sconn, conn->server_info->unix_name); safe_strcpy(conn->client_address, client_addr(get_client_fd(),addr,sizeof(addr)), @@ -757,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) { @@ -777,7 +716,6 @@ 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,""); conn->read_only = lp_readonly(SNUM(conn)); conn->admin_user = False; @@ -1054,14 +992,21 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, /* 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))); @@ -1094,12 +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. */ - conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn); + conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res); /* * Print out the 'connected as' stuff here as we need @@ -1110,7 +1063,7 @@ 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 ", conn->server_info->unix_name ); @@ -1123,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 */ @@ -1140,7 +1093,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, * @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) { @@ -1161,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")); @@ -1198,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 { @@ -1208,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); } @@ -1226,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); } @@ -1245,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)); @@ -1264,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); }