oversip 0.9.0 → 0.9.1

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