XMPP4R icq transport troubles - ruby

jid = Jabber::JID.new('....#jabber.ru')
j = Jabber::Client.new(jid)
j.connect
j.auth('12345')
if i trying to send message through transport it responds to me
SENDING:
<message to='2....3#icq.proc.ru' xmlns='jabber:client'><body>hi!</body></message>
=> nil
ruby-1.9.2-p290 :106 > RECEIVED:
<message from='2...3#icq.proc.ru' to='....#jabber.ru/38185266013242853702144' type='error'><error code='401' type='auth'><not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/><text xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'>Error. You must log into the transport before sending messages.</text></error><body>hi!</body></message>
PROCESSING:
<message from='2....3#icq.proc.ru' to='do-not-replay.perekup.net#jabber.ru/38185266013242853702144' type='error' xmlns='jabber:client'><error code='401' type='auth'><not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/><text xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'>Error. You must log into the transport before sending messages.</text></error><body>hi!</body></message> (Jabber::Message)
but:
iq = Jabber::Iq.new(:set)
query = Jabber::IqQuery.new
query.add_namespace('jabber:iq:auth')
query.add(REXML::Element.new('username').add_text("6...6"))
query.add(REXML::Element.new('password').add_text('F...1'))
iq.add(query)
iq.to = 'icq.proc.ru'
iq
j.send iq
SENDING:
<iq to='icq.proc.ru' type='set' xmlns='jabber:client'><query xmlns='jabber:iq:authenticate'><username>6....6</username><password>F....1</password></query></iq>
=> nil
ruby-1.9.2-p290 :105 > RECEIVED:
<iq from='icq.proc.ru' to='...#jabber.ru/38185266013242853702144' type='error'><error code='501' type='cancel'><feature-not-implemented/></error></iq>
PROCESSING:
<iq from='icq.proc.ru' to='...#jabber.ru/38185266013242853702144' type='error' xmlns='jabber:client'><error code='501' type='cancel'><feature-not-implemented/></error></iq> (Jabber::Iq)
i cant use Iq.new_authset_digest(jid, session_id, password) because i cant get session_id parameter
what am I doing wrong?

jid = Jabber::JID.new('user')
client = Jabber::Client.new(jid)
client.connect('54.187.67.96',5222)
client.auth('password')
client.send(Jabber::Presence.new.set_show(:chat).set_status('Rails!'))
puts "Hurray...!! Connected..!!"
# Send an Instant Message.
body = 'Hello from Rails'
to_jid = Jabber::JID.new('user')
message = Jabber::Message::new(to_jid, body).set_type(:normal).set_id('1')
client.send(message)

Related

Bad record MAC on TLS v1.3 when using early_data

I have a project to complete in Ruby involving TLS v.1.3. I want to optimize requests and thus use "early data". I'm using a package called tttls1.3 and the client works until I send early data to the server. What's even more wired is that a request with early data goes through and I get a response from the server but immediately after the reply (response message) an alert 20 (Bad Record MAC) is received. I went so far that I even go and recalculate the "client-finished" message which seemed suspicious but it looks correct.
What could be the problem? Is there a TCP or other issue I could check?
Here's an example:
require 'socket'
require 'tttls1.3'
settings2 = {
alpn: ['http/1.1'],
supported_groups: [TTTLS13::NamedGroup::SECP256R1],
cipher_suites: [TTTLS13::CipherSuite::TLS_AES_256_GCM_SHA384],
check_certificate_status: false,
}
settings1 = {
alpn: ['http/1.1'],
supported_groups: [TTTLS13::NamedGroup::SECP256R1],
cipher_suites: [TTTLS13::CipherSuite::TLS_AES_256_GCM_SHA384],
check_certificate_status: false,
process_new_session_ticket: lambda do |nst, rms, cs|
return if Time.now.to_i - nst.timestamp > nst.ticket_lifetime
settings2[:ticket] = nst.ticket
settings2[:resumption_master_secret] = rms
settings2[:psk_cipher_suite] = cs
settings2[:ticket_nonce] = nst.ticket_nonce
settings2[:ticket_age_add] = nst.ticket_age_add
settings2[:ticket_timestamp] = nst.timestamp
end
}
# REQUEST
socket = TCPSocket.new("ssltest.louis.info", 443)
client = TTTLS13::Client.new(socket, "ssltest.louis.info", settings1)
client.connect
client.write("GET / HTTP/1.1\r\n")
client.write("Host: ssltest.louis.info\r\n")
client.write("\r\n\r\n")
client.read
client.close
socket.close
sleep(1)
# RESUMPTION
socket = TCPSocket.new("ssltest.louis.info", 443)
client = TTTLS13::Client.new(socket, "ssltest.louis.info", settings2)
client.early_data("HEAD / HTTP/1.1\r\nHost: ssltest.louis.info\r\n\r\n\r\n")
client.connect
p client.read
p client.read
p client.read
p client.read
Original issue: https://github.com/thekuwayama/tttls1.3/issues/48
It turned out that the Connection: close header must be present in the request. It must be the remote server implementation specific.

