oversip_p 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. checksums.yaml +7 -0
  2. data/AUTHORS +22 -0
  3. data/LICENSE +25 -0
  4. data/README.md +43 -0
  5. data/Rakefile +54 -0
  6. data/bin/oversip +184 -0
  7. data/etc/oversip.conf +274 -0
  8. data/etc/proxies.conf +145 -0
  9. data/etc/server.rb +315 -0
  10. data/etc/tls/ca/cacert.pem +3894 -0
  11. data/etc/tls/demo-tls.oversip.net.crt +17 -0
  12. data/etc/tls/demo-tls.oversip.net.key +15 -0
  13. data/etc/tls/upgrade-cacert.sh +12 -0
  14. data/etc/tls/utils/create-cert.rb +162 -0
  15. data/etc/tls/utils/get-sip-identities.rb +95 -0
  16. data/ext/common/c_util.h +74 -0
  17. data/ext/common/ruby_c_util.h +88 -0
  18. data/ext/sip_parser/common_headers.h +210 -0
  19. data/ext/sip_parser/ext_help.h +18 -0
  20. data/ext/sip_parser/extconf.rb +3 -0
  21. data/ext/sip_parser/sip_message_parser.c +29741 -0
  22. data/ext/sip_parser/sip_parser.h +250 -0
  23. data/ext/sip_parser/sip_parser_ruby.c +1370 -0
  24. data/ext/sip_parser/sip_uri_parser.c +39699 -0
  25. data/ext/stud/extconf.rb +43 -0
  26. data/ext/stun/ext_help.h +16 -0
  27. data/ext/stun/extconf.rb +3 -0
  28. data/ext/stun/stun_ruby.c +394 -0
  29. data/ext/utils/ext_help.h +14 -0
  30. data/ext/utils/extconf.rb +3 -0
  31. data/ext/utils/haproxy_protocol.c +6163 -0
  32. data/ext/utils/haproxy_protocol.h +27 -0
  33. data/ext/utils/ip_utils.c +5952 -0
  34. data/ext/utils/ip_utils.h +64 -0
  35. data/ext/utils/outbound_utils.c +3227 -0
  36. data/ext/utils/outbound_utils.h +27 -0
  37. data/ext/utils/utils_ruby.c +392 -0
  38. data/ext/utils/utils_ruby.h +76 -0
  39. data/ext/websocket_framing_utils/ext_help.h +18 -0
  40. data/ext/websocket_framing_utils/extconf.rb +3 -0
  41. data/ext/websocket_framing_utils/ws_framing_utils.h +47 -0
  42. data/ext/websocket_framing_utils/ws_framing_utils_ruby.c +135 -0
  43. data/ext/websocket_http_parser/ext_help.h +18 -0
  44. data/ext/websocket_http_parser/extconf.rb +3 -0
  45. data/ext/websocket_http_parser/ws_http_parser.c +1635 -0
  46. data/ext/websocket_http_parser/ws_http_parser.h +87 -0
  47. data/ext/websocket_http_parser/ws_http_parser_ruby.c +630 -0
  48. data/lib/oversip/config.rb +597 -0
  49. data/lib/oversip/config_validators.rb +126 -0
  50. data/lib/oversip/default_server.rb +52 -0
  51. data/lib/oversip/errors.rb +10 -0
  52. data/lib/oversip/fiber_pool.rb +56 -0
  53. data/lib/oversip/launcher.rb +635 -0
  54. data/lib/oversip/logger.rb +84 -0
  55. data/lib/oversip/modules/outbound_mangling.rb +56 -0
  56. data/lib/oversip/modules/user_assertion.rb +73 -0
  57. data/lib/oversip/proxies_config.rb +189 -0
  58. data/lib/oversip/ruby_ext/eventmachine.rb +38 -0
  59. data/lib/oversip/sip/client.rb +428 -0
  60. data/lib/oversip/sip/client_transaction.rb +586 -0
  61. data/lib/oversip/sip/constants.rb +88 -0
  62. data/lib/oversip/sip/core.rb +217 -0
  63. data/lib/oversip/sip/launcher.rb +221 -0
  64. data/lib/oversip/sip/listeners/connection.rb +54 -0
  65. data/lib/oversip/sip/listeners/ipv4_tcp_client.rb +21 -0
  66. data/lib/oversip/sip/listeners/ipv4_tcp_server.rb +22 -0
  67. data/lib/oversip/sip/listeners/ipv4_tls_client.rb +21 -0
  68. data/lib/oversip/sip/listeners/ipv4_tls_server.rb +22 -0
  69. data/lib/oversip/sip/listeners/ipv4_tls_tunnel_server.rb +22 -0
  70. data/lib/oversip/sip/listeners/ipv4_udp_server.rb +21 -0
  71. data/lib/oversip/sip/listeners/ipv6_tcp_client.rb +21 -0
  72. data/lib/oversip/sip/listeners/ipv6_tcp_server.rb +22 -0
  73. data/lib/oversip/sip/listeners/ipv6_tls_client.rb +21 -0
  74. data/lib/oversip/sip/listeners/ipv6_tls_server.rb +22 -0
  75. data/lib/oversip/sip/listeners/ipv6_tls_tunnel_server.rb +22 -0
  76. data/lib/oversip/sip/listeners/ipv6_udp_server.rb +21 -0
  77. data/lib/oversip/sip/listeners/tcp_client.rb +97 -0
  78. data/lib/oversip/sip/listeners/tcp_connection.rb +202 -0
  79. data/lib/oversip/sip/listeners/tcp_server.rb +71 -0
  80. data/lib/oversip/sip/listeners/tls_client.rb +125 -0
  81. data/lib/oversip/sip/listeners/tls_server.rb +88 -0
  82. data/lib/oversip/sip/listeners/tls_tunnel_connection.rb +89 -0
  83. data/lib/oversip/sip/listeners/tls_tunnel_server.rb +61 -0
  84. data/lib/oversip/sip/listeners/udp_connection.rb +214 -0
  85. data/lib/oversip/sip/listeners.rb +24 -0
  86. data/lib/oversip/sip/message.rb +177 -0
  87. data/lib/oversip/sip/message_processor.rb +213 -0
  88. data/lib/oversip/sip/name_addr.rb +51 -0
  89. data/lib/oversip/sip/proxy.rb +324 -0
  90. data/lib/oversip/sip/request.rb +179 -0
  91. data/lib/oversip/sip/response.rb +37 -0
  92. data/lib/oversip/sip/rfc3263.rb +643 -0
  93. data/lib/oversip/sip/server_transaction.rb +295 -0
  94. data/lib/oversip/sip/sip.rb +76 -0
  95. data/lib/oversip/sip/tags.rb +39 -0
  96. data/lib/oversip/sip/timers.rb +55 -0
  97. data/lib/oversip/sip/transport_manager.rb +130 -0
  98. data/lib/oversip/sip/uac.rb +89 -0
  99. data/lib/oversip/sip/uac_request.rb +84 -0
  100. data/lib/oversip/sip/uri.rb +208 -0
  101. data/lib/oversip/syslog.rb +68 -0
  102. data/lib/oversip/system_callbacks.rb +45 -0
  103. data/lib/oversip/tls.rb +172 -0
  104. data/lib/oversip/utils.rb +30 -0
  105. data/lib/oversip/version.rb +21 -0
  106. data/lib/oversip/websocket/constants.rb +55 -0
  107. data/lib/oversip/websocket/http_request.rb +59 -0
  108. data/lib/oversip/websocket/launcher.rb +183 -0
  109. data/lib/oversip/websocket/listeners/connection.rb +51 -0
  110. data/lib/oversip/websocket/listeners/ipv4_ws_server.rb +22 -0
  111. data/lib/oversip/websocket/listeners/ipv4_wss_server.rb +22 -0
  112. data/lib/oversip/websocket/listeners/ipv4_wss_tunnel_server.rb +22 -0
  113. data/lib/oversip/websocket/listeners/ipv6_ws_server.rb +22 -0
  114. data/lib/oversip/websocket/listeners/ipv6_wss_server.rb +22 -0
  115. data/lib/oversip/websocket/listeners/ipv6_wss_tunnel_server.rb +22 -0
  116. data/lib/oversip/websocket/listeners/ws_server.rb +331 -0
  117. data/lib/oversip/websocket/listeners/wss_server.rb +88 -0
  118. data/lib/oversip/websocket/listeners/wss_tunnel_server.rb +133 -0
  119. data/lib/oversip/websocket/listeners.rb +13 -0
  120. data/lib/oversip/websocket/websocket.rb +13 -0
  121. data/lib/oversip/websocket/ws_framing.rb +545 -0
  122. data/lib/oversip/websocket/ws_sip_app.rb +120 -0
  123. data/lib/oversip.rb +127 -0
  124. data/test/oversip_test_helper.rb +19 -0
  125. data/test/test_http_parser.rb +73 -0
  126. data/test/test_name_addr.rb +27 -0
  127. data/test/test_name_addr_parser.rb +24 -0
  128. data/test/test_sip_message_parser.rb +168 -0
  129. data/test/test_sip_uri_parser.rb +56 -0
  130. data/test/test_uri.rb +68 -0
  131. data/thirdparty/stud/stud.tar.gz +0 -0
  132. metadata +334 -0
