Access Based Share Enum in samba on Macos - macos

I'm trying to set up a samba server on an M1 Mac. Have installed samba via homebrew.
Users and groups have been added to the OS, and then users added to samba via smbpasswd.
Everything works as expected. Users are allowed into shares to which their groups have permissions (using groups on the directory) and denied when they don't. So far, so good.
Everything breaks when I try to hide shares the user doesn't have access to, by adding 'access based share enum = yes' to the global section in smb.conf.
Then client returns an error saying "There are no shares available or you are not allowed to access them on the server."
The frustrating bit is that I have had it working, but I'm starting to lose the will!
Any suggestions?
smb.conf below
[global]
workgroup = WORKGROUP
security = user
passdb backend = tdbsam
inherit permissions = yes
inherit owner = yes
ea support = yes
min protocol = SMB2
vfs objects = fruit streams_xattr
#fruit:metadata = stream
#fruit:model = MacSamba
#fruit:posix_rename = yes
#fruit:wipe_intentionally_left_blank_rfork = yes
#fruit:veto_appledouble = no
#fruit:delete_empty_adfiles = yes
access based share enum = yes
max log size = 100000
[IT_application]
path = /Volumes/WORKFLOW/data/shares/IT
valid users = #workflow_it
force group = workflow_it
read only = no
browseable = yes
public = no
writeable = yes

what happens when you remove the valid users = #workflow_it & force group = workflow_it option?

There was a regression related to reading the share_info.tdb file. It was fixed a few weeks ago so it should show up in the 4.16.9 and 4.17.5 releases.
https://bugzilla.samba.org/show_bug.cgi?id=15265
While I wouldn't recommend it in a production system I can confirm that chmod 666 on share_info.tdb does in fact restore the expected behavior.

Related

LogonUser API doesn't work correctly with Domain from Workstation

For test I have setup a simple domain and added some users. I have Win10 workstation(s) NOT joined to that domain as well. I can access the DC with from the workstations with no issues by supplying a domain username and password to see file shares through Window's explorer. I can even use LDAP from vb.net to authenticate DC accounts.
I am trying to use the LOGONUSER API (all flavors tried) in an attempt to validate a domain account (local accounts validate OK) from a workstation NOT joined to that domain. Whatever flag/combo I use, it always returns false (failed logon). The only time I get a success is when use the flag NEW_CREDENTIALS but that supposedly returns a true value by default even with invalid credentials. Apparently From reading other posts related to using LogonUser API from a workstation computer to a domain controller nobody can seem to get it to work. I have even tried it on our corp. domains with no luck. However, the program I wrote (borrowed /tried code from several sources) works fine if I put it on any computer already joined to the domain, and it will even authenticate across domains that have a full trust between them. It just will not work from non-domain workstation to a domain. What needs to be done to make this work? I can't find any official documents that say it won't work, which would be great if I could find they exist. Thanks for your time..
<DllImport("advapi32.dll", SetLastError:=True)> _
Private Shared Function LogonUser(ByVal lpszUsername As String, ByVal lpszDomain As String, ByVal lpszPassword As String,
ByVal dwLogonType As LogonType, ByVal dwLogonProvider As LogonProvider, ByRef phToken As IntPtr) As Boolean
End Function
Enum LogonType As Integer
LOGON32_LOGON_INTERACTIVE = 2
LOGON32_LOGON_NETWORK = 3
LOGON32_LOGON_BATCH = 4
LOGON32_LOGON_SERVICE = 5
LOGON32_LOGON_UNLOCK = 7
LOGON32_LOGON_NETWORK_CLEARTEXT = 8
LOGON32_LOGON_NEW_CREDENTIALS = 9
End Enum
Enum LogonProvider As Integer
LOGON32_PROVIDER_DEFAULT = 0
LOGON32_PROVIDER_WINNT35 = 1
LOGON32_PROVIDER_WINNT40 = 2
LOGON32_PROVIDER_WINNT50 = 3
End Enum
public sub TryLogon()
Dim token As New IntPtr
Dim Username as string = "myuser",domain as string = "mydomain.local",password as string = "password"
Dim retVal = LogonUser(Username, domain, Password, LogonType.LOGON32_LOGON_NETWORK, LogonProvider.LOGON32_PROVIDER_DEFAULT, token)
If retVal = False Then
Dim errMsg = New System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()).Message
MsgBox(errMsg, MsgBoxStyle.Critical, "Logon")
End If
end sub
LogonUser() requires that the current user has the "Act as a part of the operating system" privilege. By default, it's granted to no one, not even the administrators.
EDIT: before LogonUser, you need to call AdjustTokenPrivileges() - add the SE_TCB_NAME privilege to the current user.
EDIT: I'll have to check, but I don't think LogonUser was meant for authenticating users from untrusted authorities (e. g. domains that the current machine is not on).
Consider creating a dummy share on one of the domain machines (maybe the domain controller), and calling WNetAddConnection2() against it.
I solved my problem on Windows 10 (1607) that was not connected to the domain by:
- using "." as domain
- LOGON32_LOGON_INTERACTIVE
- LOGON32_PROVIDER_DEFAULT
Just to let you know.
The following post put me on track: LogonUser() not authenticating user for invalid domain when computer is not on a domain

