Repository: certbot/certbot

Issue:
Nginx config parser cannot work with unix domain sock host
## Sumally
In certbot-nginx  
If there are some unix domain socket listen, It fail with `AttributeError: 'NoneType' object has no attribute 'ssl'`.

## Why
In [parser.py#L590](https://github.com/certbot/certbot/blob/master/certbot-nginx/certbot_nginx/parser.py#L590), it see `addr.ssl` of `obj.Addr`. but in `obj.Add.fromStriing` of `obj.py`, it [return `None`](https://github.com/certbot/certbot/blob/master/certbot-nginx/certbot_nginx/obj.py#L55) if it is the unix socket address.

## StackTrace and near log
```
Sending GET request to https://acme-staging.api.letsencrypt.org/directory.
Starting new HTTPS connection (1): acme-staging.api.letsencrypt.org
https://acme-staging.api.letsencrypt.org:443 "GET /directory HTTP/1.1" 200 372
Received response:
HTTP 200
Server: nginx
Content-Type: application/json
Content-Length: 372
Boulder-Request-Id: YEAeUNxir_MlrTWVJreyrS33D5Os8PVzytg-1B6vFi8
Replay-Nonce: pytUVIcXyJI1GtdD5Yek-PXthHeg5_XEHrww7zdtTnA
X-Frame-Options: DENY
Strict-Transport-Security: max-age=604800
Expires: Wed, 15 Feb 2017 16:05:39 GMT
Cache-Control: max-age=0, no-cache, no-store
Pragma: no-cache
Date: Wed, 15 Feb 2017 16:05:39 GMT
Connection: keep-alive

{
  "key-change": "https://acme-staging.api.letsencrypt.org/acme/key-change",
  "new-authz": "https://acme-staging.api.letsencrypt.org/acme/new-authz",
  "new-cert": "https://acme-staging.api.letsencrypt.org/acme/new-cert",
  "new-reg": "https://acme-staging.api.letsencrypt.org/acme/new-reg",
  "revoke-cert": "https://acme-staging.api.letsencrypt.org/acme/revoke-cert"
}
Exiting abnormally:
Traceback (most recent call last):
  File "/usr/local/bin/certbot", line 11, in <module>
    sys.exit(main())
  File "/opt/letsencrypt/local/lib/python2.7/site-packages/certbot/main.py", line 882, in main
    return config.func(config, plugins)
  File "/opt/letsencrypt/local/lib/python2.7/site-packages/certbot/main.py", line 658, in obtain_cert
    domains, certname = _find_domains_or_certname(config, installer)
  File "/opt/letsencrypt/local/lib/python2.7/site-packages/certbot/main.py", line 300, in _find_domains_or_certname
    domains = display_ops.choose_names(installer)
  File "/opt/letsencrypt/local/lib/python2.7/site-packages/certbot/display/ops.py", line 104, in choose_names
    domains = list(installer.get_all_names())
  File "/opt/letsencrypt/local/lib/python2.7/site-packages/certbot_nginx/configurator.py", line 389, in get_all_names
    for vhost in self.parser.get_vhosts():
  File "/opt/letsencrypt/local/lib/python2.7/site-packages/certbot_nginx/parser.py", line 141, in get_vhosts
    parsed_server = _parse_server_raw(server)
  File "/opt/letsencrypt/local/lib/python2.7/site-packages/certbot_nginx/parser.py", line 590, in _parse_server_raw
    if addr.ssl:
AttributeError: 'NoneType' object has no attribute 'ssl'

An unexpected error occurred:
AttributeError: 'NoneType' object has no attribute 'ssl'
Please see the logfiles in /var/log/letsencrypt for more details.
```

## Nginx conf
### example.com.conf
```
server {
   root /var/www/vhosts/example.com;
   server_name example.com;
   listen 80;
   index       index.php index.html index.htm;
   ....
}
```

### example.com.backend.conf
```
server {
   root /var/www/vhosts/example.com;
   server_name example.com;
   index       index.php index.html index.htm;
   listen      unix:/var/run/nginx-backend.sock default;
   ....
}
```


Discussion:
Weird, what OS are you running? What version?
What version of Certbot are you running and how did you install it?

@ohemorange you know more about nginx than I do - want to help?

Resolving patch:
diff --git a/certbot-nginx/certbot_nginx/parser.py b/certbot-nginx/certbot_nginx/parser.py
--- a/certbot-nginx/certbot_nginx/parser.py
+++ b/certbot-nginx/certbot_nginx/parser.py
@@ -586,9 +586,10 @@ def _parse_server_raw(server):
             continue
         if directive[0] == 'listen':
             addr = obj.Addr.fromstring(directive[1])
-            parsed_server['addrs'].add(addr)
-            if addr.ssl:
-                parsed_server['ssl'] = True
+            if addr:
+                parsed_server['addrs'].add(addr)
+                if addr.ssl:
+                    parsed_server['ssl'] = True
         elif directive[0] == 'server_name':
             parsed_server['names'].update(
                 _get_servernames(directive[1]))


Test patch:
diff --git a/certbot-nginx/certbot_nginx/tests/parser_test.py b/certbot-nginx/certbot_nginx/tests/parser_test.py
--- a/certbot-nginx/certbot_nginx/tests/parser_test.py
+++ b/certbot-nginx/certbot_nginx/tests/parser_test.py
@@ -323,6 +323,12 @@ def test_parse_server_raw_ssl(self):
         ])
         self.assertTrue(server['ssl'])
 
+    def test_parse_server_raw_unix(self):
+        server = parser._parse_server_raw([ #pylint: disable=protected-access
+            ['listen', 'unix:/var/run/nginx.sock']
+        ])
+        self.assertEqual(len(server['addrs']), 0)
+
     def test_parse_server_global_ssl_applied(self):
         nparser = parser.NginxParser(self.config_path, self.ssl_options)
         server = nparser.parse_server([