oversip 0.9.0 → 0.9.1

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.
@@ -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/ruby1.9.1
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/ruby1.9.1
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,31 @@
1
+ #
2
+ # OverSIP - WebSocket Access Policy
3
+ #
4
+ #
5
+ # Fill these functions with your own access policy for allowing or
6
+ # disallowing WebSocket connections from clients.
7
+ #
8
+ # If any of the following methods return _false_ then the WebSocket
9
+ # connection is rejected.
10
+
11
+
12
+ module OverSIP::WebSocket::Policy
13
+
14
+ # Check the value of the Host header, by splitting it into
15
+ # host (a String) and port (Fixnum). Both could be _nil_.
16
+ def check_hostport host=nil, port=nil
17
+ return true
18
+ end
19
+
20
+ # Check the value of the Origin header (a String with original value).
21
+ def check_origin origin=nil
22
+ return true
23
+ end
24
+
25
+ # Check the request URI path (String) and query (String). Both can be _nil_.
26
+ def check_request_uri path=nil, query=nil
27
+ return true
28
+ end
29
+
30
+ end
31
+
data/ext/stud/extconf.rb CHANGED
@@ -12,9 +12,10 @@ end
12
12
 
13
13
 
14
14
  here = File.expand_path(File.dirname(__FILE__))
15
- stud_tarball = "#{here}/stud.tar.gz"
15
+ stud_dir = "#{here}/../../thirdparty/stud/"
16
+ stud_tarball = "stud.tar.gz"
16
17
 
17
- Dir.chdir(here) do
18
+ Dir.chdir(stud_dir) do
18
19
  sys("tar -zxf #{stud_tarball}")
19
20
  Dir.chdir("stud") do
20
21
  sys("make")
@@ -446,6 +446,9 @@ module OverSIP::Launcher
446
446
  # Kill Stud processes.
447
447
  pid = Process.spawn "killall oversip_stud 2>/dev/null"
448
448
  Process.wait(pid)
449
+ sleep 0.5
450
+ pid = Process.spawn "killall -9 oversip_stud 2>/dev/null"
451
+ Process.wait(pid)
449
452
 
450
453
  # Exit by preventing any exception.
451
454
  exit!( error ? false : true )
@@ -5,7 +5,7 @@ module OverSIP
5
5
  module Version
6
6
  MAJOR = 0
7
7
  MINOR = 9
8
- TINY = 0
8
+ TINY = 1
9
9
  end
10
10
 
11
11
  PROGRAM_NAME = "OverSIP"
File without changes
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oversip
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.9.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-07-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: eventmachine-le
16
- requirement: &22334580 !ruby/object:Gem::Requirement
16
+ requirement: &13397980 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 1.1.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *22334580
24
+ version_requirements: *13397980
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: iobuffer
27
- requirement: &22333920 !ruby/object:Gem::Requirement
27
+ requirement: &13397340 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 1.1.2
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *22333920
35
+ version_requirements: *13397340
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: em-posixmq
38
- requirement: &22333300 !ruby/object:Gem::Requirement
38
+ requirement: &13396680 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 0.2.3
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *22333300
46
+ version_requirements: *13396680
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: em-udns
49
- requirement: &22332660 !ruby/object:Gem::Requirement
49
+ requirement: &13396180 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 0.3.6
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *22332660
57
+ version_requirements: *13396180
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: escape_utils
60
- requirement: &22332180 !ruby/object:Gem::Requirement
60
+ requirement: &13395700 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: 0.2.4
66
66
  type: :runtime
67
67
  prerelease: false
68
- version_requirements: *22332180
68
+ version_requirements: *13395700
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: term-ansicolor
71
- requirement: &22331800 !ruby/object:Gem::Requirement
71
+ requirement: &13395320 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :runtime
78
78
  prerelease: false
79
- version_requirements: *22331800
79
+ version_requirements: *13395320
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: posix-spawn
82
- requirement: &22331320 !ruby/object:Gem::Requirement
82
+ requirement: &13394720 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,7 +87,7 @@ dependencies:
87
87
  version: '0'
88
88
  type: :runtime
89
89
  prerelease: false
90
- version_requirements: *22331320
90
+ version_requirements: *13394720
91
91
  description: ! "OverSIP is an async SIP server. Built on top of Ruby EventMachine\n
92
92
  \ library it follows the Reactor Pattern, allowing thousands of concurrent connections
93
93
  and requests\n handled by a single processor in a never-blocking fashion. It
@@ -216,11 +216,30 @@ files:
216
216
  - ext/websocket_framing_utils/ws_framing_utils.h
217
217
  - ext/websocket_framing_utils/ws_framing_utils_ruby.c
218
218
  - ext/stud/extconf.rb
219
- - ext/stud/stud.tar.gz
219
+ - thirdparty/stud/stud.tar.gz
220
+ - etc/oversip.conf
221
+ - etc/logic.rb
222
+ - etc/proxies.conf
223
+ - etc/websocket_policy.rb
224
+ - etc/tls/demo-tls.oversip.net.crt
225
+ - etc/tls/demo-tls.oversip.net.key
226
+ - etc/tls/upgrade-cacert.sh
227
+ - etc/tls/ca/cacert.pem
228
+ - etc/tls/utils/get-sip-identities.rb
229
+ - etc/tls/utils/create-cert.rb
230
+ - debian/postrm
231
+ - debian/compat
232
+ - debian/copyright
233
+ - debian/rules
234
+ - debian/oversip.init
235
+ - debian/oversip.default
236
+ - debian/changelog
237
+ - debian/postinst
238
+ - debian/control
220
239
  - Rakefile
221
240
  - README.md
222
- - AUTHORS.txt
223
- - LICENSE.txt
241
+ - AUTHORS
242
+ - LICENSE
224
243
  - test/oversip_test_helper.rb
225
244
  - test/test_sip_parser.rb
226
245
  - test/test_http_parser.rb