RSQLite does not create local database

Reprex:
con <- DBI::dbConnect(RSQLite::SQLite(), path = "test.sqlite")
dbWriteTable(con, "mtcars", mtcars)
dbListTables(con)
[1] "mtcars"
dbDisconnect(con)
When I come back:
con <- DBI::dbConnect(RSQLite::SQLite(), path = "test.sqlite")
dbListTables(con)
character(0)
I thought dbConnect should create a database if none exists. I don't know what is going on.
To create a local database you still need to supply parameters specific to your machine. This fixed the issue for me:
con <- DBI::dbConnect(RSQLite::SQLite(),
user = 'root',
password = '',
dbname = 'test.sqlite',
host = 'localhost')
This is documented poorly if you do not have much understanding of SQLite databases. It seems a database was only being created in memory. Maybe someone else can expound on this as I think warnings would help guide users in this situation.

Adding members to security group: SetInfo returns error 80070005

Background
I working on (modifying) a vbscript intended to create an AD shadow group formed by all users of several OU's.
The script logs into a remote AD, using alternate credentials.Note: The user I log in as, have full AD read access, but only inherited write access to the OU containing the group I'm adding members to.
Problematic code
The script is easily able to log in, scan for users on the OU's, open the shadow group and list it's current members, perform compares and locate the users to add and remove....but...
the actual adding (and removing) of members to the named security group fails, Error: 80070005 Srce: Active Directory Desc: Access is denied., when I apply .SetInfo.
I'm using this code to read and write:
aMembers = oGroup.GetEx("member") ' This gets populated as it should.
oGroup.PutEx ADS_PROPERTY_APPEND, "member", Array("CN=Doe\, John [LOCATION/COUNTRY],OU=foo,OU=bar,OU=Country,DC=domain,DC=org")
oGroup.SetInfo ' This fails
Just in case this is related to how I log into the AD, here's the code:
' Open an ADO connection using full credentials
Set oConnection = CreateObject("ADODB.Connection")
oConnection.Provider = "ADsDSOObject"
oConnection.Properties("User ID") = sLDAP_USER ' "domain\user"
oConnection.Properties("Password") = sLDAP_PASS ' "pass!word"
oConnection.Properties("Encrypt Password") = True
oConnection.Properties("ADSI Flag") = ADS_SECURE_AUTHENTICATION Or ADS_SERVER_BIND
oConnection.Open "Active Directory Provider"
Verifying my login users rights
I've seen lots of similar posts with this sort of error, and have only seen answers stating that this is a permission problem - however never seen a description of what permission was missing/wrong. The Access is denied error really made me doubt that the login I used had the right permissions, so I attempted to add members to the group by using JXplore. It works, but only if I enable the option to ignore schema checking (Based on online advice, when using JXplore with AD instead of pure LDAP).
Edit: Without ignoring the schema checking, the following properties are also requested to be populated: instanceType, nTSecurityDescriptor and objectCatagory, but I notice they are blank on existing users.
Questions
Did I fall into an obvious pitfall?
Do I also somehow need to ignore the schema in my script? If so, how to do that?

get the operating system of an Amazon image via Fog