Creating a Message with Attachement GmailV1 API ruby

I am trying to send a en email with an attachment via the GmailV1 API. However it just isn't working due to Missing Draft Message errors.
According to RubyDoc I tried to create a draft message as follows:
The GmailV1:GmailService.create_user_draft() methods takes in an identifier and a draft_object (accepting 'me' for the authorized user). A draft object (Google::Apis::GmailV1::Draft) takes a message in the form of Google::Apis::GmailV1::Message which in turn takes a payload in the form of Google::Apis::GmailV1::MessagePart which has the desired filename method.
So I ran this code:
##assume client is an authorized instance of Google::Apis::GmailV1:GmailService
msg_part = Google::Apis::GmailV1::MessagePart.new(filename: 'path/to/file')
msg = Google::Apis::GmailV1::Message.new(payload: msg_part)
draft = Google::Apis::GmailV1::Draft.new(message: msg)
client.create_user_draft('me', draft)
>> Google::Apis::ClientError: invalidArgument: Missing draft message
How Come?
Versions:
google-api-client 0.9.9
googleauth 0.5.1
ruby 2.3.1p112
Using the GmailService class as described here I was able to save a draft using the code below. I think the key is that the raw keyword is required in the message.
result = service.create_user_draft(
user_id,
Google::Apis::GmailV1::Draft.new(
:message => Google::Apis::GmailV1::Message.new(
:raw => "To: test#test.com\r\nSubject: Test Message\r\n\r\nTest Body"
)
)
)
I solved this problem creating first a Mail object with the 'mail' gem in this way:
require 'mail'
mail = Mail.new
mail['from'] = 'pippo#pluto.it'
mail[:to] = 'me#mymail.it'
mail.subject = 'This is a test email'
mail.body 'this is the body'
mail.add_file("./path/to/file")
#... and other ...
then i converted this in a raw object:
raw_message = mail.to_s
then i create gmail message with this raw:
message = Google::Apis::GmailV1::Message.new(
:raw => raw_message
)
and finnaly:
draft = Google::Apis::GmailV1::Draft.new(message: message)
gmail.create_user_draft('me', draft)

Ruby TCP server - ERROR:PG::ConnectionBad: FATAL: remaining connection slots are reserved for non-replication superuser connections

