Utoaji otomatiki wa Yealink T19 + kitabu cha anwani kinachobadilika

Nilipokuja kufanya kazi kwa kampuni hii, tayari nilikuwa na hifadhidata fulani ya vifaa vya IP, seva kadhaa zilizo na nyota na kiraka katika mfumo wa FreeBPX. Kwa kuongezea, analog PBX Samsung IDCS500 ilifanya kazi sambamba na, kwa ujumla, ilikuwa mfumo mkuu wa mawasiliano katika kampuni; Simu ya IP ilifanya kazi kwa idara ya uuzaji tu. Na kila kitu kingeendelea kupika kama hii, lakini siku moja nzuri amri ilitolewa kuhamisha kila mtu kwa simu ya IP, tarehe za mwisho zilikubaliwa, vifaa vilinunuliwa, na mpango wa kuhamisha biashara katika karne ya 21 ulianza kutekelezwa.
Jambo la kwanza ambalo linaanza kuwa na wasiwasi katika hali hiyo ni kuongezeka kwa kasi kwa idadi ya seti za simu zinazohitaji kusimamiwa kwa namna fulani, jambo la pili lililokuwa na wasiwasi sana ni kitabu cha simu. Ikiwa Endpoint Manager angeweza kutusaidia na ya kwanza (ambayo, kwa njia, ilikatwa kutoka kwa matoleo ya hivi karibuni ya FreePBX), basi maswali kadhaa yalizuka na kitabu:

  • Kwanza, jinsi ya kuhakikisha usahihi wake wakati eneo/umiminikaji wa watumiaji unabadilika kila mara?
  • Pili, jinsi ya kubinafsisha kabisa simu. Na si kujaza jina la mwasiliani kila wakati?

Tatizo lilikuwa la kuvutia, ufumbuzi haukuchukua muda mrefu kufika. Sasa nitatoa orodha kamili, na kisha tutaiangalia kwa utaratibu.

from scapy.all import sniff
from scapy.layers.inet import IP
import mysql.connector
import ldap
import getpass
import tftpy
import requests
import os
import time
from string import replace

def conn_ldap(login):
    ad = ldap.initialize('ldap://***.local')
    ad.simple_bind_s('voip@***.local', 'password')
    basedn = 'OU=IT,DC=***,DC=LOCAL'
    basedn_user = 'OU=***,OU=***,DC=***,DC=LOCAL'
    scope = ldap.SCOPE_SUBTREE
    filterexp = "(&(sAMAccountName=" + login + ")(ObjectClass=person))"
    filterexp2 = "(&(ObjectClass=organizationUnit))"
    attrlist = ['cn']
    attrlist2 = ['OU']
    search = ad.search_s(basedn, scope, filterexp, attrlist)
    adname = search[0][1]['cn'][0].decode('utf-8')
    if adname == ' ':
        search = ad.search_s(basedn_user, scope, filterexp2, attrlist2)
        for i in range(1, len(search)+1):
            group = search[i][1]['ou'][0]
            basedn_user2 = 'OU='+group+','+basedn_user
            search = ad.search_s(basedn_user2, scope, filterexp, attrlist)
            adname = search[0][1]['cn'][0].decode('utf-8')
            if adname != ' ':
                return adname
        adname = search[0][1]['cn'][0].decode('utf-8')
    ad.unbind_s()
    return adname


def tftp_file_change(config,place,adname,current_account,current_account_password):

    client = tftpy.TftpClient("192.168.0.3", 69)
    client.download('template.cfg', place)
    fileread = open(place, 'r')
    line = fileread.readlines()
    fileread.close()
    line[5] = (('account.1.label = ').encode('utf-8') + adname.encode('utf-8') + 'n')
    line[2] = (('account.1.auth_name = ').encode('utf-8') + current_account.encode('utf-8') + 'n')
    line[3] = (('account.1.display_name = ').encode('utf-8') + current_account.encode('utf-8') + 'n')
    line[6] = (('account.1.password = ').encode('utf-8') + current_account_password[0][0] + 'n')
    filewrite = open(place, 'w')
    for i in line:
      filewrite.write(i)
    filewrite.close()
    print place
    print config
    client.upload(config,place)


def get_phone_inform(ipaddr):
    fileconf = requests.get('http://admin:admin@'+ipaddr+'/servlet?phonecfg=get[&accounts=1]')
    conf = fileconf.text.split('|')
    current_account = conf[2]
    return current_account


def sniff_frame():
    pcapf = sniff(count=1, timeout=70, filter="dst host 192.168.0.3 and port 5060")
    if len(pcapf) == 0:
        exit()
    frame = pcapf[0]
    macaddr = frame.src
    print macaddr[:8]
    if macaddr[:8] != '80:5e:c0':
        exit()
    ipaddr = frame[0][IP].src
    return macaddr, ipaddr


