Pwovizyon oto Yealink T19 + liv adrès dinamik

Lè m 'vin travay pou konpayi sa a, mwen te deja gen kèk baz done nan aparèy IP, plizyè serveurs ak asterisk ak yon plak nan fòm lan nan FreeBPX. Anplis de sa, yon analog PBX Samsung IDCS500 te travay nan paralèl epi, an jeneral, se te sistèm kominikasyon prensipal la nan konpayi an; Telefoni IP te travay sèlman pou depatman lavant yo. Ak tout bagay ta kontinye kwit konsa, men yon bon jou yo te bay yon dekrè pou transfere tout moun nan telefòn IP, dat limit yo te dakò sou, ekipman yo te achte, ak plan an transfere antrepriz la nan 21yèm syèk la te kòmanse aplike.
Premye bagay ki kòmanse enkyete nan yon sitiyasyon konsa se nimewo a rapidman ap grandi nan aparèy telefòn ki bezwen jere yon jan kanmenm, dezyèm bagay la ki te trè mangonmen te anyè telefòn lan. Si Manadjè Endpoint te kapab ede nou ak premye youn nan (ki, nan chemen an, te koupe soti nan dènye vèsyon yo nan FreePBX), Lè sa a, kèk kesyon leve ak liv la:

  • Pwemyeman, ki jan asire presizyon li lè kote / likidite itilizatè yo toujou ap chanje?
  • Dezyèmman, ki jan yo konplètman depèsonalize telefòn yo. Epi yo pa ranpli non kontak la chak fwa?

Pwoblèm nan te enteresan, solisyon an pa t pran tan rive. Koulye a, mwen pral bay lis la konplè, epi Lè sa a, nou pral gade li nan lòd.

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')

Pwogram nan kouri sou òdinatè itilizatè a epi li travay depi òdinatè a konekte ak rezo a atravè yon telefòn, paske Yealink T19 pa ka travay kòm yon pòtay.

Premyèman, nou bezwen konprann si wi ou non li konekte? ak ki mac ak ip telefòn nou an genyen.

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

Isit la nou itilize fonksyon sniff ki soti nan chapant scapy la, avèk èd li nou resevwa yon pake udp predetèmine, tann 70 segonn epi si nou pa trape anyen, nou sòti.

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

Apre sa, nou asire w ke aparèy la se vre Yealink epi retounen valè ki nesesè yo (ip ak mac).

Sèvi ak yon demann espesyal, nou jwenn kont aktyèl la sou telefòn la. Pou fè sa, konfigirasyon aktyèl la telechaje soti nan telefòn nan epi analize.

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

Chèche konnen modpas pou kont sa a. Pou fè sa, nou ale nan tab la asterisk.sip ak jaden an done nan li.

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

Oke, pou etap final la nou konekte ak ldap AD epi itilize sAMAccountName jwenn nan fonksyon an getpass.getuser() pran cn itilizatè aktyèl la (ki anjeneral gen non konplè itilizatè a).

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

Nou konekte nan yon tab pre-kreye nan baz done a (mwen te kreye li la) epi antre nan tout sa nou te aprann, sètadi: ip, mac, non itilizatè.

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()

Nou ta ka sispann isit la, paske nou te deja kreye yon liv adrès dinamik, ou ka mande, men mwen te ale pi lwen epi mwen te ajoute oto-pwovizyon nan aparèy isit la.

Pou fè sa, yon konfigirasyon modèl telechaje soti nan yon sèvè tftp pre-konfigirasyon, nan ki nou fè chanjman nou yo epi sove li kòm mac.cfg. Sa vle di, pou Yealink gen de kalite konfigirasyon, youn se mondyal, ak dezyèm lan aplike nan yon telefòn espesifik epi yo ta dwe nan fòm mac_phone.cfg.

Apre tout chanjman ki fèt nan dosye a epi sove li tounen nan sèvè tftp la, nou bay telefòn nan lòd pou pwovizyon epi rdemare aparèy la.

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')

Apre rdemare aparèy la, nou jwenn non konplè nou an sou ekran telefòn lan + yon liv adrès ki toujou ranpli kòrèkteman nan fòm yon baz done, Lè sa a, tout sa ki rete se ajoute XML ak yon ti PHP nan dinamik montre kontni an. Gen anpil egzanp sa yo, menm YEALINK li menm genyen yo.

PS: Pou pi gwo évolutivité, ou ka deplase anviwònman prensipal yo (varyab) nan yon dosye separe.

Sous: www.habr.com

Add nouvo kòmantè