Creating an access point with wpa_supplicant via dbus interface - linux

I was told that it's possible to create an access point with wpa_supplicant over its dbus interface. All I found with a google is this forum thread, which, despite having exact same title, isn't much informative to me.
Is it possible to do this via wpa_supplicant dbus interface and what exact steps does it take to create one with custom parameters (like frequency, etc.)?

After all, I've found a way to launch access point with wpa_supplicant's dbus inteface. Below is pretty self explanatory python code that's is trying to launch AP with the first interface (adapter) it have found.
import dbus
import sys
ssid = "TEST_WPA_DBUS_HOTSPOT"
frequency = 2412
bus = dbus.SystemBus()
wpa_sup_obj = bus.get_object('fi.w1.wpa_supplicant1', '/fi/w1/wpa_supplicant1')
props_iface = dbus.Interface(wpa_sup_obj, "org.freedesktop.DBus.Properties")
interfaces = props_iface.Get('fi.w1.wpa_supplicant1', "Interfaces")
try:
interface = interfaces[0]
except IndexError:
sys.exit("No interfaces availible")
print "Creating ap with %s" % (interface)
interface_obj = bus.get_object('fi.w1.wpa_supplicant1', interface)
interface_interface_props = dbus.Interface(interface_obj, "org.freedesktop.DBus.Properties")
interface_interface = dbus.Interface(interface_obj, "fi.w1.wpa_supplicant1.Interface")
adapters_name = interface_interface_props.Get("fi.w1.wpa_supplicant1.Interface", "Ifname")
print "Interface's name is %s" % adapters_name
key_mgmt = "NONE"
args = dbus.Dictionary({
'ssid': ssid,
'key_mgmt': key_mgmt,
'mode': 2,
'frequency': frequency
}, signature='sv')
netw = interface_interface.AddNetwork(args)
interface_interface.SelectNetwork(netw)
print "AP %s with frequency %i created with adapter %s" % ( ssid, frequency, adapters_name)
Note, that, after all, I've found wpa_supplicant not quite reliable for my needs (in my particular case, I wasn't able to launch 5GHz AP) and have switched to launching hostapd with different configuration files.

Related

How to specify AdressType in bluez device-api?