I have written a tcp server that receives packets from a terminal device. The TCP server interprets the data and saves it in the database using postgres.
The tcp server is multi-threaded. A sample of the code of the moment i open the db connection and save data looks like this;
conn = Sequel.connect('postgres://xxxxx:xxxxxxxxxx#127.0.0.1:xxxxx/xxxxxxxxx',:max_connections => 100) # requires pg
transactions = conn.from(:transactions)
if transactions.insert(serial_number: card_serial, balance_before: balance_before, amount: transaction_amount, balance_after: balance_after, transaction_time: time, terminal_number: terminal_number, terminal_type: terminal_type, created_at: Time.now, updated_at: Time.now)
response = {message: "TT01000080", status: "SUCCESS" }
return response
else
response = {message: "", status: "FAILED" }
return response
end
After a few packets, the db creates an error like this;
ERROR:PG::ConnectionBad: FATAL: remaining connection slots are reserved for non-replication superuser connections
Even adding the line conn.disconnect does not help the issue.
The idea to connect to DB every time you want to create a record is not the best approach. Think about changing it to some Connection Pool.
But if you still want to connect every time, try to use the block form of connect, which will assure connection is closed after block finishes.
Also there was no close/disconnect in your code, maybe you put it after return call (which means it was not executed)
Try something like this:
response = nil
Sequel.connect('postgres://xxxxx:xxxxxxxxxx#127.0.0.1:xxxxx/xxxxxxxxx',:max_connections => 100) do |conn| # requires pg
transactions = conn.from(:transactions)
if transactions.insert(serial_number: card_serial, balance_before: balance_before, amount: transaction_amount, balance_after: balance_after, transaction_time: time, terminal_number: terminal_number, terminal_type: terminal_type, created_at: Time.now, updated_at: Time.now)
response = {message: "TT01000080", status: "SUCCESS" }
else
response = {message: "", status: "FAILED" }
end
end
return response

Cannot access SOAP xml nested id= attribute using Savon 2

