zimbra_wall 0.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.
- checksums.yaml +7 -0
- data/.gitignore +23 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +147 -0
- data/Rakefile +9 -0
- data/bin/zimbra_wall +52 -0
- data/examples/monit_zimbra_wall +5 -0
- data/examples/zimbra_wall +91 -0
- data/lib/zimbra_wall.rb +36 -0
- data/lib/zimbra_wall/backend.rb +10 -0
- data/lib/zimbra_wall/config.rb +65 -0
- data/lib/zimbra_wall/connection.rb +26 -0
- data/lib/zimbra_wall/debug.rb +15 -0
- data/lib/zimbra_wall/request.rb +75 -0
- data/lib/zimbra_wall/server.rb +72 -0
- data/lib/zimbra_wall/user.rb +67 -0
- data/lib/zimbra_wall/version.rb +3 -0
- data/lib/zimbra_wall/yamler.rb +18 -0
- data/test/fixtures/auth_80.txt +14 -0
- data/test/fixtures/route_7072.txt +9 -0
- data/test/fixtures/users.yml +6 -0
- data/test/fixtures/zco_soap.xml +1 -0
- data/test/test_backend.rb +32 -0
- data/test/test_helper.rb +29 -0
- data/test/test_request.rb +39 -0
- data/test/test_user.rb +71 -0
- data/test/test_yamler.rb +24 -0
- data/zimbra_wall.gemspec +32 -0
- metadata +208 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5ff4ea8a8bac60edb0c0844ea3f9b193b9fc788f
|
4
|
+
data.tar.gz: 348cf17d109ecb33bfb164cf0be7bb74822ff48d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 92421e69edb13bb1542f16486f6b2d45e83475fab0299f33bcdc0b98b70b5bae7297e27b6d3143c48275123fc85bc60048cd2ccfcddc4c74f5559bd60ca8902b
|
7
|
+
data.tar.gz: ce7808dcb42bcce1c7bb0c82b8ba07506fa45dd3ee0a89e9f1f17daa48ae405c340a608ca74e4c945ec7d071ccbd207c193dae2c2e2469bf206d1c7b1e1a2bf1
|
data/.gitignore
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/fixtures/*.org
|
17
|
+
test/version_tmp
|
18
|
+
tmp
|
19
|
+
*.bundle
|
20
|
+
*.so
|
21
|
+
*.o
|
22
|
+
*.a
|
23
|
+
mkmf.log
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Patricio Bruna
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
# Zimbra Wall
|
2
|
+
A server for blocking users to access Zimbra CS.
|
3
|
+
|
4
|
+
This software is used to intercept and apply modifications to the traffic between a Zimbra Proxy and Zimbra Mailboxes.
|
5
|
+
If you don't know what a Zimbra Proxy is, You can read about it here: [https://wiki.zimbra.com/wiki/Zimbra_Proxy_Guide](https://wiki.zimbra.com/wiki/Zimbra_Proxy_Guide)
|
6
|
+
|
7
|
+
This work for all kind of client access:
|
8
|
+
|
9
|
+
* POP3
|
10
|
+
* IMAP
|
11
|
+
* Webmail
|
12
|
+
* ActiveSync
|
13
|
+
* Zimbra Outlook Connector
|
14
|
+
|
15
|
+
## Use cases
|
16
|
+
You need to deny access to some users from Internet.
|
17
|
+
|
18
|
+
|
19
|
+
### How it works
|
20
|
+
Zimbra Wall reads a map file, a `YAML` file, in which you indicate the pair `email:zimbraID` of the users you want to block
|
21
|
+
|
22
|
+
Based on this information, `Zimbra Wall` tell the Zimbra Proxy to deny access to the user.
|
23
|
+
|
24
|
+
## Instalation and configuration
|
25
|
+
|
26
|
+
### Requirements
|
27
|
+
This has been tested with:
|
28
|
+
|
29
|
+
* Zimbra >= 8.5
|
30
|
+
* Ruby >= 1.93
|
31
|
+
* Bundler >= 1.3
|
32
|
+
* Zimbra Proxy
|
33
|
+
|
34
|
+
**You need to have direct access to the `7072` port of both Mailboxes**.
|
35
|
+
|
36
|
+
### Installation
|
37
|
+
It's recommended to install it on the same Zimbra Proxy server. All you need to do is run:
|
38
|
+
|
39
|
+
```bash
|
40
|
+
$ gem install bundler
|
41
|
+
$ gem install zimbra_wall
|
42
|
+
```
|
43
|
+
|
44
|
+
### Zimbra Proxy Modification
|
45
|
+
|
46
|
+
**Important Note**
|
47
|
+
You are going to modify Zimbra template files, used to build the configuration files of Nginx. **Take some backups!!**
|
48
|
+
|
49
|
+
* All the files are located in `/opt/zimbra/conf/nginx/templates`.
|
50
|
+
* `<`, config being replaced
|
51
|
+
* `>`, new config
|
52
|
+
|
53
|
+
You have to make this modifications
|
54
|
+
|
55
|
+
```diff
|
56
|
+
# nginx.conf.web.template
|
57
|
+
< ${web.login.upstream.disable} ${web.upstream.loginserver.:servers}
|
58
|
+
< ${web.login.upstream.disable} ${web.ssl.upstream.loginserver.:servers}
|
59
|
+
---
|
60
|
+
>
|
61
|
+
> ${web.login.upstream.disable} server localhost:9292 fail_timeout=60s version=8.6.0_GA_1153;
|
62
|
+
> ${web.login.upstream.disable} server localhost:9292 fail_timeout=60s version=8.6.0_GA_1153;
|
63
|
+
```
|
64
|
+
|
65
|
+
```diff
|
66
|
+
# nginx.conf.zmlookup.template
|
67
|
+
< zm_lookup_handlers ${zmlookup.:handlers};
|
68
|
+
---
|
69
|
+
> zm_lookup_handlers localhost:9292/service/extension/nginx-lookup;
|
70
|
+
```
|
71
|
+
|
72
|
+
Next restart. You should restart memcached and nginx, but just to be sure:
|
73
|
+
|
74
|
+
```bash
|
75
|
+
$ zmcontrol restart
|
76
|
+
```
|
77
|
+
|
78
|
+
### Starting Zimbra Wall
|
79
|
+
|
80
|
+
```bash
|
81
|
+
$ bundle exec bin/zimbra_wall -d zboxapp.dev -f /tmp/users.yml -m 192.168.50.10 -a 0.0.0.0 -p 9292 --mailbox-port 8080
|
82
|
+
```
|
83
|
+
|
84
|
+
#### Options
|
85
|
+
|
86
|
+
* `-d`, the domain, in case the user only enters the username,
|
87
|
+
* `-m`, One of the mailboxes,
|
88
|
+
* `-f`, the `YAML` map file, with the list of users on the `--newmailbox`,
|
89
|
+
* `-p`, the bind port
|
90
|
+
* `-a`, the bind address
|
91
|
+
* `--mailbox-port`, the mailbox port
|
92
|
+
|
93
|
+
#### The Map File
|
94
|
+
|
95
|
+
It's a simple YAML file with a `email:zimbraId` pair, like
|
96
|
+
|
97
|
+
```yaml
|
98
|
+
max@example.com: "7b562c60-be97-0132-9a66-482a1423458f"
|
99
|
+
moliery@example.com: "7b562ce0-be97-0132-9a66-482a1423458f"
|
100
|
+
watson@example.com: "251b1902-2250-4477-bdd1-8a101f7e7e4e"
|
101
|
+
sherlock@example.com: "7b562dd0-be97-0132-9a66-482a1423458f"
|
102
|
+
```
|
103
|
+
|
104
|
+
Updating the file does **not require** a restart.
|
105
|
+
|
106
|
+
You can get the `zimbraId` with:
|
107
|
+
|
108
|
+
```
|
109
|
+
$ zmprov ga watson@example.com zimbraId
|
110
|
+
```
|
111
|
+
|
112
|
+
##### Error in Map File
|
113
|
+
If you have an error in your file, `Zimbra Wall` will return the on memory Map, this way we can keep the service up. In this event you should see this on `STDOUT`:
|
114
|
+
|
115
|
+
```shel
|
116
|
+
ERROR Yaml File: (./test/fixtures/users.yml): could not find expected ':' while scanning a simple key at line 7
|
117
|
+
```
|
118
|
+
|
119
|
+
## Init scripts
|
120
|
+
|
121
|
+
In the `examples` directory you have the following files:
|
122
|
+
|
123
|
+
* `zimbra_wall`, to start the server on port 9292
|
124
|
+
|
125
|
+
Copy the file to the `/etc/init.d/` directory and then enable the services like this:
|
126
|
+
|
127
|
+
```bash
|
128
|
+
$ chkconfig --add zimbra_wall
|
129
|
+
```
|
130
|
+
|
131
|
+
### Monit
|
132
|
+
It may be posible that this crash for some reason, it's a new software after all. To reduce the down time we recomend to use [Monit](http://mmonit.com/monit/) to monitor and restart `Zimbra Wall` in case of trouble.
|
133
|
+
|
134
|
+
Check the examples directory for config files.
|
135
|
+
|
136
|
+
## Thanks
|
137
|
+
|
138
|
+
* To the Zimbra folks for a great product, and
|
139
|
+
* [@igrigorik](http://twitter.com/igrigorik) for [em-proxy](https://github.com/igrigorik/em-proxy)
|
140
|
+
|
141
|
+
## Contributing
|
142
|
+
|
143
|
+
1. Fork it ( https://github.com/pbruna/zimbra_intercepting_proxy/fork )
|
144
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
145
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
146
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
147
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/bin/zimbra_wall
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'zimbra_wall'
|
5
|
+
require 'optparse'
|
6
|
+
|
7
|
+
# host, port
|
8
|
+
ARGV << '-h' if ARGV.empty?
|
9
|
+
|
10
|
+
options = {}
|
11
|
+
|
12
|
+
optparse = OptionParser.new do |opts|
|
13
|
+
|
14
|
+
opts.banner = "Usage: zimbra_wall [options]"
|
15
|
+
|
16
|
+
opts.on("-dDOMAIN", "--domain=DOMAIN", "Email domain of the mailboxes") do |o|
|
17
|
+
options[:domain] = o
|
18
|
+
end
|
19
|
+
|
20
|
+
opts.on("-fFILE", "--usersfile=FILE", "YAML file with the list of blocked users") do |o|
|
21
|
+
options[:blocked_users_file] = o
|
22
|
+
end
|
23
|
+
|
24
|
+
opts.on("-mSERVER", "--mailbox=SERVER", "Hostname or IP of the mailbox to where we are migrating") do |o|
|
25
|
+
options[:backend] = o
|
26
|
+
end
|
27
|
+
|
28
|
+
opts.on("-zSERVERPORT", "--mailbox-port=SERVERPORT", "Hostname or IP of the mailbox to where we are migrating") do |o|
|
29
|
+
options[:backend_port] = o
|
30
|
+
end
|
31
|
+
|
32
|
+
opts.on("-aADDRESS", "--bindaddress=ADDRESS", "The IP Address to bind to. Default 0.0.0.0") do |o|
|
33
|
+
options[:bind_address] = o
|
34
|
+
end
|
35
|
+
|
36
|
+
opts.on("-pPORT", "--bindport=PORT", "The Port to bind to. Default 0.0.0.0") do |o|
|
37
|
+
options[:bind_port] = o
|
38
|
+
end
|
39
|
+
|
40
|
+
opts.on("-v", "--verbose", "Save logs information to /var/log/zimbra_wall.log") do |o|
|
41
|
+
options[:debug] = true
|
42
|
+
end
|
43
|
+
|
44
|
+
opts.on("-h", "--help", "Prints this help") do
|
45
|
+
puts opts
|
46
|
+
exit
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
optparse.parse!
|
52
|
+
ZimbraWall.start options
|
@@ -0,0 +1,91 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
### BEGIN INIT INFO
|
3
|
+
# Provides:
|
4
|
+
# Default-Start: 2 3 4 5
|
5
|
+
# Default-Stop: 0 1 6
|
6
|
+
# Short-Description: Start daemon at boot time
|
7
|
+
# Description: Enable service provided by daemon.
|
8
|
+
### END INIT INFO
|
9
|
+
|
10
|
+
dir=""
|
11
|
+
user=""
|
12
|
+
cmd="zimbra_wall -d zboxapp.dev -f /tmp/users.yml -m 192.168.50.10 -a 0.0.0.0 -p 9292 --mailbox-port 8080"
|
13
|
+
|
14
|
+
name=`basename $0`
|
15
|
+
pid_file="/var/run/$name.pid"
|
16
|
+
stdout_log="/var/log/$name.log"
|
17
|
+
stderr_log="/var/log/$name.err"
|
18
|
+
|
19
|
+
get_pid() {
|
20
|
+
cat "$pid_file"
|
21
|
+
}
|
22
|
+
|
23
|
+
is_running() {
|
24
|
+
[ -f "$pid_file" ] && ps `get_pid` > /dev/null 2>&1
|
25
|
+
}
|
26
|
+
|
27
|
+
case "$1" in
|
28
|
+
start)
|
29
|
+
if is_running; then
|
30
|
+
echo "Already started"
|
31
|
+
else
|
32
|
+
echo "Starting $name"
|
33
|
+
$cmd >> "$stdout_log" 2>> "$stderr_log" &
|
34
|
+
echo $! > "$pid_file"
|
35
|
+
if ! is_running; then
|
36
|
+
echo "Unable to start, see $stdout_log and $stderr_log"
|
37
|
+
exit 1
|
38
|
+
fi
|
39
|
+
fi
|
40
|
+
;;
|
41
|
+
stop)
|
42
|
+
if is_running; then
|
43
|
+
echo -n "Stopping $name.."
|
44
|
+
kill `get_pid`
|
45
|
+
for i in {1..10}
|
46
|
+
do
|
47
|
+
if ! is_running; then
|
48
|
+
break
|
49
|
+
fi
|
50
|
+
|
51
|
+
echo -n "."
|
52
|
+
sleep 1
|
53
|
+
done
|
54
|
+
echo
|
55
|
+
|
56
|
+
if is_running; then
|
57
|
+
echo "Not stopped; may still be shutting down or shutdown may have failed"
|
58
|
+
exit 1
|
59
|
+
else
|
60
|
+
echo "Stopped"
|
61
|
+
if [ -f "$pid_file" ]; then
|
62
|
+
rm "$pid_file"
|
63
|
+
fi
|
64
|
+
fi
|
65
|
+
else
|
66
|
+
echo "Not running"
|
67
|
+
fi
|
68
|
+
;;
|
69
|
+
restart)
|
70
|
+
$0 stop
|
71
|
+
if is_running; then
|
72
|
+
echo "Unable to stop, will not attempt to start"
|
73
|
+
exit 1
|
74
|
+
fi
|
75
|
+
$0 start
|
76
|
+
;;
|
77
|
+
status)
|
78
|
+
if is_running; then
|
79
|
+
echo "Running"
|
80
|
+
else
|
81
|
+
echo "Stopped"
|
82
|
+
exit 1
|
83
|
+
fi
|
84
|
+
;;
|
85
|
+
*)
|
86
|
+
echo "Usage: $0 {start|stop|restart|status}"
|
87
|
+
exit 1
|
88
|
+
;;
|
89
|
+
esac
|
90
|
+
|
91
|
+
exit 0
|
data/lib/zimbra_wall.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require "yaml"
|
2
|
+
require "uuid"
|
3
|
+
require 'em-proxy'
|
4
|
+
require 'http/parser'
|
5
|
+
require "addressable/uri"
|
6
|
+
require 'logger'
|
7
|
+
require 'cgi'
|
8
|
+
require 'xmlsimple'
|
9
|
+
require "zimbra_wall/version"
|
10
|
+
require "zimbra_wall/user"
|
11
|
+
require "zimbra_wall/config"
|
12
|
+
require "zimbra_wall/backend"
|
13
|
+
require "zimbra_wall/request"
|
14
|
+
require "zimbra_wall/server"
|
15
|
+
require "zimbra_wall/debug"
|
16
|
+
require "zimbra_wall/connection"
|
17
|
+
require "zimbra_wall/yamler"
|
18
|
+
|
19
|
+
module ZimbraWall
|
20
|
+
|
21
|
+
def self.start(options)
|
22
|
+
config!(options)
|
23
|
+
ZimbraWall::Server.run
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.config!(options)
|
27
|
+
ZimbraWall::Config.domain = options[:domain]
|
28
|
+
ZimbraWall::Config.blocked_users_file = options[:blocked_users_file]
|
29
|
+
ZimbraWall::Config.backend = options[:backend]
|
30
|
+
ZimbraWall::Config.backend_port = options[:backend_port]
|
31
|
+
ZimbraWall::Config.bind_address = options[:bind_address] || "0.0.0.0"
|
32
|
+
ZimbraWall::Config.bind_port = options[:bind_port]
|
33
|
+
ZimbraWall::Config.debug = options[:debug]
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module ZimbraWall
|
2
|
+
module Config
|
3
|
+
|
4
|
+
ROUTE_URL = "/service/extension/nginx-lookup"
|
5
|
+
ROUTE_REQUEST_PORT = 7072
|
6
|
+
AUTH_REQUEST_PORT = 80
|
7
|
+
|
8
|
+
def self.domain=(domain)
|
9
|
+
@domain = domain
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.domain
|
13
|
+
@domain
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.blocked_users_file=(file)
|
17
|
+
@blocked_users_file = file
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.blocked_users_file
|
21
|
+
@blocked_users_file
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.backend=(backend)
|
25
|
+
@backend = backend
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.backend
|
29
|
+
@backend
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.backend_port=(port)
|
33
|
+
@backend_port = port
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.backend_port
|
37
|
+
@backend_port
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.bind_port=(bind_port)
|
41
|
+
@bind_port = bind_port
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.bind_port
|
45
|
+
@bind_port
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.bind_address=(bind_address)
|
49
|
+
@bind_address = bind_address
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.bind_address
|
53
|
+
@bind_address
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.debug=(debug)
|
57
|
+
@debug = debug
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.debug
|
61
|
+
@debug
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module ZimbraWall
|
2
|
+
class Connection
|
3
|
+
|
4
|
+
attr_accessor :headers, :body, :started, :done, :buffer
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@headers = nil
|
8
|
+
@body = ""
|
9
|
+
@started = false
|
10
|
+
@done = false
|
11
|
+
@buffer = ''
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.parse_lookup_response(resp)
|
15
|
+
array = resp.split("\r\n")
|
16
|
+
array.push("")
|
17
|
+
hash = {}
|
18
|
+
array[1..-1].each do |h|
|
19
|
+
tmp = h.split(/: /)
|
20
|
+
hash[tmp[0]] = tmp[1]
|
21
|
+
end
|
22
|
+
hash
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module ZimbraWall
|
2
|
+
class Request
|
3
|
+
require 'pp'
|
4
|
+
|
5
|
+
attr_accessor :body, :headers, :parser
|
6
|
+
|
7
|
+
def initialize(connection, parser = nil)
|
8
|
+
@body = connection.body
|
9
|
+
@headers = connection.headers
|
10
|
+
@parser = parser
|
11
|
+
end
|
12
|
+
|
13
|
+
def auth_request?
|
14
|
+
default_auth_request? || zco_auth_request?
|
15
|
+
end
|
16
|
+
|
17
|
+
# This is the post Auth request sent by Webmail, ActiveSync and POP and IMAP
|
18
|
+
def default_auth_request?
|
19
|
+
@parser.http_method == 'POST' && @parser.request_url == '/' && @headers["Cookie"] = "ZM_TEST=true" && auth_request_params?
|
20
|
+
end
|
21
|
+
|
22
|
+
def zco_auth_request?
|
23
|
+
@parser.http_method == 'POST' && @parser.request_url == "/service/soap/AuthRequest" && @headers["User-Agent"].match(/Zimbra-ZCO/)
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
def blank_password_from_body
|
28
|
+
params = CGI::parse(@body)
|
29
|
+
params['password'] = ['']
|
30
|
+
URI.encode_www_form params
|
31
|
+
end
|
32
|
+
|
33
|
+
def auth_request_params?
|
34
|
+
uri = Addressable::URI.parse("#{@headers['Origin']}/?#{@body}")
|
35
|
+
uri.query_values["loginOp"] == "login"
|
36
|
+
end
|
37
|
+
|
38
|
+
def modify_query_field(field, value)
|
39
|
+
uri = Addressable::URI.parse("#{@headers['Referer']}?#{@body}")
|
40
|
+
uri.query_values[field] = value
|
41
|
+
uri.query_values
|
42
|
+
end
|
43
|
+
|
44
|
+
def route_request?
|
45
|
+
@parser.request_url == ZimbraWall::Config::ROUTE_URL
|
46
|
+
end
|
47
|
+
|
48
|
+
def port
|
49
|
+
return ZimbraWall::Config::ROUTE_REQUEST_PORT if route_request?
|
50
|
+
return ZimbraWall::Config::AUTH_REQUEST_PORT if auth_request?
|
51
|
+
end
|
52
|
+
|
53
|
+
def user_token
|
54
|
+
return auth_username if default_auth_request?
|
55
|
+
return auth_zimbraId if route_request?
|
56
|
+
return auth_zco_username if zco_auth_request?
|
57
|
+
end
|
58
|
+
|
59
|
+
def auth_zimbraId
|
60
|
+
headers["Auth-User"]
|
61
|
+
end
|
62
|
+
|
63
|
+
def auth_zco_username
|
64
|
+
# Hold on, we have to dig deeper
|
65
|
+
xml = XmlSimple.xml_in @body
|
66
|
+
xml["Body"].first["AuthRequest"].first["account"].first["content"]
|
67
|
+
end
|
68
|
+
|
69
|
+
def auth_username
|
70
|
+
uri = Addressable::URI.parse("http://localhost/?#{@body}")
|
71
|
+
uri.query_values["username"]
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module ZimbraWall
|
2
|
+
|
3
|
+
module Server
|
4
|
+
require 'pp'
|
5
|
+
|
6
|
+
|
7
|
+
def run
|
8
|
+
debug = ZimbraWall::Debug
|
9
|
+
host = ZimbraWall::Config.bind_address
|
10
|
+
port = ZimbraWall::Config.bind_port
|
11
|
+
|
12
|
+
Proxy.start(host: host, port: port) do |conn|
|
13
|
+
debug.logger "Running on #{host}:#{port} - V. #{ZimbraWall::VERSION}"
|
14
|
+
|
15
|
+
@backend = { host: ZimbraWall::Config.backend, port: '7072' }
|
16
|
+
connection = ZimbraWall::Connection.new
|
17
|
+
|
18
|
+
@parser = Http::Parser.new
|
19
|
+
@parser.on_message_begin = proc { connection.started = true }
|
20
|
+
@parser.on_headers_complete = proc { |e| connection.headers = e }
|
21
|
+
@parser.on_body = proc { |chunk| connection.body << chunk }
|
22
|
+
@parser.on_message_complete = proc do
|
23
|
+
request = ZimbraWall::Request.new(connection, @parser)
|
24
|
+
if request.auth_request?
|
25
|
+
@backend[:port] = ZimbraWall::Config.backend_port
|
26
|
+
user = User.new(request.user_token)
|
27
|
+
if user.blocked?
|
28
|
+
connection.buffer.gsub!(/(?<=&password=).*(?=(&|$))/, '')
|
29
|
+
puts "User blocked: #{user.email} - #{user.zimbraId}"
|
30
|
+
end
|
31
|
+
conn.server @backend[:host], host: @backend[:host], port: @backend[:port]
|
32
|
+
conn.relay_to_servers connection.buffer
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
conn.server @backend[:host], host: @backend[:host], port: @backend[:port]
|
37
|
+
conn.relay_to_servers connection.buffer
|
38
|
+
connection.buffer.clear
|
39
|
+
|
40
|
+
conn.on_connect do |data, b|
|
41
|
+
debug.logger [:on_connect, data, b]
|
42
|
+
end
|
43
|
+
|
44
|
+
conn.on_data do |data|
|
45
|
+
debug.logger [:on_data, data]
|
46
|
+
connection.buffer << data
|
47
|
+
@parser << data if data !~ /\/service\/extension\/nginx-lookup/
|
48
|
+
data
|
49
|
+
end
|
50
|
+
|
51
|
+
conn.on_response do |backend, resp|
|
52
|
+
debug.logger [:on_response, backend, resp]
|
53
|
+
if resp =~ /Auth-Status/i
|
54
|
+
lookup_resp = ZimbraWall::Connection.parse_lookup_response(resp)
|
55
|
+
user = User.new(lookup_resp['Auth-User'])
|
56
|
+
if user.blocked?
|
57
|
+
puts "User blocked: #{user.email} - #{user.zimbraId}"
|
58
|
+
resp.gsub!(/Auth-Status: OK/, 'Auth-Status: ERR')
|
59
|
+
end
|
60
|
+
end
|
61
|
+
resp
|
62
|
+
end
|
63
|
+
|
64
|
+
conn.on_finish do |_, name|
|
65
|
+
debug.logger [:on_finish, name].inspect
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
module_function :run
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module ZimbraWall
|
2
|
+
|
3
|
+
class User
|
4
|
+
attr_accessor :email, :zimbraId
|
5
|
+
|
6
|
+
@@db = {}
|
7
|
+
|
8
|
+
# user_identifier can be an email address, zimbraId UUID or just the
|
9
|
+
# local part of an email address, like user in user@example.com
|
10
|
+
def initialize(user_identifier)
|
11
|
+
@zimbraId = set_zimbraId user_identifier
|
12
|
+
@email = set_email user_identifier
|
13
|
+
User.load_migrated_users
|
14
|
+
end
|
15
|
+
|
16
|
+
# If user has email (unless email.nil?)
|
17
|
+
def blocked?
|
18
|
+
!find_in_db.nil?
|
19
|
+
end
|
20
|
+
|
21
|
+
def backend
|
22
|
+
ZimbraWall::Config.backend
|
23
|
+
end
|
24
|
+
|
25
|
+
def find_in_db
|
26
|
+
self.zimbraId = User.DB[email] if has_email?
|
27
|
+
self.email = User.DB.invert[zimbraId] if has_zimbraId?
|
28
|
+
User.DB[email] || User.DB.invert[zimbraId]
|
29
|
+
end
|
30
|
+
|
31
|
+
def has_email?
|
32
|
+
!email.nil?
|
33
|
+
end
|
34
|
+
|
35
|
+
def has_zimbraId?
|
36
|
+
!zimbraId.nil?
|
37
|
+
end
|
38
|
+
|
39
|
+
# Return the old DB if the YAML file has error
|
40
|
+
def self.load_migrated_users
|
41
|
+
data = ZimbraWall::Yamler.db
|
42
|
+
return @@db unless data
|
43
|
+
@@db = data
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.DB
|
47
|
+
load_migrated_users
|
48
|
+
@@db
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
def set_zimbraId user_identifier
|
53
|
+
return user_identifier if UUID.validate user_identifier
|
54
|
+
nil
|
55
|
+
end
|
56
|
+
|
57
|
+
def set_email user_identifier
|
58
|
+
return nil if user_identifier.nil?
|
59
|
+
return user_identifier if user_identifier.match(/@/)
|
60
|
+
return "#{user_identifier}@#{ZimbraWall::Config.domain}" unless UUID.validate user_identifier
|
61
|
+
nil
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module ZimbraWall
|
2
|
+
|
3
|
+
module Yamler
|
4
|
+
require 'pp'
|
5
|
+
|
6
|
+
def self.db
|
7
|
+
begin
|
8
|
+
YAML.load_file ZimbraWall::Config.blocked_users_file
|
9
|
+
rescue Psych::SyntaxError => e
|
10
|
+
puts "ERROR Yaml File: #{e}"
|
11
|
+
return false
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
POST /zimbra/ HTTP/1.0
|
2
|
+
X-Forwarded-For: 186.67.32.114
|
3
|
+
Host: 200.91.20.185
|
4
|
+
Connection: close
|
5
|
+
Content-Type: application/x-www-form-urlencoded
|
6
|
+
Origin: http://190.196.208.85
|
7
|
+
Cookie: ZM_TEST=true; ZM_TEST=true
|
8
|
+
Content-Length: 66
|
9
|
+
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
|
10
|
+
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/600.5.17 (KHTML, like Gecko) Version/8.0.5 Safari/600.5.17
|
11
|
+
Accept-Language: es-es
|
12
|
+
Accept-Encoding: gzip, deflate
|
13
|
+
|
14
|
+
loginOp=login&username=pbruna&password=5693537374&client=preferred
|
@@ -0,0 +1,6 @@
|
|
1
|
+
pato@example.com: "7b562ae0-be97-0132-9a66-482a1423458f"
|
2
|
+
max@example.com: "7b562c60-be97-0132-9a66-482a1423458f"
|
3
|
+
moliery@example.com: "7b562ce0-be97-0132-9a66-482a1423458f"
|
4
|
+
watson@example.com: "251b1902-2250-4477-bdd1-8a101f7e7e4e"
|
5
|
+
sherlock@example.com: "7b562dd0-be97-0132-9a66-482a1423458f"
|
6
|
+
pbruna@itlinux.cl: "cfd6e914-4f00-440c-9a57-e1a9327128b9"
|
@@ -0,0 +1 @@
|
|
1
|
+
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"><soap:Header><context xmlns="urn:zimbra"><userAgent name="ZimbraConnectorForOutlook" version="8.5.1.1259"/><nonotify/><noqualify/></context></soap:Header><soap:Body><AuthRequest xmlns="urn:zimbraAccount"><account by="name">watson@example.com</account><password>watson</password><virtualHost>200.91.20.186</virtualHost></AuthRequest></soap:Body></soap:Envelope>
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Backend < Minitest::Test
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@user_migrated_email = ZimbraWall::User.new("watson@example.com")
|
7
|
+
@user_migrated_zimbraId = ZimbraWall::User.new("251b1902-2250-4477-bdd1-8a101f7e7e4e")
|
8
|
+
@user_not_migrated_email = ZimbraWall::User.new("jackbower@example.com")
|
9
|
+
@user_not_migrated_zimbraId = ZimbraWall::User.new("251b1902-2250-4477-bdd1-8a101f7e7333")
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_should_return_old_backend_if_user_email_is_not_migrated
|
13
|
+
backend = ZimbraWall::Backend.for_user @user_not_migrated_email
|
14
|
+
assert_equal(ZimbraWall::Config.old_backend, backend)
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_should_return_old_backend_if_user_zimbraID_is_not_migrated
|
18
|
+
backend = ZimbraWall::Backend.for_user @user_not_migrated_zimbraId
|
19
|
+
assert_equal(ZimbraWall::Config.old_backend, backend)
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_should_return_new_backend_if_user_email_was_migrated
|
23
|
+
backend = ZimbraWall::Backend.for_user @user_migrated_email
|
24
|
+
assert_equal(ZimbraWall::Config.new_backend, backend)
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_should_return_new_backend_if_user_zimbraID_was_migrated
|
28
|
+
backend = ZimbraWall::Backend.for_user @user_migrated_zimbraId
|
29
|
+
assert_equal(ZimbraWall::Config.new_backend, backend)
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require "zimbra_intercepting_proxy"
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
require 'minitest/autorun'
|
5
|
+
require 'minitest/reporters' # requires the gem
|
6
|
+
|
7
|
+
Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new # spec-like progress
|
8
|
+
|
9
|
+
ZimbraWall::Config.domain="example.com"
|
10
|
+
ZimbraWall::Config.blocked_users_file="./test/fixtures/users.yml"
|
11
|
+
ZimbraWall::Config.old_backend = "old-mailbox.example.com"
|
12
|
+
ZimbraWall::Config.new_backend = "new-mailbox.zboxapp.com"
|
13
|
+
|
14
|
+
def add_error_line
|
15
|
+
f = File.open ZimbraWall::Config.blocked_users_file, "a"
|
16
|
+
f.puts "juan :94949494-9494949-040404"
|
17
|
+
f.close
|
18
|
+
end
|
19
|
+
|
20
|
+
def restore_map_file
|
21
|
+
backup_file = "./test/fixtures/users.yml.org"
|
22
|
+
FileUtils.cp(backup_file, ZimbraWall::Config.blocked_users_file)
|
23
|
+
FileUtils.rm "./test/fixtures/users.yml.org"
|
24
|
+
end
|
25
|
+
|
26
|
+
def backup_map_file
|
27
|
+
backup_file = "./test/fixtures/users.yml.org"
|
28
|
+
FileUtils.cp(ZimbraWall::Config.blocked_users_file, backup_file)
|
29
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Request < Minitest::Test
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@done = false
|
7
|
+
@auth_request = IO.read("./test/fixtures/auth_80.txt")
|
8
|
+
@route_request = IO.read("./test/fixtures/route_7072.txt")
|
9
|
+
@soap_auth_request = IO.read("./test/fixtures/zco_soap.xml")
|
10
|
+
@connection = OpenStruct.new
|
11
|
+
@parser = OpenStruct.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_should_return_user_token_from_auth_request
|
15
|
+
@parser.http_method = "POST"
|
16
|
+
@parser.request_url = "/zimbra/"
|
17
|
+
@connection.headers = {"Cookie" => "ZM_TEST=true"}
|
18
|
+
@connection.body = "loginOp=login&username=pbruna&password=5693537374&client=preferred"
|
19
|
+
request = ZimbraWall::Request.new @connection, @parser
|
20
|
+
assert_equal("pbruna", request.user_token)
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_should_return_user_token_from_route_request
|
24
|
+
@parser.request_url = ZimbraWall::Config::ROUTE_URL
|
25
|
+
@connection.headers = {"Auth-User" => "251b1902-2250-4477-bdd1-8a101f7e7e4e"}
|
26
|
+
request = ZimbraWall::Request.new @connection, @parser
|
27
|
+
assert_equal("251b1902-2250-4477-bdd1-8a101f7e7e4e", request.user_token)
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_should_get_username_from_zco_auth_request
|
31
|
+
@parser.http_method = "POST"
|
32
|
+
@parser.request_url = "/service/soap/AuthRequest"
|
33
|
+
@connection.headers = {"User-Agent" => "Zimbra-ZCO"}
|
34
|
+
@connection.body = @soap_auth_request
|
35
|
+
request = ZimbraWall::Request.new @connection, @parser
|
36
|
+
assert_equal("watson@example.com", request.user_token)
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
data/test/test_user.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class User < Minitest::Test
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@user = {email: "watson@example.com", zimbraId: "251b1902-2250-4477-bdd1-8a101f7e7e4e"}
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_only_set_zimbraId_when_passed_a_zimbraId
|
10
|
+
u = ZimbraWall::User.new(@user[:zimbraId])
|
11
|
+
assert_equal(u.zimbraId, @user[:zimbraId])
|
12
|
+
assert_nil(u.email)
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_only_set_email_when_passed_an_email
|
16
|
+
u = ZimbraWall::User.new(@user[:email])
|
17
|
+
assert_equal(u.email, @user[:email])
|
18
|
+
assert_nil(u.zimbraId)
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_return_email_when_passed_just_an_username
|
22
|
+
u = ZimbraWall::User.new("watson")
|
23
|
+
assert_equal(u.email, @user[:email])
|
24
|
+
assert_nil(u.zimbraId)
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_should_load_db_user_file_to_global_hash
|
28
|
+
assert_equal(ZimbraWall::User.DB.class, Hash)
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_db_should_have_emails_when_email_is_passed
|
32
|
+
assert(ZimbraWall::User.DB["watson@example.com"])
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_return_true_if_migrated_user_with_zimbraId
|
36
|
+
u = ZimbraWall::User.new("7b562ce0-be97-0132-9a66-482a1423458f")
|
37
|
+
assert(u.migrated?, "Failure message.")
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_return_false_if_not_migrated_user_with_zimbraId
|
41
|
+
u = ZimbraWall::User.new("7b562ce0-be97-0132-9a66-482a14234333")
|
42
|
+
assert(!u.migrated?, "Failure message.")
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_return_true_if_migrated_user_with_email
|
46
|
+
u = ZimbraWall::User.new(@user[:email])
|
47
|
+
assert(u.migrated?, "Failure message.")
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_return_false_if_no_migrated_user_with_email
|
51
|
+
u = ZimbraWall::User.new("pbruna")
|
52
|
+
assert(!u.migrated?, "Failure message.")
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_migrated_false_if_email_nil
|
56
|
+
u = ZimbraWall::User.new(nil)
|
57
|
+
assert(!u.migrated?, "Failure message.")
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
def test_return_old_db_if_yamler_db_is_false
|
62
|
+
backup_map_file # backup users.yml
|
63
|
+
yaml_1 = ZimbraWall::User.DB.inspect
|
64
|
+
add_error_line
|
65
|
+
yaml_2 = ZimbraWall::User.DB.inspect
|
66
|
+
restore_map_file
|
67
|
+
assert_equal(Digest::MD5.digest(yaml_1), Digest::MD5.digest(yaml_2))
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
end
|
data/test/test_yamler.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'digest'
|
3
|
+
|
4
|
+
class Yamler < Minitest::Test
|
5
|
+
|
6
|
+
def setup
|
7
|
+
backup_map_file
|
8
|
+
end
|
9
|
+
|
10
|
+
def teardown
|
11
|
+
restore_map_file
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_yamler_db_must_return_the_yaml_file_hash
|
15
|
+
db = ZimbraWall::Yamler.db
|
16
|
+
assert_equal("251b1902-2250-4477-bdd1-8a101f7e7e4e", db["watson@example.com"])
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_return_false_if_updated_files_has_error
|
20
|
+
add_error_line
|
21
|
+
assert(!ZimbraWall::Yamler.db, "Failure message.")
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
data/zimbra_wall.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'zimbra_wall/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "zimbra_wall"
|
8
|
+
spec.version = ZimbraWall::VERSION
|
9
|
+
spec.authors = ["Patricio Bruna"]
|
10
|
+
spec.email = ["pbruna@itlinux.cl"]
|
11
|
+
spec.summary = "An authorization wall for Zimbra"
|
12
|
+
spec.description = spec.summary
|
13
|
+
spec.homepage = "https://github.com/pbruna/zimbra_wall"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency 'em-proxy', "~> 0.1.8"
|
22
|
+
spec.add_dependency 'thor', "~> 0.19"
|
23
|
+
spec.add_dependency 'uuid', "~> 2.3"
|
24
|
+
spec.add_dependency 'http_parser.rb', "~> 0.6"
|
25
|
+
spec.add_dependency 'addressable', "~> 2.3"
|
26
|
+
spec.add_dependency 'xml-simple', "~> 1.1"
|
27
|
+
spec.add_development_dependency "bundler"
|
28
|
+
|
29
|
+
|
30
|
+
spec.add_development_dependency "rake"
|
31
|
+
spec.add_development_dependency "minitest-reporters"
|
32
|
+
end
|
metadata
ADDED
@@ -0,0 +1,208 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: zimbra_wall
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Patricio Bruna
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-05-10 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: em-proxy
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.1.8
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.1.8
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: thor
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.19'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.19'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: uuid
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2.3'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2.3'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: http_parser.rb
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.6'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.6'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: addressable
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '2.3'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '2.3'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: xml-simple
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.1'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.1'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: bundler
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rake
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: minitest-reporters
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
description: An authorization wall for Zimbra
|
140
|
+
email:
|
141
|
+
- pbruna@itlinux.cl
|
142
|
+
executables:
|
143
|
+
- zimbra_wall
|
144
|
+
extensions: []
|
145
|
+
extra_rdoc_files: []
|
146
|
+
files:
|
147
|
+
- ".gitignore"
|
148
|
+
- Gemfile
|
149
|
+
- LICENSE.txt
|
150
|
+
- README.md
|
151
|
+
- Rakefile
|
152
|
+
- bin/zimbra_wall
|
153
|
+
- examples/monit_zimbra_wall
|
154
|
+
- examples/zimbra_wall
|
155
|
+
- lib/zimbra_wall.rb
|
156
|
+
- lib/zimbra_wall/backend.rb
|
157
|
+
- lib/zimbra_wall/config.rb
|
158
|
+
- lib/zimbra_wall/connection.rb
|
159
|
+
- lib/zimbra_wall/debug.rb
|
160
|
+
- lib/zimbra_wall/request.rb
|
161
|
+
- lib/zimbra_wall/server.rb
|
162
|
+
- lib/zimbra_wall/user.rb
|
163
|
+
- lib/zimbra_wall/version.rb
|
164
|
+
- lib/zimbra_wall/yamler.rb
|
165
|
+
- test/fixtures/auth_80.txt
|
166
|
+
- test/fixtures/route_7072.txt
|
167
|
+
- test/fixtures/users.yml
|
168
|
+
- test/fixtures/zco_soap.xml
|
169
|
+
- test/test_backend.rb
|
170
|
+
- test/test_helper.rb
|
171
|
+
- test/test_request.rb
|
172
|
+
- test/test_user.rb
|
173
|
+
- test/test_yamler.rb
|
174
|
+
- zimbra_wall.gemspec
|
175
|
+
homepage: https://github.com/pbruna/zimbra_wall
|
176
|
+
licenses:
|
177
|
+
- MIT
|
178
|
+
metadata: {}
|
179
|
+
post_install_message:
|
180
|
+
rdoc_options: []
|
181
|
+
require_paths:
|
182
|
+
- lib
|
183
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - ">="
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0'
|
188
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
189
|
+
requirements:
|
190
|
+
- - ">="
|
191
|
+
- !ruby/object:Gem::Version
|
192
|
+
version: '0'
|
193
|
+
requirements: []
|
194
|
+
rubyforge_project:
|
195
|
+
rubygems_version: 2.5.1
|
196
|
+
signing_key:
|
197
|
+
specification_version: 4
|
198
|
+
summary: An authorization wall for Zimbra
|
199
|
+
test_files:
|
200
|
+
- test/fixtures/auth_80.txt
|
201
|
+
- test/fixtures/route_7072.txt
|
202
|
+
- test/fixtures/users.yml
|
203
|
+
- test/fixtures/zco_soap.xml
|
204
|
+
- test/test_backend.rb
|
205
|
+
- test/test_helper.rb
|
206
|
+
- test/test_request.rb
|
207
|
+
- test/test_user.rb
|
208
|
+
- test/test_yamler.rb
|