I'm trying to connect a LE device to my Linux laptop through a python script. Nevertheless, the device address must be specified as "random" for the connection to happen, and the examples that I have (mainly https://www.bluetooth.com/blog/the-bluetooth-for-linux-developers-study-guide/) doesn't show any way of doing it.
The device-api from BlueZ (https://github.com/bluez/bluez/blob/master/doc/device-api.txt) list it as one of its properties, but my knowledge is still incomplete, and I couldn't manage to find a way of setting this property.
Any idea, indication or example will be immensely helpful.
Following is my script
PATH_DA_BSN = "/org/bluez/hci0/dev_CA_DB_17_8A_02_97"
ADAPTER_NAME = "hci0"
BLUEZ_SERVICE_NAME = "org.bluez"
BLUEZ_NAMESPACE = "/org/bluez/"
DEVICE_INTERFACE = BLUEZ_SERVICE_NAME + ".Device1"
ADAPTER_INTERFACE = BLUEZ_SERVICE_NAME + ".Adapter1"
def connect():
global bus
global device_interface
try:
device_interface.Connect()
except Exception as e:
print("Failed to connect")
print(e.get_dbus_name())
print(e.get_dbus_message())
if ("UnknownObject" in e.get_dbus_name()):
print("Try scanning first to resolve this problem")
return bluetooth_constants.RESULT_EXCEPTION
else:
print("Connected OK")
return bluetooth_constants.RESULT_OK
bus = dbus.SystemBus()
bsn_proxy = bus.get_object(BLUEZ_SERVICE_NAME, PATH_DA_BSN)
device_interface = dbus.Interface(bsn_proxy, DEVICE_INTERFACE)
adapter_path = BLUEZ_NAMESPACE + ADAPTER_NAME
# acquire the adapter interface so we can call its methods
adapter_object = bus.get_object(BLUEZ_SERVICE_NAME, adapter_path)
adapter_interface = dbus.Interface(adapter_object, ADAPTER_INTERFACE)
print("Connecting to " + PATH_DA_BSN)
connect()
The AddressType is already set from when the device was discovered.
You can iterate through the already discovered devices using D-Bus's GetManagedObjects functionality to find what the address type is set to for each device.
An example using the pydbus bindings:
>>> import pydbus
>>> bus = pydbus.SystemBus()
>>> mngr = bus.get('org.bluez', '/')
>>> mngd_objs = mngr.GetManagedObjects()
>>> for path, iface in mngd_objs.items():
... if 'org.bluez.Device1' in iface.keys():
... print(iface.get('org.bluez.Device1', {}).get('AddressType'))
...
public
random
random
public
public
public
random
public
public
public
random
you have 2 options:
Do a discovery and connect when the device is found. In this case Bluez will already know the addresstype.
Call the method ConnectDevice which is available on an adapter. In this method you can pass the ‘random’ parameter. Keep in mind this method is marked as experimental.
I recommend option 1

Ble dbus python: advertise ServiceUUIDs information

Background: I want to use ble for server/client software. But in this case, the server should be the peripheral with multiple connections. For that i start multiple services, up to 10. I think that's the limit for peripheral connections on my chip. The different services are the same in functionality but should connect to only one client. I see no other possibility to differentiate the clients in the notification function.
Problem: For that i restart the advertising after each connection. In the advertisement, I set the uuid information field “ServiceUUIDs” for the next free service to connect. This is working after restarting my pc. In my flutter app, I’m able to read this field perfectly in the advertisment. But when I restart the python script, the uuid is no longer advertised and the field “ServiceUUIDs” is empty although {'Type': 'peripheral', 'ServiceUUIDs': dbus.Array(['0000ac01-0000-1000-8000-00805f9b34fb'], signature=dbus.Signature('s')), 'LocalName': dbus.String('Hello'), 'Discoverable': dbus.Boolean(True)} is set in the bluetooth_constants.ADVERTISING_MANAGER_INTERFACE. Also restarting the bluetooth module is not working. Therefore I must restart my pc everytime I want to restart my server... After connecting to the server, the client can scan all services and does not know, which one of the 10 services is free to connect.
My python code is the same as in the dbus tutorial:
class Advertisement(dbus.service.Object):
PATH_BASE = '/org/bluez/ldsg/advertisement'
def __init__(self, bus, index, advertising_type):
self.path = self.PATH_BASE + str(index)
self.bus = bus
self.ad_type = advertising_type
self.service_uuids = ['0000ac01-0000-1000-8000-00805f9b34fb']
self.manufacturer_data = None
self.solicit_uuids = None
self.service_data = None
self.local_name = 'Hello'
self.include_tx_power = False
self.data = None #{0x26: dbus.Array([0x01, 0x01, 0x01], signature='y')}
self.discoverable = True
dbus.service.Object.__init__(self, bus, self.path)
def get_properties(self):
properties = dict()
properties['Type'] = self.ad_type
if self.service_uuids is not None:
properties['ServiceUUIDs'] = dbus.Array(self.service_uuids,
signature='s')
if self.solicit_uuids is not None:
properties['SolicitUUIDs'] = dbus.Array(self.solicit_uuids,
signature='s')
if self.manufacturer_data is not None:
properties['ManufacturerData'] = dbus.Dictionary(
self.manufacturer_data, signature='qv')
if self.service_data is not None:
properties['ServiceData'] = dbus.Dictionary(self.service_data,
signature='sv')
if self.local_name is not None:
properties['LocalName'] = dbus.String(self.local_name)
if self.discoverable is not None and self.discoverable == True:
properties['Discoverable'] = dbus.Boolean(self.discoverable)
if self.include_tx_power:
properties['Includes'] = dbus.Array(["tx-power"], signature='s')
if self.data is not None:
properties['Data'] = dbus.Dictionary(
self.data, signature='yv')
print(properties)
return {bluetooth_constants.ADVERTISING_MANAGER_INTERFACE: properties}
def start_advertising():
global adv
global adv_mgr_interface
# we're only registering one advertisement object so index (arg2) is hard coded as 0
print("Registering advertisement",adv.get_path())
adv_mgr_interface.RegisterAdvertisement(adv.get_path(), {},
reply_handler=register_ad_cb,
error_handler=register_ad_error_cb)
bus = dbus.SystemBus()
adv_mgr_interface = dbus.Interface(bus.get_object(bluetooth_constants.BLUEZ_SERVICE_NAME,adapter_path), bluetooth_constants.ADVERTISING_MANAGER_INTERFACE)
adv = Advertisement(bus, 0, 'peripheral')
start_advertising()
Maybe there is an other way to send additional information in the advertisment? I also tried "Data" and "ServiceData" but then the advertisement throws an error. I haven't found a good tutorial for this. I'm only looking for a stable way to give the additional information for the next free service in the advertisment.
Thank You!

Getting owner of file from smb share, by using python on linux

I need to find out for a script I'm writing who is the true owner of a file in an smb share (mounted using mount -t cifs of course on my server and using net use through windows machines).
Turns out it is a real challenge finding this information out using python on a linux server.
I tried using many many smb libraries (such as smbprotocol, smbclient and others), nothing worked.
I find few solutions for windows, they all use pywin32 or another windows specific package.
And I also managed to do it from bash using smbcalcs but couldn't do it cleanly but using subprocess.popen('smbcacls')..
Any idea on how to solve it?
This was unbelievably not a trivial task, and unfortunately the answer isn't simple as I hoped it would be..
I'm posting this answer if someone will be stuck with this same problem in the future, but hope maybe someone would post a better solution earlier
In order to find the owner I used this library with its examples:
from smb.SMBConnection import SMBConnection
conn = SMBConnection(username='<username>', password='<password>', domain=<domain>', my_name='<some pc name>', remote_name='<server name>')
conn.connect('<server name>')
sec_att = conn.getSecurity('<share name>', r'\some\file\path')
owner_sid = sec_att.owner
The problem is that pysmb package will only give you the owner's SID and not his name.
In order to get his name you need to make an ldap query like in this answer (reposting the code):
from ldap3 import Server, Connection, ALL
from ldap3.utils.conv import escape_bytes
s = Server('my_server', get_info=ALL)
c = Connection(s, 'my_user', 'my_password')
c.bind()
binary_sid = b'....' # your sid must be in binary format
c.search('my_base', '(objectsid=' + escape_bytes(binary_sid) + ')', attributes=['objectsid', 'samaccountname'])
print(c.entries)
But of course nothing will be easy, it took me hours to find a way to convert a string SID to binary SID in python, and in the end this solved it:
# posting the needed functions and omitting the class part
def byte(strsid):
'''
Convert a SID into bytes
strdsid - SID to convert into bytes
'''
sid = str.split(strsid, '-')
ret = bytearray()
sid.remove('S')
for i in range(len(sid)):
sid[i] = int(sid[i])
sid.insert(1, len(sid)-2)
ret += longToByte(sid[0], size=1)
ret += longToByte(sid[1], size=1)
ret += longToByte(sid[2], False, 6)
for i in range(3, len(sid)):
ret += cls.longToByte(sid[i])
return ret
def byteToLong(byte, little_endian=True):
'''
Convert bytes into a Python integer
byte - bytes to convert
little_endian - True (default) or False for little or big endian
'''
if len(byte) > 8:
raise Exception('Bytes too long. Needs to be <= 8 or 64bit')
else:
if little_endian:
a = byte.ljust(8, b'\x00')
return struct.unpack('<q', a)[0]
else:
a = byte.rjust(8, b'\x00')
return struct.unpack('>q', a)[0]
... AND finally you have the full solution! enjoy :(
I'm adding this answer to let you know of the option of using smbprotocol; as well as expand in case of misunderstood terminology.
SMBProtocol Owner Info
It is possible to get the SID using the smbprotocol library as well (just like with the pysmb library).
This was brought up in the github issues section of the smbprotocol repo, along with an example of how to do it. The example provided is fantastic and works perfectly. An extremely stripped down version
However, this also just retrieves a SID and will need a secondary library to perform a lookup.
Here's a function to get the owner SID (just wrapped what's in the gist in a function. Including here in case the gist is deleted or lost for any reason).
import smbclient
from ldap3 import Server, Connection, ALL,NTLM,SUBTREE
def getFileOwner(smb: smbclient, conn: Connection, filePath: str):
from smbprotocol.file_info import InfoType
from smbprotocol.open import FilePipePrinterAccessMask,SMB2QueryInfoRequest, SMB2QueryInfoResponse
from smbprotocol.security_descriptor import SMB2CreateSDBuffer
class SecurityInfo:
# 100% just pulled from gist example
Owner = 0x00000001
Group = 0x00000002
Dacl = 0x00000004
Sacl = 0x00000008
Label = 0x00000010
Attribute = 0x00000020
Scope = 0x00000040
Backup = 0x00010000
def guid2hex(text_sid):
"""convert the text string SID to a hex encoded string"""
s = ['\\{:02X}'.format(ord(x)) for x in text_sid]
return ''.join(s)
def get_sd(fd, info):
""" Get the Security Descriptor for the opened file. """
query_req = SMB2QueryInfoRequest()
query_req['info_type'] = InfoType.SMB2_0_INFO_SECURITY
query_req['output_buffer_length'] = 65535
query_req['additional_information'] = info
query_req['file_id'] = fd.file_id
req = fd.connection.send(query_req, sid=fd.tree_connect.session.session_id, tid=fd.tree_connect.tree_connect_id)
resp = fd.connection.receive(req)
query_resp = SMB2QueryInfoResponse()
query_resp.unpack(resp['data'].get_value())
security_descriptor = SMB2CreateSDBuffer()
security_descriptor.unpack(query_resp['buffer'].get_value())
return security_descriptor
with smbclient.open_file(filePath, mode='rb', buffering=0,
desired_access=FilePipePrinterAccessMask.READ_CONTROL) as fd:
sd = get_sd(fd.fd, SecurityInfo.Owner | SecurityInfo.Dacl)
# returns SID
_sid = sd.get_owner()
try:
# Don't forget to convert the SID string-like object to a string
# or you get an error related to "0" not existing
sid = guid2hex(str(_sid))
except:
print(f"Failed to convert SID {_sid} to HEX")
raise
conn.search('DC=dell,DC=com',f"(&(objectSid={sid}))",SUBTREE)
# Will return an empty array if no results are found
return [res['dn'].split(",")[0].replace("CN=","") for res in conn.response if 'dn' in res]
to use:
# Client config is required if on linux, not if running on windows
smbclient.ClientConfig(username=username, password=password)
# Setup LDAP session
server = Server('mydomain.com',get_info=ALL,use_ssl = True)
# you can turn off raise_exceptions, or leave it out of the ldap connection
# but I prefer to know when there are issues vs. silently failing
conn = Connection(server, user="domain\username", password=password, raise_exceptions=True,authentication=NTLM)
conn.start_tls()
conn.open()
conn.bind()
# Run the check
fileCheck = r"\\shareserver.server.com\someNetworkShare\someFile.txt"
owner = getFileOwner(smbclient, conn, fileCheck)
# Unbind ldap session
# I'm not clear if this is 100% required, I don't THINK so
# but better safe than sorry
conn.unbind()
# Print results
print(owner)
Now, this isn't super efficient. It takes 6 seconds for me to run this one a SINGLE file. So if you wanted to run some kind of ownership scan, then you probably want to just write the program in C++ or some other low-level language instead of trying to use python. But for something quick and dirty this does work. You could also setup a threading pool and run batches. The piece that takes longest is connecting to the file itself, not running the ldap query, so if you can find a more efficient way to do that you'll be golden.
Terminology Warning, Owner != Creator/Author
Last note on this. Owner != File Author. Many domain environments, and in particular SMB shares, automatically alter ownership from the creator to a group. In my case the results of the above is:
What I was actually looking for was the creator of the file. File creator and modifier aren't attributes which windows keeps track of by default. An administrator can enable policies to audit file changes in a share, or auditing can be enabled on a file-by-file basis using the Security->Advanced->Auditing functionality for an individual file (which does nothing to help you determine the creator).
That being said, some applications store that information for themselves. For example, if you're looking for Excel this answer provides a method for which to get the creator of any xls or xlsx files (doesn't work for xlsb due to the binary nature of the files). Unfortunately few files store this kind of information. In my case I was hoping to get that info for tblu, pbix, and other reporting type files. However, they don't contain this information (which is good from a privacy perspective).
So in case anyone finds this answer trying to solve the same kind of thing I did - Your best bet (to get actual authorship information) is to work with your domain IT administrators to get auditing setup.

Obtain bluetooth signal strength on Raspberry Pi of BT device without pairing

I like to create a kind of indoor-tracking-system for my already existing home automation system. I thought of using BLE. I already successfully set up hcitool on my Raspberry Pi and I can connect to my iPhone without any problems. But how can I obtain the signal strength between my Raspberry Pi and my iPhone without connecting them. I already tried to use sudo hcitool cc [BTADDRESS] to connect to my iPhone without authentication, but it looks like the iPhone don't allow those connection to stay open. I think that must be a way to get the signal strength without connecting both devices. I want to use it to determine the distance from my Raspberry Pi to my iPhone. May I am able to calculate the distance from the time I need to discover my iPhone?
There are two ways to go, and by now I have been able to get both work reliably only on Android devices.
Exploiting the Bluetooth friendly name of the smartphone and set the discoverability to infinite. I have done this writing a simple app. Works in background, also after that the app has been killed, since the discoverability setting is preserved. At the best of my knowledge, this is not possible in iOS.
Advertising a UUID in a BLE packet from the phone. This can be done by both Android and iOS devices. However, while in background, iPhones switch the advertising to a shrinked mode that makes the packet unidentifiable. The problem of identifying an advertising iOS devices in background is still open.
On the raspberry, I used PyBluez to scan and looking for the presence of smartphones running (1) or (2). I report a code example:
import bluetooth
import bluetooth._bluetooth as bluez
import struct, socket, sys, select
def hci_enable_le_scan(sock):
hci_toggle_le_scan(sock, 0x01)
#Discover name and RSS of enabled BLE devices
class MyDiscoverer(bluetooth.DeviceDiscoverer):
def pre_inquiry(self):
self.done = False
def device_discovered(self, address, device_class, rssi, name):
discovery_logger.info("Discovered %s" % (address, ))
if name == "YOUR-DEVICE-FRIENDLY_NAME":
#Use the RSS for your detection / localization system
def inquiry_complete(self):
self.done = True
#Performs inquiry for name request
def async_inquiry():
d = MyDiscoverer()
while True:
d.find_devices(lookup_names = True)
readfiles = [ d, ]
while True:
rfds = select.select( readfiles, [], [] )[0]
if d in rfds:
d.process_event()
if d.done:
break
time.sleep(DISCOVERY_INTERVAL)
#Parse received advertising packets
def parse_events(sock):
# save current filter
old_filter = sock.getsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, 14)
flt = bluez.hci_filter_new()
bluez.hci_filter_all_events(flt)
bluez.hci_filter_set_ptype(flt, bluez.HCI_EVENT_PKT)
sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, flt )
while True:
pkt = sock.recv(255)
ptype, event, plen = struct.unpack("BBB", pkt[:3])
if event == LE_META_EVENT:
subevent, = struct.unpack("B", pkt[3])
pkt = pkt[4:]
if subevent == EVT_LE_CONN_COMPLETE:
le_handle_connection_complete(pkt)
elif subevent == EVT_LE_ADVERTISING_REPORT:
#Check if the advertisement is the one we are searching for
if getASCII(pkt[start:end]) == "YOUR-UUID"
report_pkt_offset = 0
report_data_length, = struct.unpack("B", pkt[report_pkt_offset + 9])
# each report is 2 (event type, bdaddr type) + 6 (the address)
# + 1 (data length field) + report_data length + 1 (rssi)
report_pkt_offset = report_pkt_offset + 10 + report_data_length + 1
rssi, = struct.unpack("b", pkt[report_pkt_offset -1])
#Now you have the RSS indicator, use it for monitoring / localization
sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, old_filter )
dev_id = 0
try:
sock = bluez.hci_open_dev(dev_id)
except:
print "error accessing bluetooth device..."
sys.exit(1)
p = threading.Thread(group=None, target=parse_events, name='parsing', args=(sock, ))
d = threading.Thread(group=None, target=async_inquiry, name='async_inquiry', args=())
try:
p.start()
except:
print "Error: unable to start parsing thread"
try:
d.start()
except:
print "Error: unable to start asynchronous discovery thread"