In the soap response below (from SoapUI), under the parent SearchForReservationResponse tag, I am trying to pull out the values of Reservation id, Restaurant id and Location id with Savon 2.
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<SearchForReservationResponse xmlns="http://schemas.livebookings.net/OneFormat/Aggregator/Internal/1/0/">
<Reservation id="34639536" status="Confirmed">
<DiningDateAndTime>2015-07-01T17:00:00</DiningDateAndTime>
<Restaurant id="25200">
<Name>Eat Food - UK Demo Website - Bookatable.com</Name>
<Location id="35839">
<Name>Bar</Name>
</Location>
</Restaurant>
<Size>2</Size>
<Created>2015-07-01T13:22:17.41</Created>
<SessionId>DINNER</SessionId>
<FirstName>John</FirstName>
<LastName>Smith</LastName>
<ConfirmationNumber>JWRW5HR5</ConfirmationNumber>
<AllowedToCancelOnline>true</AllowedToCancelOnline>
<RestaurantPhoneNumber type="Main">+44 7951300529</RestaurantPhoneNumber>
</Reservation>
</SearchForReservationResponse>
</soap:Body>
</soap:Envelope>
Below is my attempt for trying to access Reservation id. After a lot of googling I found that the new Savon 2 syntax uses #attrib, but I keep getting errors as I think I am not using this Ruby nested hash syntax correctly - I find it very confusing and am fairly new to Ruby. If you could help me out here it would be much appreciated!
require 'savon'
class SearchReservation
attr_reader :reservation_id
def client
client = Savon.client(wsdl: "http://example-wsdl-url", follow_redirects: :follow_redirects)
end
def main_method(confirm_number, email)
message = {'ConfirmationNumber' => "JWRW5HR5", 'EMail' => "jon#" }
response = client.call(:search_for_reservation, message: message)
data = response.body(:search_for_reservation_response => { #attrib => {:reservation => :id} })
if data
#reservation_id = data[:id]
end
end
end
search = SearchReservation.new
puts search.main_method("JWRW5HR5", "jon#")
N.B. the email value jon# doesn't have to be a valid email address (used just for testing purposes) - it returns a valid response in SoapUI.
My last syntax error trace in the terminal/console:
/~/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/savon-2.11.1/lib/savon/response.rb:36:in `body': wrong number of arguments (1 for 0) (ArgumentError)
from search.rb:13:in `main_method'
from search.rb:22:in `<main>'
My final solution pulling out all the values I need. Of note: even though dining_date_and_time was presented as xml when putting response.body, when it is extracted using #dining_date_and_time = data[:dining_date_and_time] the date and time values get printed cleanly. This is key once porting to a fully-fledged Rails app.
Despite all the discussion online about attributes, ids within an xml tag can be pulled by just ensuring you are far enough down the "tree" (ie. location id falls under location tag) and then specifying the key: in this case the api displays it as :#id for each nested case.
N.B, this only returns the last value called each time in console. But all values should be pulled in views once integrated into Rails. (Hopefully!)
require 'savon'
class SearchClass
def client
client = Savon.client(wsdl: "http://wsdl-example-url", follow_redirects: :follow_redirects)
end
def return_data(confirm_number, email)
message = {'ConfirmationNumber' => confirm_number, 'EMail' => email }
response = client.call(:search_for_reservation, message: message)
data = response.to_hash[:search_for_reservation_response][:reservation]
#reservation_id = data[:#id]
#dining_date_and_time = data[:dining_date_and_time]
#size = data[:size]
#session_id = data[:session_id]
#first_name = data[:first_name]
#last_name = data[:last_name]
#confirm_number = data[:confirmation_number]
#allowed_to_cancel_online = data[:allowed_to_cancel_online]
#restaurant_phone_number = data[:restaurant_phone_number]
data2 = response.to_hash[:search_for_reservation_response][:reservation][:restaurant]
#restaurant_id = data2[:#id]
#restaurant_name = data2[:name]
data3 = response.to_hash[:search_for_reservation_response][:reservation][:restaurant][:location]
#location_id = data3[:#id]
#location_name = data3[:name]
end
end
search = SearchClass.new
puts search.return_data("JWRW5HR5", "jon#")

XMPP transport to ICQ

I try to send messages to icq via jabber-transport. I tried to use code from this answer
XMPP transport to another protocol, but I got this message:
DEBUG -- : SENDING:
<message to='12345#icq.jabber.blahblah.ru' xmlns='jabber:client'><body>test
message from robot</body></message>
=> nil
DEBUG -- : RECEIVED:
<message from='12345#icq.jabber.blahblah.ru' to='myjit#blahblah.ru/83076
14161416233482839674' type='error'><error code='401' type='auth'><not-authorized
xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/><text xmlns='urn:ietf:params:xml:n
s:xmpp-stanzas'>Error. You must log into the transport before sending messages.<
/text></error><body>test message from robot</body></message>
Please explain me: What am I doing wrong? Thanks in advance.
Here's my code
require 'rubygems'
require 'xmpp4r/client'
include Jabber
Jabber.debug = true
jid = JID::new('myjit#blahblah.ru')
pass = 'pwd'
server = 'jabber.blahblah.ru'
port = '5223'
subj = 'Nagios notification'
user = '12345#icq.jabber.blahblah.ru'
text = 'AAAA AAAA AAAA'
cl = Jabber::Client::new(jid)
cl.use_ssl = true
cl.connect(server,port)
cl.auth(pass)
#connect to transport
reg=Jabber::Iq.new_register "54321", "pwd2"
reg.to="icq.jabber.blahblah.ru"
cl.send reg
mes = Message::new(user,text)
cl.send(mes)
cl.close()
Updated code:
cl.connect(server,port)
cl.auth(pass)
# sending initial presence
p = Jabber::Presence.new
cl.send p
mes = Message::new(user,text)
mes.type = :chat
cl.send(mes)
cl.close()
returns:
D, [2014-11-18T19:01:35.986182 #8084] DEBUG -- : SENDING:
<presence xmlns='jabber:client'/>
=> nil
irb(main):027:0> D, [2014-11-18T19:01:36.048980 #8084] DEBUG -- : RECEIVED:
<presence from='icq.jabber.blahblah.ru' to='myjit#blahblah.ru' type='subscri
be'><status/></presence>
and still doesnt work
You only need to register transport only first time, then you need to send initial presence after session creation.

Resources