def conn_mysql(query,fquery,macaddr,qwery2):
    connect = mysql.connector.connect(host='192.168.0.3', database='voip', user='voip_wr', password='***')
    cursor = connect.cursor()
    cursor.execute(fquery)
    state = cursor.fetchall()
    state = bool(state[0][0])
    if state == True:
        cursor.execute(qwery2)
        connect.commit()
        connect.close()
    else:
        cursor.execute(query)
        connect.commit()
        connect.close()


def check_account(current_account):
    connect = mysql.connector.connect(host='192.168.0.3', database='asterisk', user='voip_wr', password='***')
    cursor = connect.cursor()
    qwery = 'select data from sip where id=' + current_account + ' and keyword="secret";'
    cursor.execute(qwery)
    password = cursor.fetchall()
    if password == ' ':
        exit()
    else:
        return password


if __name__ == '__main__':
    macaddr, ipaddr = sniff_frame()
    current_account = get_phone_inform(ipaddr)
    current_account_password = check_account(current_account)
    macaddr = macaddr.replace(':', '')
    ipaddr = ipaddr.decode('utf-8')
    adname = conn_ldap(getpass.getuser())
    query = 'INSERT INTO station (mac, ip, name, number) VALUES (' + '"' + macaddr + '",' + '"' + ipaddr + '",' + '"' + adname + '",' + '"' + get_phone_inform(ipaddr) + '"' + ')'
    qwery2 = 'UPDATE station SET ip=' + '"' + ipaddr + '"' + ', name=' + '"' + adname + '"' + ', number=' + '"' + get_phone_inform(ipaddr) + '"' + ' WHERE mac=' + '"' + macaddr + '"'
    fquery = 'SELECT EXISTS(SELECT mac FROM voip.station WHERE mac=' + '"' + macaddr + '")'
    query = query.encode('utf-8')
    fquery = fquery.encode('utf-8')
    config = macaddr + '.cfg'
    place = os.path.expanduser("~") + "" + "AppDataLocal" + config
    conn_mysql(query,fquery,macaddr,qwery2)
    tftp_file_change(config,place,adname,current_account,current_account_password)
    requests.get('http://admin:admin@'+ipaddr+'/cgi-bin/ConfigManApp.com?key=AutoP')
    requests.get('http://admin:admin@'+ipaddr+'/cgi-bin/ConfigManApp.com?key=Reboot')

Programu inaendesha kwenye kompyuta ya mtumiaji na inafanya kazi mradi kompyuta imeunganishwa kwenye mtandao kupitia simu, kwani Yealink T19 haiwezi kufanya kazi kama lango.

Kwanza, tunahitaji kuelewa ikiwa imeunganishwa? na simu yetu ina mac na ip nini.

def sniff_frame():
    pcapf = sniff(count=1, timeout=70, filter="dst host 192.168.0.3 and port 5060")
    if len(pcapf) == 0:
        exit()
    frame = pcapf[0]
    macaddr = frame.src
    print macaddr[:8]
    if macaddr[:8] != '80:5e:c0':
        exit()
    ipaddr = frame[0][IP].src
    return macaddr, ipaddr

Hapa tunatumia kazi ya kunusa kutoka kwa mfumo wa scapy, kwa msaada wake tunapokea pakiti ya udp iliyopangwa tayari, kusubiri sekunde 70 na ikiwa hatupati chochote, tunatoka.

count=1, timeout=70, filter="dst host 192.168.0.3 and port 5060"

Ifuatayo, tunahakikisha kuwa kifaa ni Yealink na tunarudisha maadili muhimu (ip na mac).

Kutumia ombi maalum, tunapata akaunti ya sasa kwenye simu. Ili kufanya hivyo, usanidi wa sasa unapakuliwa kutoka kwa simu na kuchanganuliwa.

def get_phone_inform(ipaddr):
    fileconf = requests.get('http://admin:admin@'+ipaddr+'/servlet?phonecfg=get[&accounts=1]')
    conf = fileconf.text.split('|')
    current_account = conf[2]
    return current_account

Tafuta nenosiri la akaunti hii. Ili kufanya hivyo, tunageuka kwenye meza ya asterisk.sip na shamba la data ndani yake.

def check_account(current_account):
    connect = mysql.connector.connect(host='192.168.0.3', database='asterisk', user='voip_wr', password='***')
    cursor = connect.cursor()
    qwery = 'select data from sip where id=' + current_account + ' and keyword="secret";'
    cursor.execute(qwery)
    password = cursor.fetchall()
    if password == ' ':
        exit()
    else:
        return password