How to capture probe request data or probe response data sent from wireless router

I have a tplink-wr703n wireless router with OpenWrt.
I know I can capture all kinds of data when the adapter is in monitor mode.
I want to the adapter work in master mode, and I also want to capture probe request data sent from client or probe response data sent from my router.
I have tried to use libpcap to capture data, but I failed.
Can you tell me how I can get that data?
You can set up several modes on one radio card simultaneously.
Using the "iw" command you should be able to create a secondary wifi device interface with type monitor, I guess you could read all frame types from this one.
See http://wireless.kernel.org/en/users/Documentation/iw/vif/
I am also trying to prepare a scapy script to capture probe request only.
there is an Indian guy who made this nice video:https://www.youtube.com/watch?v=Z1MbpIkzQjU
His script seems to work in his enviroment but for some reason I cant get this to work for me.
I will appreciate your assistance.
The script is:
#!/usr/bin/python
import sys
from scapy.all import *
clientprobes = set()
def PacketHandler(pkt):
if pkt.haslayer(Dot11ProbeReq):
if len(pkt.info) > 0:
testcase = pkt.addr2 + '_ _ _' + pkt.info
if testcase not in clientprobes:
clientprobes.add(testcase)
print "New Probe Found: " + pkt.addr2 + ' ' + pkt.info
print "\n-----------Client Probes Table-------------\n"
counter = 1
for probe in clientprobes:
[client, ssid] = probe.split('---')
print counter, client, ssid
counter = counter + 1
print "\n--------------------------------------------\n"
sniff(iface = sys.argv[1], count = int(sys.argv[2]), prn = PacketHandler)

Resources