Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

A Python 3 script to create a new client on the server and to download and execute a custom client installer. The current version works with UrBackup 2.x:

Code Block
languagepy
import http.client as http
import json
from urllib.parse import urlparse
from urllib.parse import urlencode
from base64 import b64encode
import hashlib
import socket
import shutil
import os
import binascii
 
#############################
# Settings. Please edit.
#############################
 
#Your server URL. Do not forget the 'x' at the end
server_url = 'http://example.com:55414/x'
 
 
#If you have basic authentication via .htpasswd
server_basic_username = ''
server_basic_password = ''
 
#user 
# Login user needs following rights
#   "settingsstatus": "allsome"
#   "statusadd_client": "someall"
# "add_clientOptionally, to be able to 
# install existing clients:
#   "settings": "all"
server_username='adminadduser'
server_password='foo'
 
 
#############################
# Global script variables.
# Please do not modify.
# Only modify something after this line
# if you know what you are doing
#############################
 
session=""
 
def get_response(action, params, method):
    global server_url;
    global server_basic_username;
    global server_basic_password;
    global session;
     
    headers = {
        'Accept': 'application/json',
        'Content-Type': 'application/json; charset=UTF-8'
    }
     
    if('server_basic_username' in globals() and len(server_basic_username)>0):
        userAndPass = b64encode(str.encode(server_basic_username+":"+server_basic_password)).decode("ascii")
        headers['Authorization'] = 'Basic %s' %  userAndPass
     
    curr_server_url=server_url+"?"+urlencode({"a": action});
     
    if(len(session)>0):
        params["ses"]=session
     
    if method=='GET':
        curr_server_url+="&"+urlencode(params);
     
    target = urlparse(curr_server_url)
    
    if not method:
        method = 'GET'
        
    if method=='POST':
        body = urlencode(params)
    else:
        body = ''
     
    if(target.scheme=='http'):
        h = http.HTTPConnection(target.hostname, target.port)
    elif(target.scheme=='https'):
        h = http.HTTPSConnection(target.hostname, target.port)
    else:
        print('Unkown scheme: '+target.scheme)
        raise Exception("Unkown scheme: "+target.scheme)
     
    h.request(
            method,
            target.path+"?"+target.query,
            body,
            headers)
     
    return h.getresponse();
 
def get_json(action, params = {}):
     
    response = get_response(action, params, "POST")
     
    if(response.status != 200):
        return ""
     
    data = response.readall();
     
    response.close()
         
    return json.loads(data.decode("utf-8"))
 
def download_file(action, outputfn, params):
     
    response = get_response(action, params, "GET");
     
    if(response.status!=200):
        return False
     
    with open(outputfn, 'wb') as outputf:
        shutil.copyfileobj(response, outputf)
    
    if os.path.getsize(outputfn)<10*1024:
        return False
    
    return True       
 
def md5(s):
    return hashlib.md5(s.encode()).hexdigest()
 
 
print("Logging in...")
 
salt = get_json("salt", {"username": server_username})
 
if( not ('ses' in salt) ):
    print('Username does not exist')
    exit(1)
     
session = salt["ses"];
     
if( 'salt' in salt ):
    password_md5_bin = hashlib.md5((salt["rndsalt"]+server_password).encode()).digest()
    password_md5 = binascii.hexlify(password_md5_bin).decode()
    
    if "pbkdf2_rounds" in salt:
        pbkdf2_rounds = int(salt["pbkdf2_rounds"])
        if pbkdf2_rounds>0:
            password_md5 = binascii.hexlify(hashlib.pbkdf2_hmac('sha256', password_md5_bin, 
                                               salt["salt"].encode(), pbkdf2_rounds)).decode()
    
    password_md5 = md5(salt["rnd"]+serverpassword_passwordmd5));
     
    login = get_json("login", { "username": server_username,
                                "password": password_md5 })
     
    if('success' not in login or not login['success']):
        print('Error during login. Password wrong?')
        exit(1)
        
    clientname = socket.gethostname()
         
    print("Creating client "+socket.gethostname()clientname+"...")
         
   status new_client = get_json("statusadd_client", { "clientname": socket.gethostname()})clientname})
    
    if "already_exists" in new_client:
        print("Client already exists")
        
        status = get_json("status")
        
        if "client_downloads" in status:
            for client in status["client_downloads"]:         
                if (client["name"] == socket.gethostname(clientname)):
 
                       print("Downloading Installer...")
                    
                    if not download_file("download_client", "Client Installer.exe",
                                 {"clientid": client["id"] }):
                        print("Downloading client failed")
                        exit(1)
        else:        
            print("Downloading client failed")
     Client already exists and login user has probably no right to access existing clients")
            exit(12) 
    else:
        if not "new_authkey" in new_client:
            print("SucessfullyError creating downloadednew client")
            exit(3)
            
        os.startfile("Client Installer.exe")print("Downloading Installer...")
                 
        if not download_file("download_client", "Client Installer.exe",
                             {"clientid": new_client["new_clientid"],
                              "authkey": new_client["new_authkey"]
                              }):
             
   exit(0)         print("Downloading client failed")
            exit(1)
         
    print("Could not find client for download. No permission?"Sucessfully downloaded client")
    os.startfile("Client Installer.exe")
    exit(10)

 

Use e.g. http://cx-freeze.sourceforge.net/ to create an executable, if you need to.