My end goal is to get the operating system of an Amazon image. When I do:
connection = Fog::Compute.new(provider: 'AWS',
aws_access_key_id: 'blah',
aws_secret_access_key: 'thing')
images = connection.describe_images('Owner' => 'self').body['imagesSet']
The data I get returned does not include platform, as this documentation suggests. However, I do get values like:
architecture: "x86_64",
imageType: "machine",
kernelId: "aki-825ea7eb",
And if I Google for that kernel ID I find this page saying it's Linux. Is there a way I can pass kernelId to Amazon via Fog and get back data about that kernelId, such as linux?
On a separate note, sometimes my images don't have kernelId, so are there any other fields in a <DescribeImagesResponse xmlns="http://ec2.amazonaws.com/doc/2012-12-01/"> that are definite indicators of operating system?
Here's a solution if you have the Kernel ID using http://thecloudmarket.com.
Pass the Kernel ID to a variable in ruby.
ker_id = imagesSet
url = []
url_0 = "http://thecloudmarket.com/image/"
url_1 = "ker_id"
url_2 = "#/definition"
new_url = url_0 + url_1 _ url_2
There are many ways to forge this url just made it easy to read.
Then use nokogiri to parse the webpage and put the image name back into your script.
I didn't see another notifiers in the documentation.

How do I write a script to modify the password expiration values for users on a Windows Server?

I need to create several users on Windows 2008 servers and modify the password expiration value to "Never". These will be local (not AD) users. I can create them using "net user", it's modifying the pass expiry that is killing me. If I do a "net user username" it lists the field and its value, but there is no switch (at least not one that the help file references) to modify it, and most of the solutions I saw online suggested installing 3rd party tools, however this solution must be native to Windows (ideally using Powershell). Any help is appreciated.
UPDATE
I said if I figured out how to do this in Powershell I would post it here, and I am a man of my word.
Get-WmiObject -Class Win32_UserAccount -Filter "name = 'steve'" | Set-WmiInstance -Argument #{PasswordExpires = 0}
This is a boolean value so if you wanted to set a password to expire just change 0 to 1. This is beautiful to me in its simplicity, and I have tested this method updating other WMI objects and it works every time.
The simple solution is to create a batch file that issues the following command:
net accounts /maxpwage:unlimited
However, that will set the maximum password age for all accounts on the local machine to unlimited, not just the new accounts that you have created.
If you need a finer level of control (i.e., the ability to set the password expiration values for individual users), you'll need something a little more complicated. The Scripting Guys share an example of a VBScript that will modify a local user account so that its password never expires:
Const ADS_UF_DONT_EXPIRE_PASSWD = &h10000
strDomainOrWorkgroup = "Fabrikam"
strComputer = "atl-win2k-01"
strUser = "KenMeyer"
Set objUser = GetObject("WinNT://" & strDomainOrWorkgroup & "/" & _
strComputer & "/" & strUser & ",User")
objUserFlags = objUser.Get("UserFlags")
objPasswordExpirationFlag = objUserFlags OR ADS_UF_DONT_EXPIRE_PASSWD
objUser.Put "userFlags", objPasswordExpirationFlag
objUser.SetInfo
It would be easy to modify this to work for any user of your choice, or even to create a new user.
Finally, here's an example in C#, which you should be able to port to PowerShell. I'm not much of a PS expert, but considering it uses the .NET Framework, the above code should give you some ideas.
From this technet thread.
$computer = $env:Computername
$account = ([adsi]"WinNT://$computer/TestAccount")
$account.PasswordExpired = 1
$account.psbase.commitchanges()
You can add the domain before the computer name if you need to.
Set password never expires for local user. Do not change other flags:
$ADS_UF_DONT_EXPIRE_PASSWD = 0x10000
$username = 'user'
$user = [adsi] "WinNT://./$username"
$user.UserFlags = $user.UserFlags[0] -bor $ADS_UF_DONT_EXPIRE_PASSWD
$user.SetInfo()
ADS_USER_FLAG_ENUM enumeration
works for me:
WMIC USERACCOUNT WHERE "Name='ftpuser'" SET PasswordExpires=FALSE
replace ftpuser with correct user name
The other solutions weren't working for me so I tweaked Jason's solution to:
$svrname = $env:computername
$user = ([adsi]"WinNT://$svrname/Administrator")
$user.userflags = 66049
$user.psbase.commitchanges()
The userflags value determines what tickboxes are checked for the user - this one is a basic "password doesn't expire" value. Can't seem to work out how it the numbers go together, the below may be useful but according to that I've got a reserved value enabled which doesn't make sense.
http://www.selfadsi.org/ads-attributes/user-userAccountControl.htm
Instead I just enabled the options I needed on a test box and retrieved the value. Is the most reliable means of determining what you need I guess.
I took Deadly-Bagel's solution and it didn't work, until I made a small change. See below:
$svrname = $env:computername
$user = ([adsi]"WinNT://$svrname/Administrator")
$user.psbase.InvokeSet("userflags", 66049)
$user.psbase.commitchanges()

Resources