@@ -0,0 +1,17 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIICrzCCAhigAwIBAgIET/1hdzANBgkqhkiG9w0BAQUFADBxMR0wGwYDVQQDDBRk
3
+ ZW1vLXRscy5vdmVyc2lwLm5ldDELMAkGA1UEBhMCRVMxEjAQBgNVBAoMCVZlcnNh
4
+ dGljYTEQMA4GA1UECwwHT3ZlclNJUDEdMBsGCgmSJomT8ixkAQMMDWliY0BhbGlh
5
+ eC5uZXQwHhcNMTIwNzEwMTEyMDMyWhcNMTcwNzEwMTEyMDMyWjBxMR0wGwYDVQQD
6
+ DBRkZW1vLXRscy5vdmVyc2lwLm5ldDELMAkGA1UEBhMCRVMxEjAQBgNVBAoMCVZl
7
+ cnNhdGljYTEQMA4GA1UECwwHT3ZlclNJUDEdMBsGCgmSJomT8ixkAQMMDWliY0Bh
8
+ bGlheC5uZXQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALXVloxokaERx4xL
9
+ 0pH4rEe5liijlScKLGFJtpESUiG1pMTtWCxNzNTZ4J6mgdE07umS7567tHAEpRbr
10
+ C+yJ+VzoLNEpOf+x9zm83NTs3xg55SbhfVEL1vQqlnsfr5YG0iTy2znUPM3r3LVS
11
+ rTXz9UsIpnJO9ICvi28wz2a+HgStAgMBAAGjVDBSMAwGA1UdEwQFMAMBAf8wHQYD
12
+ VR0OBBYEFLMUKsF6Xm3uI2UnBTXZihnyOv90MCMGA1UdEQQcMBqGGHNpcDpkZW1v
13
+ LXRscy5vdmVyc2lwLm5ldDANBgkqhkiG9w0BAQUFAAOBgQAPj8XD5/snSPgjJocn
14
+ TpWqbOIbsQBMn11+sRpftf2SsC82wQ4iZy3E1nEDVItO+YzGkxtt2VV+uFoWYNKp
15
+ kzlTJDjvuE2lHwpiWgHIK4qcuC3NBYRKqopfmEtNj2vojQ3DPqyOA5v1YZyGw+SI
16
+ AhSZ8W6FTvfiHCO5ut/d7036VA==
17
+ -----END CERTIFICATE-----
@@ -0,0 +1,15 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIICWwIBAAKBgQC11ZaMaJGhEceMS9KR+KxHuZYoo5UnCixhSbaRElIhtaTE7Vgs
3
+ TczU2eCepoHRNO7pku+eu7RwBKUW6wvsiflc6CzRKTn/sfc5vNzU7N8YOeUm4X1R
4
+ C9b0KpZ7H6+WBtIk8ts51DzN69y1Uq018/VLCKZyTvSAr4tvMM9mvh4ErQIDAQAB
5
+ AoGAVFzCOmaRmk8ra9YJ3hunoqdiGXy7yJ8ZtBGFGI2NeYJS7eLIU9XMwLxNUI4k
6
+ ELIkXk4Dynt/3bDp/1YR9C6XeFEZkmLcA3jbaX74/mcx6GgeCdAUg1bvrzpSFqyk
7
+ UYUw2ioFTKyfI1Z3VQmtWDxtz9BkHQ7uakOyu/HA8N8m0EECQQDe1velUoiQUTTn
8
+ DlsdrMvwFhBvJHstXzZMA6Rwp7HKwh6kmaqycr4Lv5UZX/6nzpqiM7EO7eCD6l9n
9
+ x7zIoOD5AkEA0OSHbCzJr0Wlxuq8joQe+ZXRz5BS+A3XWLG2ahnw/FdtLuxzNsWi
10
+ PdDiUOO4xdPoVj/9l2xwkPTfDLsxmDRiVQJAWfZ7QBkT3P+L1gQrsM1EAAdIVzZp
11
+ LCYWK5YE2x44Xt0Dtfv7t9Mu+ls7/GSO0HxOXVF1F8vdKiSCo8k1Y+HfMQJAcrLY
12
+ zQP2ph+2+/cOG67eFys1biQP+pYXBWNnBvFBij0y/U3loVB5Wjnk2od/gFhvvVQb
13
+ mVZ4pI9gHex3OdyhlQJAXNLuufGOEjnUC8lsmupiAQApMXscYPP0ahNES+hfX5uS
14
+ ylXyHsIJp7h6tBbK/bv/BW4HYFsWUpLbjl71EC2ymg==
15
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1,12 @@
1
+ #!/bin/bash
2
+
3
+ # This script downloads the Root CAs list from Mozilla and stores
4
+ # it under ca/ directory for TLS validation.
5
+ # cacert.pem is downloaded from http://curl.haxx.se/docs/caextract.html
6
+ # (the exact link is http://curl.haxx.se/ca/cacert.pem).
7
+ # cacert.pem is just downloaded in case the server version is newer than
8
+ # the local version of the file.
9
+
10
+ cd ca/
11
+ wget -N http://curl.haxx.se/ca/cacert.pem
12
+
@@ -0,0 +1,162 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "openssl"
4
+ require "socket"
5
+ require "readline"
6
+ require "term/ansicolor"
7
+
8
+
9
+ module OverSIP
10
+ module Cert
11
+
12
+ class Error < ::StandardError ; end
13
+
14
+ extend Term::ANSIColor
15
+
16
+ def self.create_cert
17
+
18
+ begin
19
+ puts
20
+ puts bold(green("OverSIP TLS Certificate Generator"))
21
+
22
+ puts
23
+ puts bold("Certificate informational fields.")
24
+
25
+ ca = OpenSSL::X509::Name.new
26
+
27
+ cert_common_name = Readline.readline("- Common Name (eg, your name or your server's hostname): ").downcase.strip
28
+ cert_common_name = nil if cert_common_name.empty?
29
+ ca.add_entry "CN", cert_common_name if cert_common_name
30
+
31
+ cert_country_code = Readline.readline("- Country Name (2 letter code): ").upcase.strip
32
+ ca.add_entry "C", cert_country_code unless cert_country_code.empty?
33
+
34
+ cert_state = Readline.readline("- State or Province Name (full name): ").strip
35
+ ca.add_entry "ST", cert_state unless cert_state.empty?
36
+
37
+ cert_locality = Readline.readline("- Locality Name (eg, city): ").strip
38
+ ca.add_entry "L", cert_locality unless cert_locality.empty?
39
+
40
+ cert_organization = Readline.readline("- Organization Name (eg, company): ").strip
41
+ ca.add_entry "O", cert_organization unless cert_organization.empty?
42
+
43
+ cert_organization_unit = Readline.readline("- Organizational Unit Name (eg, section): ").strip
44
+ ca.add_entry "OU", cert_organization_unit unless cert_organization_unit.empty?
45
+
46
+ cert_mail = Readline.readline("- Email: ").strip
47
+ ca.add_entry "mail", cert_mail unless cert_mail.empty?
48
+
49
+ puts
50
+ puts bold("SubjectAltName SIP URI domains. ") + "For each given _domain_ an entry \"URI:sip:_domain_\" will be added to the SubjectAltName field."
51
+ cert_sipuri_domains = Readline.readline("- SubjectAltName SIP URI domains (multiple values separated by space): ").downcase.strip.split
52
+ cert_sipuri_domains = nil if cert_sipuri_domains.empty?
53
+
54
+ puts
55
+ puts bold("SubjectAltName DNS domains. ") + "For each given _domain_ an entry \"DNS:_domain_\" will be added to the SubjectAltName field."
56
+ cert_dns_domains = Readline.readline("- SubjectAltName DNS domains (multiple values separated by space): ").downcase.strip.split
57
+ cert_dns_domains = nil if cert_dns_domains.empty?
58
+
59
+ puts
60
+ puts bold("Signing data.")
61
+
62
+ rsa_key_bits = Readline.readline("- RSA key bits (1024/2048/4096) [1024]: ").strip.to_i
63
+ unless rsa_key_bits.zero?
64
+ unless [1024, 2048, 4096].include? rsa_key_bits
65
+ raise OverSIP::Cert::Error, "invalid number of bits (#{rsa_key_bits}) for RSA key"
66
+ end
67
+ else
68
+ rsa_key_bits = 1024
69
+ end
70
+
71
+ key = OpenSSL::PKey::RSA.generate(rsa_key_bits)
72
+
73
+ cert = OpenSSL::X509::Certificate.new
74
+ cert.version = 2
75
+ cert.subject = ca
76
+ cert.issuer = ca
77
+ cert.serial = Time.now.to_i
78
+ cert.public_key = key.public_key
79
+
80
+ years_to_expire = Readline.readline("- Expiration (in years from now) [1]: ").strip.to_i
81
+ years_to_expire = 1 if years_to_expire.zero?
82
+ cert.not_after = Time.now + (years_to_expire * 365 * 24 * 60 * 60)
83
+ cert.not_before = Time.now - (24 * 60 * 60)
84
+
85
+ factory = OpenSSL::X509::ExtensionFactory.new
86
+ factory.subject_certificate = cert
87
+ factory.issuer_certificate = cert
88
+
89
+ subject_alt_name_fields = []
90
+
91
+ cert_sipuri_domains.each do |sipuri_domain|
92
+ subject_alt_name_fields.<< "URI:sip:#{sipuri_domain}"
93
+ end if cert_sipuri_domains
94
+
95
+ cert_dns_domains.each do |dns_domain|
96
+ subject_alt_name_fields.<< "DNS:#{dns_domain}"
97
+ end if cert_dns_domains
98
+
99
+ extensions = {
100
+ "basicConstraints" => "CA:TRUE",
101
+ "subjectKeyIdentifier" => "hash"
102
+ }
103
+ if subject_alt_name_fields.any?
104
+ extensions["subjectAltName"] = subject_alt_name_fields.join(",")
105
+ end
106
+
107
+ cert.extensions = extensions.map {|k,v| factory.create_ext(k,v) }
108
+
109
+ cert.sign(key, OpenSSL::Digest::SHA1.new)
110
+
111
+ puts
112
+ puts bold("File name. ") + "For the given _name_ a public certificate _name_.crt and a private key _name_.key will be created. Also a file _name_.key.crt containing both the public certificate and the private key will be created."
113
+ file_name = Readline.readline("- File name [#{cert_common_name}]: ").strip
114
+ file_name = cert_common_name if file_name.empty?
115
+ unless file_name
116
+ raise OverSIP::Cert::Error, "a file name must be set"
117
+ end
118
+
119
+ puts
120
+
121
+ # Make two files:
122
+ # - file_name.crt => public certificate.
123
+ # - file_name.key => private key.
124
+ {"key" => key, "crt" => cert}.each_pair do |ext, o|
125
+ name = "#{file_name}.#{ext}"
126
+ File.open(name, "w") {|f| f.write(o.to_pem) }
127
+ File.chmod(0600, name) if ext == "key"
128
+
129
+ case ext
130
+ when "key"
131
+ puts yellow(">> private key generated in file '#{bold("#{name}")}'")
132
+ when "crt"
133
+ puts yellow(">> public certificate generated in file '#{bold("#{name}")}'")
134
+ end
135
+ end
136
+
137
+ # Make a single file containing both the public certificate and the private key.
138
+ name = "#{file_name}.key.crt"
139
+ File.open(name, "w") do |f|
140
+ f.write(cert.to_pem)
141
+ f.write(key.to_pem)
142
+ end
143
+ File.chmod(0600, name)
144
+ puts yellow(">> public certificate + private key generated in file '#{bold("#{name}")}'")
145
+
146
+ rescue ::Interrupt => e
147
+ puts "\n\n" + red("Interrupted")
148
+ exit
149
+
150
+ rescue ::OverSIP::Cert::Error => e
151
+ puts "\n" + bold(red("ERROR: #{e}"))
152
+ exit 1
153
+ end
154
+
155
+ end # def create_cert
156
+
157
+ end
158
+ end
159
+
160
+
161
+ OverSIP::Cert.create_cert
162
+
@@ -0,0 +1,95 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Runs as follows:
4
+ #
5
+ # ~$ ruby get-sip-identities.rb PEM_FILE
6
+
7
+
8
+ require "openssl"
9
+
10
+
11
+ module TLS
12
+
13
+ # Extracts the SIP identities in a public certificate following
14
+ # the mechanism in http://tools.ietf.org/html/rfc5922#section-7.1
15
+ # and returns an array containing them.
16
+ #
17
+ # Arguments:
18
+ # - _cert_: must be a public X.509 certificate in PEM format.
19
+ #
20
+ def self.get_sip_identities cert
21
+ puts "DEBUG: following rules in RFC 5922 \"Domain Certificates in SIP\" section 7.1 \"Finding SIP Identities in a Certificate\""
22
+ verify_subjectAltName_DNS = true
23
+ verify_CN = true
24
+ subjectAltName_URI_sip_entries = []
25
+ subjectAltName_DNS_entries = []
26
+ sip_identities = {}
27
+
28
+ cert.extensions.each do |ext|
29
+ next if ext.oid != "subjectAltName"
30
+ verify_CN = false
31
+
32
+ ext.value.split(/,\s+/).each do |name|
33
+ if /^URI:sip:([^@]*)/i =~ name
34
+ verify_subjectAltName_DNS = false
35
+ subjectAltName_URI_sip_entries << $1.downcase
36
+ elsif verify_subjectAltName_DNS && /^DNS:(.*)/i =~ name
37
+ subjectAltName_DNS_entries << $1.downcase
38
+ end
39
+ end
40
+ end
41
+
42
+ unless verify_CN
43
+ puts "DEBUG: certificate contains 'subjectAltName' extensions, 'CommonName' ignored"
44
+ unless verify_subjectAltName_DNS
45
+ subjectAltName_URI_sip_entries.each {|domain| sip_identities[domain] = true}
46
+ puts "DEBUG: 'subjectAltName' entries of type \"URI:sip:\" found, 'subjectAltName' entries of type \"DNS\" ignored"
47
+ else
48
+ subjectAltName_DNS_entries.each {|domain| sip_identities[domain] = true}
49
+ puts "DEBUG: 'subjectAltName' entries of type \"URI:sip:\" not found, using 'subjectAltName' entries of type \"DNS\""
50
+ end
51
+
52
+ else
53
+ puts "DEBUG: no 'subjectAltName' extension found, using 'CommonName' value"
54
+ cert.subject.to_a.each do |oid, value|
55
+ if oid == "CN"
56
+ sip_identities[value.downcase] = true
57
+ break
58
+ end
59
+ end
60
+ end
61
+
62
+ return sip_identities
63
+ end
64
+
65
+ end
66
+
67
+
68
+ unless (file = ARGV[0])
69
+ $stderr.puts "ERROR: no file given as argument"
70
+ exit false
71
+ end
72
+
73
+ unless ::File.file?(file) and ::File.readable?(file)
74
+ $stderr.puts "ERROR: given file is not a readable file"
75
+ exit false
76
+ end
77
+
78
+ begin
79
+ cert = ::OpenSSL::X509::Certificate.new(::File.read(file))
80
+ rescue => e
81
+ $stderr.puts "ERROR: cannot get a PEM certificate in the given file: #{e.message} (#{e.class})"
82
+ exit false
83
+ end
84
+
85
+ sip_identities = TLS.get_sip_identities cert
86
+
87
+ puts
88
+ if sip_identities.any?
89
+ puts "SIP identities found in the certificate:"
90
+ puts
91
+ sip_identities.each_key {|name| puts " - #{name}"}
92
+ else
93
+ puts "No SIP identities found in the certificate"
94
+ end
95
+ puts
@@ -0,0 +1,74 @@
1
+ /*
2
+ * Generic C functions and macros go here, there are no dependencies
3
+ * on OverSIP internal structures or the Ruby C API in here.
4
+ */
5
+
6
+ #ifndef c_util_h
7
+ #define c_util_h
8
+
9
+
10
+ #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
11
+
12
+
13
+ /*
14
+ * str_to_int: Given a pointer to char and length returns an int (but just possitive).
15
+ */
16
+ static int str_to_int(const char* str, size_t len)
17
+ {
18
+ TRACE();
19
+ int number = 0;
20
+ const char *s = str;
21
+
22
+ while (len--) {
23
+ /* Ignore zeroes at the beginning. */
24
+ if (number || *s != '0')
25
+ number = number*10 + (*s)-'0';
26
+ s++;
27
+ }
28
+ return number;
29
+ }
30
+
31
+
32
+ /*
33
+ * strnchr: Find the first character in a length limited string.
34
+ * @s: The string to be searched
35
+ * @len: The number of characters to be searched
36
+ * @c: The character to search for
37
+ */
38
+ static char *strnchr(const char *s, size_t len, size_t c)
39
+ {
40
+ TRACE();
41
+ for (; len--; ++s)
42
+ if (*s == (char)c)
43
+ return (char *)s;
44
+ return NULL;
45
+ }
46
+
47
+
48
+ /*
49
+ * str_find_upcase: Returns non zero if the string (*str, len) contains at least
50
+ * an upcase letter.
51
+ */
52
+ static char *str_find_upcase(const char *s, size_t len)
53
+ {
54
+ TRACE();
55
+ for (; len--; ++s)
56
+ if (*s >= 'A' && *s <= 'Z')
57
+ return (char *)s;
58
+ return NULL;
59
+ }
60
+
61
+
62
+ /*
63
+ * capitalizes all lower-case ASCII characters.
64
+ */
65
+ static void downcase_char(char *c)
66
+ {
67
+ TRACE();
68
+ if (*c >= 'A' && *c <= 'Z')
69
+ *c += 32;
70
+ }
71
+
72
+
73
+ #endif
74
+
@@ -0,0 +1,88 @@
1
+ /*
2
+ * Generic Ruby C functions and macros go here.
3
+ */
4
+
5
+ #ifndef ruby_c_util_h
6
+ #define ruby_c_util_h
7
+
8
+
9
+ #include <ruby.h>
10
+ #include <ruby/encoding.h> /* Required: http://redmine.ruby-lang.org/issues/show/4272 */
11
+ #include "c_util.h"
12
+
13
+
14
+ #define RB_STR_UTF8_NEW(s, len) (rb_enc_str_new(s, len, rb_utf8_encoding()))
15
+
16
+
17
+ /*
18
+ * my_rb_str_hex_unescape: Unescapes hexadecimal encoded symbols (%NN).
19
+ */
20
+ static VALUE my_rb_str_hex_unescape(const char *str, size_t len)
21
+ {
22
+ TRACE();
23
+ /* Check if hexadecimal unescaping is required. */
24
+ if (strnchr(str, len, '%')) {
25
+ char *new_str;
26
+ VALUE str_unescaped;
27
+
28
+ new_str = ALLOC_N(char, len);
29
+ memcpy(new_str, str, len);
30
+
31
+ char *s, *t;
32
+ char hex[3] = {0, 0, 0};
33
+ int i;
34
+
35
+ for (s = t = new_str, i = 0 ; i < len ; s++, i++) {
36
+ if (*s != '%' || !(*(s+1)) || !(*(s+2)))
37
+ *t++ = *s;
38
+ else {
39
+ hex[0] = *(s+1);
40
+ hex[1] = *(s+2);
41
+ *t++ = (strtol(hex, NULL, 16) & 0xFF);
42
+ s += 2;
43
+ len -= 2;
44
+ }
45
+ }
46
+
47
+ str_unescaped = RB_STR_UTF8_NEW(new_str, len);
48
+ xfree(new_str);
49
+ return(str_unescaped);
50
+ }
51
+ /* If unescaping is not required, then create a Ruby string with original pointer and length. */
52
+ else
53
+ return(RB_STR_UTF8_NEW(str, len));
54
+ }
55
+
56
+ /*
57
+ * my_rb_str_downcase: Downcases a string formed by simple symbols (ASCII).
58
+ */
59
+ static VALUE my_rb_str_downcase(const char *str, size_t len)
60
+ {
61
+ TRACE();
62
+ /* Check if there is at least an upcase char. */
63
+ if (str_find_upcase(str, len)) {
64
+ char *new_str;
65
+ VALUE str_downcased;
66
+
67
+ new_str = ALLOC_N(char, len);
68
+ memcpy(new_str, str, len);
69
+
70
+ char *s;
71
+ int i;
72
+
73
+ for (s = new_str, i = 0 ; i < len ; s++, i++)
74
+ if (*s >= 'A' && *s <= 'Z')
75
+ *s += 32;
76
+
77
+ str_downcased = RB_STR_UTF8_NEW(new_str, len);
78
+ xfree(new_str);
79
+ return(str_downcased);
80
+ }
81
+ /* If not, then create a Ruby string with original pointer and length. */
82
+ else
83
+ return(RB_STR_UTF8_NEW(str, len));
84
+ }
85
+
86
+
87
+ #endif
88
+
@@ -0,0 +1,210 @@
1
+ #ifndef common_headers_h
2
+ #define common_headers_h
3
+
4
+ #include "../common/c_util.h"
5
+ #include "ruby.h"
6
+ #include <ctype.h> // toupper()
7
+
8
+
9
+ /* There are 20 headers with sort representation. */
10
+ #define NUM_SHORT_HEADERS 20
11
+
12
+
13
+ struct common_header_name {
14
+ const signed long len;
15
+ const char *name;
16
+ VALUE value;
17
+ const char short_name;
18
+ };
19
+
20
+
21
+ struct short_header {
22
+ char abbr;
23
+ VALUE value;
24
+ };
25
+
26
+
27
+ /*
28
+ * A list of common SIP headers we expect to receive.
29
+ * This allows us to avoid repeatedly creating identical string
30
+ * objects to be used with rb_hash_aset().
31
+ */
32
+ static struct common_header_name common_headers[] = {
33
+ #define f(N, S) { (sizeof(N) - 1), N, Qnil, S }
34
+ f("Accept", ' '),
35
+ f("Accept-Contact", 'A'),
36
+ f("Accept-Encoding", ' '),
37
+ f("Accept-Language", ' '),
38
+ f("Alert-Info", ' '),
39
+ f("Allow", ' '),
40
+ f("Allow-Events", 'U'),
41
+ f("Authentication-Info", ' '),
42
+ f("Authorization", ' '),
43
+ f("Call-ID", 'I'),
44
+ f("Call-Info", ' '),
45
+ f("Contact", 'M'),
46
+ f("Content-Disposition", ' '),
47
+ f("Content-Encoding", 'E'),
48
+ f("Content-Language", ' '),
49
+ f("Content-Length", 'L'),
50
+ f("Content-Type", 'C'),
51
+ f("CSeq", ' '),
52
+ f("Date", ' '),
53
+ f("Event", 'O'),
54
+ f("Error-Info", ' '),
55
+ f("Expires", ' '),
56
+ f("From", 'F'),
57
+ f("Identity", 'Y'),
58
+ f("Identity-Info", 'N'),
59
+ f("In-Reply-To", ' '),
60
+ f("Max-Forwards", ' '),
61
+ f("Min-Expires", ' '),
62
+ f("MIME-Version", ' '),
63
+ f("Organization", ' '),
64
+ f("Priority", ' '),
65
+ f("Proxy-Authenticate", ' '),
66
+ f("Proxy-Authorization", ' '),
67
+ f("Proxy-Require", ' '),
68
+ f("Record-Route", ' '),
69
+ f("Refer-To", 'R'),
70
+ f("Referred-By", 'B'),
71
+ f("Reject-Contact", 'J'),
72
+ f("Reply-To", ' '),
73
+ f("Request-Disposition", 'D'),
74
+ f("Require", ' '),
75
+ f("Retry-After", ' '),
76
+ f("Route", ' '),
77
+ f("Server", ' '),
78
+ f("Session-Expires", 'X'),
79
+ f("Subject", 'S'),
80
+ f("Supported", 'K'),
81
+ f("Timestamp", ' '),
82
+ f("To", 'T'),
83
+ f("Unsupported", ' '),
84
+ f("User-Agent", ' '),
85
+ f("Via", 'V'),
86
+ f("Warning", ' '),
87
+ f("WWW-Authenticate", ' ')
88
+ # undef f
89
+ };
90
+
91
+
92
+ /*
93
+ * The list of short headers. This list is filled by the funcion
94
+ * init_short_header_names.
95
+ */
96
+ static struct short_header short_headers[NUM_SHORT_HEADERS];
97
+
98
+
99
+ /* this function is not performance-critical, called only at load time */
100
+ static void init_common_headers(void)
101
+ {
102
+ TRACE();
103
+ int i;
104
+ struct common_header_name *cf = common_headers;
105
+
106
+ for(i = ARRAY_SIZE(common_headers); --i >= 0; cf++) {
107
+ cf->value = rb_str_new(cf->name, cf->len);
108
+ cf->value = rb_obj_freeze(cf->value);
109
+ /* This tell Ruby not to GC global variables which refer to Ruby's objects,
110
+ but are not exported to the Ruby world. */
111
+ rb_global_variable(&cf->value);
112
+ }
113
+ }
114
+
115
+ /* this funcion fills the list of short headers taken the data from
116
+ * common_headers array.
117
+ */
118
+ static void init_short_headers(void)
119
+ {
120
+ TRACE();
121
+ int i, j;
122
+ struct common_header_name *cf = common_headers;
123
+
124
+ for(i = ARRAY_SIZE(common_headers), j=0; --i >= 0; cf++) {
125
+ if (cf->short_name != ' ') {
126
+ short_headers[j].abbr = cf->short_name;
127
+ short_headers[j].value = cf->value;
128
+ j++;
129
+ }
130
+ }
131
+ }
132
+
133
+ /* this function is called for every header set */
134
+ static VALUE find_common_header_name(const char *name, size_t len)
135
+ {
136
+ TRACE();
137
+ int i;
138
+ struct common_header_name *cf = common_headers;
139
+
140
+ for(i = ARRAY_SIZE(common_headers); --i >= 0; cf++) {
141
+ if (cf->len == (long)len && !strncasecmp(cf->name, name, len))
142
+ return cf->value;
143
+ }
144
+ return Qnil;
145
+ }
146
+
147
+ /* This function is called for every short header found */
148
+ static VALUE find_short_header_name(char abbr)
149
+ {
150
+ TRACE();
151
+ int i;
152
+ struct short_header *sh = short_headers;
153
+
154
+ for(i = ARRAY_SIZE(short_headers); --i >= 0; sh++) {
155
+ if (sh->abbr == toupper(abbr))
156
+ return sh->value;
157
+ }
158
+ return Qnil;
159
+ }
160
+
161
+
162
+ /* Tries to lookup the header name in a list of well-known headers. If so,
163
+ * returns the retrieved VALUE. It also works for short headers.
164
+ * In case the header is unknown, it normalizes it (by capitalizing the
165
+ * first letter and each letter under a "-" or "_" symbol).
166
+ */
167
+ static VALUE headerize(const char* hname, size_t hname_len)
168
+ {
169
+ TRACE();
170
+ VALUE headerized;
171
+ char* str;
172
+ int i;
173
+
174
+ /* Header short name. */
175
+ if (hname_len == 1) {
176
+ headerized = find_short_header_name(hname[0]);
177
+ if (NIL_P(headerized)) {
178
+ headerized = rb_str_new(hname, hname_len);
179
+ /* Downcase the header name. */
180
+ downcase_char(RSTRING_PTR(headerized));
181
+ }
182
+ }
183
+
184
+ /* Header long name. */
185
+ else {
186
+ headerized = find_common_header_name(hname, hname_len);
187
+ if (NIL_P(headerized)) {
188
+ headerized = rb_str_new(hname, hname_len);
189
+ str = RSTRING_PTR(headerized);
190
+ if (*str >= 'a' && *str <= 'z')
191
+ *str &= ~0x20;
192
+
193
+ for(i = 1; i < hname_len; i++) {
194
+ if (str[i-1] == '-' || str[i-1] == '_') {
195
+ if (str[i] >= 'a' && str[i] <= 'z')
196
+ str[i] &= ~0x20;
197
+ }
198
+ else {
199
+ if (str[i] >= 'A' && str[i] <= 'Z')
200
+ str[i] += 32;
201
+ }
202
+ }
203
+ }
204
+ }
205
+
206
+ return(headerized);
207
+ }
208
+
209
+
210
+ #endif
@@ -0,0 +1,18 @@
1
+ #ifndef ext_help_h
2
+ #define ext_help_h
3
+
4
+ #define RAISE_NOT_NULL(T) if(T == NULL) rb_raise(rb_eArgError, "NULL found for " # T " when shouldn't be.");
5
+ #define DATA_GET(from,type,name) Data_Get_Struct(from,type,name); RAISE_NOT_NULL(name);
6
+ #define REQUIRE_TYPE(V, T) if(TYPE(V) != T) rb_raise(rb_eTypeError, "Wrong argument type for " # V " required " # T);
7
+
8
+
9
+ /* Uncomment for enabling TRACE() function. */
10
+ /*#define DEBUG */
11
+
12
+ #ifdef DEBUG
13
+ #define TRACE() fprintf(stderr, "TRACE: %s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__)
14
+ #else
15
+ #define TRACE()
16
+ #endif
17
+
18
+ #endif
@@ -0,0 +1,3 @@
1
+ require "mkmf"
2
+
3
+ create_makefile("oversip/sip/sip_parser")