;************************ ;* Library : ltls.pbi ;* ;* Server side TLS Implementation to communicate encrypted. ;* ;* Created and develobed by Linder Hard- und Software ;* ;* Current only usable for Linux. ;* ;* CompilerIf #PB_Compiler_OS <> #PB_OS_Linux CompilerError "Only for Linux" CompilerEndIf XIncludeFile "lsocket.pbi" DeclareModule ltls Structure s_tls_server CA.s Cert.s Key.s Password.s EndStructure Declare InitSimpleTLS(CA.s, Cert.s, Key.s, Password.s, TLSID.i = 0) Declare InitTLS(*Settings.s_tls_server, TLSID.i = 0) Declare WaitTLSSocket(ServerSocket.i, TLSID.i = 0) Declare ReadTLSSocket(Connection.i, *Buffer, Length.i) Declare WriteTLSSocket(Connection.i, *Buffer, Length.i) Declare CloseTLSSocket(Connection.i) Declare CloseTLS(TLSID.i = 0) Declare.s ErrorTLSSrv(TLSID.i = 0) Declare.s ErrorTLSCli(Connection) Declare GetSocket(Connection.i) EndDeclareModule Module ltls Structure tls_socket server_id.i client_id.i tls_id.i EndStructure Global NewMap socket_sort.tls_socket() PrototypeC.i Pr_tls_init() PrototypeC.i Pr_tls_config_new() PrototypeC.i Pr_tls_load_file_pw(FileName.p-utf8, Length, Password.p-utf8) PrototypeC.i Pr_tls_load_file(FileName.p-utf8, Length, Passord.s = #Null$) PrototypeC.i Pr_tls_config_set_ca_mem(*tls_config , Memory.i, Length.i) PrototypeC.i Pr_tls_config_set_cert_mem(*tls_config , Memory.i, Length.i) PrototypeC.i Pr_tls_config_set_key_mem(*tls_config , Memory.i, Length.i) PrototypeC.i Pr_tls_server() PrototypeC.i Pr_tls_configure(*ctx, *cfg) PrototypeC.i Pr_tls_error(*ctx) PrototypeC.i Pr_tls_accept_socket(*ctx, *cctx, Socket.l) PrototypeC.i Pr_tls_accept_cbs(*ctx, *cctx, read_cb.i, write_cb.i, arg_ch.i = #Null) PrototypeC.i Pr_tls_read(*cctx, *buffer, Size.i) PrototypeC.i Pr_tls_write(*cctx, *buffer, Size.i) PrototypeC.i Pr_tls_handshake(*cctx) PrototypeC.i Pr_tls_close(*cctx) PrototypeC.i Pr_tls_free(*ctx) PrototypeC.i Pr_tls_config_free(*cfg) #TLS_WANT_POLLIN = -2 #TLS_WANT_POLLOUT = -3 CompilerIf #PB_Compiler_Processor = #PB_Processor_x64 Define libressl_tls = OpenLibrary(#PB_Any, "/usr/lib64/libtls.so.22") If Not IsLibrary(libressl_tls) Define libressl_tls = OpenLibrary(#PB_Any, "/usr/lib64/libtls.so.20") If Not IsLibrary(libressl_tls) Define libressl_tls = OpenLibrary(#PB_Any, "/usr/lib64/libtls.so.17") If Not IsLibrary(libressl_tls) lhs_log::Out("Library not found: /usr/lib64/libtls.so.22 or .20 or .17") End EndIf EndIf EndIf CompilerElse Define libressl_tls = OpenLibrary(#PB_Any, "/usr/lib/libtls.so.20") If Not IsLibrary(libressl_tls) Define libressl_tls = OpenLibrary(#PB_Any, "/usr/lib/libtls.so.17") If Not IsLibrary(libressl_tls) lhs_log::Out("Library not found: /usr/lib/libtls.so.20 or .17") End EndIf EndIf CompilerEndIf If IsLibrary(libressl_tls) Define Call_tls_init = GetFunction(libressl_tls, "tls_init") Define Call_tls_config_new = GetFunction(libressl_tls, "tls_config_new") Define Call_tls_load_file = GetFunction(libressl_tls, "tls_load_file") Define Call_tls_config_set_ca_mem = GetFunction(libressl_tls, "tls_config_set_ca_mem") Define Call_tls_config_set_cert_mem = GetFunction(libressl_tls, "tls_config_set_cert_mem") Define Call_tls_config_set_key_mem = GetFunction(libressl_tls, "tls_config_set_key_mem") Define Call_tls_server = GetFunction(libressl_tls, "tls_server") Define Call_tls_configure = GetFunction(libressl_tls, "tls_configure") Define Call_tls_error = GetFunction(libressl_tls, "tls_error") Define Call_tls_accept_socket = GetFunction(libressl_tls, "tls_accept_socket") Define Call_tls_accept_cbs = GetFunction(libressl_tls, "tls_accept_cbs") Define Call_tls_read = GetFunction(libressl_tls, "tls_read") Define Call_tls_write = GetFunction(libressl_tls, "tls_write") Define Call_tls_handshake = GetFunction(libressl_tls, "tls_handshake") Define Call_tls_close = GetFunction(libressl_tls, "tls_close") Define Call_tls_free = GetFunction(libressl_tls, "tls_free") Define Call_tls_config_free = GetFunction(libressl_tls, "tls_config_free") Else lhs_log::Out("libtls.so Library Not found") End EndIf Global.Pr_tls_init tls_init = Call_tls_init Global.Pr_tls_config_new tls_config_new = Call_tls_config_new Global.Pr_tls_load_file tls_load_file = Call_tls_load_file Global.Pr_tls_load_file_pw tls_load_file_pw = Call_tls_load_file Global.Pr_tls_config_set_ca_mem tls_config_set_ca_mem = Call_tls_config_set_ca_mem Global.Pr_tls_config_set_cert_mem tls_config_set_cert_mem = Call_tls_config_set_cert_mem Global.Pr_tls_config_set_key_mem tls_config_set_key_mem = Call_tls_config_set_key_mem Global.Pr_tls_server tls_server = Call_tls_server Global.Pr_tls_configure tls_configure = Call_tls_configure Global.Pr_tls_error tls_error = Call_tls_error Global.Pr_tls_accept_socket tls_accept_socket = Call_tls_accept_socket Global.Pr_tls_accept_cbs tls_accept_cbs = Call_tls_accept_cbs Global.Pr_tls_read tls_read = Call_tls_read Global.Pr_tls_write tls_write = Call_tls_write Global.Pr_tls_handshake tls_handshake = Call_tls_handshake Global.Pr_tls_close tls_close = Call_tls_close Global.Pr_tls_free tls_free = Call_tls_free Global.Pr_tls_config_free tls_config_free = Call_tls_config_free Global *ctx, *cfg Global tls_cfg = #Null Global tls_ctx = #Null Procedure InitSimpleTLS(CA.s, Cert.s, Key.s, Password.s, TLSID.i = 0) Define Settings.s_tls_server Define TLSInitReturn.i Settings\CA = CA Settings\Cert = Cert Settings\Key = Key Settings\Password = Password TLSInitReturn = InitTLS(@Settings, TLSID) ProcedureReturn TLSInitReturn EndProcedure Procedure InitTLS(*Settings.s_tls_server, TLSID.i = 0) Protected mem_ptr.i, length.i, returns.i If tls_init() <> 0 : ProcedureReturn -1 : EndIf tls_cfg = tls_config_new() lhs_log::Out("TLS cfg obj:"+Str(tls_cfg)) lhs_log::Out("CA:"+*Settings\CA) mem_ptr = tls_load_file(*Settings\CA, @length) If Not mem_ptr : tls_config_free(tls_cfg) : ProcedureReturn -2 : EndIf tls_config_set_ca_mem(tls_cfg, mem_ptr, length) lhs_log::Out("Cert:"+*Settings\Cert) mem_ptr = tls_load_file(*Settings\Cert, @length) If Not mem_ptr : tls_config_free(tls_cfg) : ProcedureReturn -3 : EndIf tls_config_set_cert_mem(tls_cfg, mem_ptr, length) If Len(*Settings\Password) > 0 lhs_log::Out("Key:"+*Settings\Key + " Password:"+*Settings\Password) mem_ptr = tls_load_file_pw(*Settings\Key, @length, *Settings\Password) If Not mem_ptr : tls_config_free(tls_cfg) : ProcedureReturn -4 : EndIf tls_config_set_key_mem(tls_cfg, mem_ptr, length) Else lhs_log::Out("Key:"+*Settings\Key) mem_ptr = tls_load_file(*Settings\Key, @length) If Not mem_ptr : tls_config_free(tls_cfg) : ProcedureReturn -5 : EndIf tls_config_set_key_mem(tls_cfg, mem_ptr, length) EndIf tls_ctx = tls_server() lhs_log::Out("TLS Server obj:"+Str(tls_ctx)) If Not tls_ctx : tls_config_free(tls_cfg) : ProcedureReturn -6 : EndIf returns = tls_configure(tls_ctx, tls_cfg) lhs_log::Out("Configure Returns:"+Str(returns)) If returns <> 0 :lhs_log::Out(ErrorTLSSrv()): tls_free(tls_ctx) : tls_config_free(tls_cfg) : ProcedureReturn -7 : EndIf ProcedureReturn 1 EndProcedure Procedure WaitTLSSocket(ServerSocket.i, TLSID.i = 0) Protected sockID.i , tlssID.i, cctx sockID = lsocket::WaitSocket(ServerSocket) If sockID < 0 : ProcedureReturn -1 : EndIf tlssID = tls_accept_socket(tls_ctx, @cctx, sockID) If tlssID = -1 : ProcedureReturn -2 : EndIf socket_sort(Str(cctx))\client_id = sockID socket_sort(Str(cctx))\tls_id = cctx socket_sort(Str(cctx))\server_id = ServerSocket ProcedureReturn cctx EndProcedure Procedure ReadTLSSocket(Connection.i, Buffer, Length.i) Protected Received.i Received = tls_read(Connection, Buffer, Length) ProcedureReturn Received EndProcedure Procedure WriteTLSSocket(Connection.i, Buffer, Length.i) Protected Received.i Received = tls_write(Connection, Buffer, Length) ProcedureReturn Received EndProcedure Procedure CloseTLSSocket(Connection.i) tls_close(Connection) DeleteMapElement(socket_sort(), Str(Connection)) EndProcedure Procedure GetSocket(Connection.i) ProcedureReturn socket_sort(Str(Connection))\client_id EndProcedure Procedure.s ErrorTLSSrv(TLSID.i = 0) Protected Error.s Error = PeekS(tls_error(tls_ctx),-1,#PB_Ascii) ProcedureReturn Error EndProcedure Procedure.s ErrorTLSCli(Connection.i) Protected Error.s Error = PeekS(tls_error(Connection),-1,#PB_Ascii) ProcedureReturn Error EndProcedure Procedure CloseTLS(TLSID.i = 0) tls_free(tls_ctx) tls_config_free(tls_cfg) EndProcedure EndModule