Kweli, kwa hatua ya mwisho tunaunganisha kwa ldap AD na kutumia sAMAccountName iliyopatikana kupitia chaguo la kukokotoa getpass.getuser() chukua cn ya mtumiaji wa sasa (ambayo kwa kawaida huwa na jina kamili la mtumiaji).

def conn_ldap(login):
    ad = ldap.initialize('ldap://***.local')
    ad.simple_bind_s('voip@***.local', 'password')
    basedn = 'OU=***,DC=***,DC=LOCAL'
    basedn_user = 'OU=***,OU=***,DC=***,DC=LOCAL'
    scope = ldap.SCOPE_SUBTREE
    filterexp = "(&(sAMAccountName=" + login + ")(ObjectClass=person))"
    filterexp2 = "(&(ObjectClass=organizationUnit))"
    attrlist = ['cn']
    attrlist2 = ['OU']
    search = ad.search_s(basedn, scope, filterexp, attrlist)
    adname = search[0][1]['cn'][0].decode('utf-8')
    if adname == ' ':
        search = ad.search_s(basedn_user, scope, filterexp2, attrlist2)
        for i in range(1, len(search)+1):
            group = search[i][1]['ou'][0]
            basedn_user2 = 'OU='+group+','+basedn_user
            search = ad.search_s(basedn_user2, scope, filterexp, attrlist)
            adname = search[0][1]['cn'][0].decode('utf-8')
            if adname != ' ':
                return adname
        adname = search[0][1]['cn'][0].decode('utf-8')
    ad.unbind_s()
    return adname

Tunaunganisha kwenye jedwali lililoundwa hapo awali kwenye hifadhidata (niliiunda hapo) na ingiza kila kitu tulichojifunza, yaani: ip, mac, jina la mtumiaji.

def conn_mysql(query,fquery,macaddr,qwery2):
    connect = mysql.connector.connect(host='192.168.0.3', database='voip', user='voip_wr', password='***')
    cursor = connect.cursor()
    cursor.execute(fquery)
    state = cursor.fetchall()
    state = bool(state[0][0])
    if state == True:
        cursor.execute(qwery2)
        connect.commit()
        connect.close()
    else:
        cursor.execute(query)
        connect.commit()
        connect.close()

Tunaweza kuacha hapa, kwa sababu tayari tumeunda kitabu cha anwani kinachobadilika, unaweza kuuliza, lakini nilienda mbali zaidi na kuongeza utoaji wa vifaa kiotomatiki hapa.

Ili kufanya hivyo, usanidi wa kiolezo hupakuliwa kutoka kwa seva ya tftp iliyosanidiwa awali, ambayo tunafanya mabadiliko yetu na kuihifadhi kama mac.cfg. Hiyo ni, kwa Yealink kuna aina mbili za usanidi, moja ni ya kimataifa, na ya pili inatumika kwa simu maalum na inapaswa kuwa ya fomu mac_phone.cfg.

Baada ya mabadiliko yote kwenye faili na kuihifadhi kwenye seva ya tftp, tunatoa amri kwa simu kutoa na kuanzisha upya kifaa.

def tftp_file_change(config,place,adname,current_account,current_account_password):

    client = tftpy.TftpClient("192.168.0.3", 69)
    client.download('template.cfg', place)
    fileread = open(place, 'r')
    line = fileread.readlines()
    fileread.close()
    line[5] = (('account.1.label = ').encode('utf-8') + adname.encode('utf-8') + 'n')
    line[2] = (('account.1.auth_name = ').encode('utf-8') + current_account.encode('utf-8') + 'n')
    line[3] = (('account.1.display_name = ').encode('utf-8') + current_account.encode('utf-8') + 'n')
    line[6] = (('account.1.password = ').encode('utf-8') + current_account_password[0][0] + 'n')
    filewrite = open(place, 'w')
    for i in line:
      filewrite.write(i)
    filewrite.close()
    print place
    print config
    client.upload(config,place)

requests.get('http://admin:admin@'+ipaddr+'/cgi-bin/ConfigManApp.com?key=AutoP')
requests.get('http://admin:admin@'+ipaddr+'/cgi-bin/ConfigManApp.com?key=Reboot')

Baada ya kuwasha upya kifaa, tunapata jina letu kamili kwenye skrini ya simu + kitabu cha anwani kilichojazwa kwa usahihi kila wakati katika mfumo wa hifadhidata, basi kinachobakia ni kuongeza XML na PHP kidogo ili kuonyesha maudhui kwa nguvu. Kuna mifano mingi kama hii, hata YEALINK yenyewe inayo.

PS: Kwa uboreshaji mkubwa, unaweza kuhamisha mipangilio kuu (vigezo) kwenye faili tofauti.

Chanzo: mapenzi.com

Kuongeza maoni