oversip_p 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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")